1 //===--- RuntimeDebugBuilder.h --- Helper to insert prints into LLVM-IR ---===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 //===----------------------------------------------------------------------===// 11 12 #ifndef RUNTIME_DEBUG_BUILDER_H 13 #define RUNTIME_DEBUG_BUILDER_H 14 15 #include "polly/CodeGen/IRBuilder.h" 16 #include "llvm/ADT/ArrayRef.h" 17 #include "llvm/ADT/StringRef.h" 18 #include <vector> 19 20 namespace llvm { 21 class Value; 22 class Function; 23 } // namespace llvm 24 25 namespace polly { 26 27 /// Insert function calls that print certain LLVM values at run time. 28 /// 29 /// This class inserts libc function calls to print certain LLVM values at 30 /// run time. 31 struct RuntimeDebugBuilder { 32 33 /// Print a set of LLVM-IR Values or StringRefs via printf 34 /// 35 /// This function emits a call to printf that will print the given arguments. 36 /// It is useful for debugging CPU programs. All arguments given in this list 37 /// will be automatically concatenated and the resulting string will be 38 /// printed atomically. We also support ArrayRef arguments, which can be used 39 /// to provide of id values. 40 /// 41 /// @param Builder The builder used to emit the printer calls. 42 /// @param Args The list of values to print. 43 template <typename... Args> 44 static void createCPUPrinter(PollyIRBuilder &Builder, Args... args) { 45 std::vector<llvm::Value *> Vector; 46 createPrinter(Builder, /* CPU */ false, Vector, args...); 47 } 48 49 /// Print a set of LLVM-IR Values or StringRefs on an NVIDIA GPU. 50 /// 51 /// This function emits a call to vprintf that will print the given 52 /// arguments from within a kernel thread. It is useful for debugging 53 /// CUDA program kernels. All arguments given in this list will be 54 /// automatically concatenated and the resulting string will be printed 55 /// atomically. We also support ArrayRef arguments, which can be used to 56 /// provide for example a list of thread-id values. 57 /// 58 /// @param Builder The builder used to emit the printer calls. 59 /// @param Args The list of values to print. 60 template <typename... Args> 61 static void createGPUPrinter(PollyIRBuilder &Builder, Args... args) { 62 std::vector<llvm::Value *> Vector; 63 createPrinter(Builder, /* GPU */ true, Vector, args...); 64 } 65 66 private: 67 /// Handle Values. 68 template <typename... Args> 69 static void createPrinter(PollyIRBuilder &Builder, bool UseGPU, 70 std::vector<llvm::Value *> &Values, 71 llvm::Value *Value, Args... args) { 72 Values.push_back(Value); 73 createPrinter(Builder, UseGPU, Values, args...); 74 } 75 76 /// Handle StringRefs. 77 template <typename... Args> 78 static void createPrinter(PollyIRBuilder &Builder, bool UseGPU, 79 std::vector<llvm::Value *> &Values, 80 llvm::StringRef String, Args... args) { 81 Values.push_back(Builder.CreateGlobalStringPtr(String, "", 4)); 82 createPrinter(Builder, UseGPU, Values, args...); 83 } 84 85 /// Handle ArrayRefs. 86 template <typename... Args> 87 static void createPrinter(PollyIRBuilder &Builder, bool UseGPU, 88 std::vector<llvm::Value *> &Values, 89 llvm::ArrayRef<llvm::Value *> Array, Args... args) { 90 if (Array.size() >= 2) 91 createPrinter(Builder, Values, Array[0], " ", 92 llvm::ArrayRef<llvm::Value *>(&Array[1], Array.size() - 1), 93 args...); 94 else if (Array.size() == 1) 95 createPrinter(Builder, UseGPU, Values, Array[0], args...); 96 else 97 createPrinter(Builder, UseGPU, Values, args...); 98 } 99 100 /// Print a list of Values. 101 static void createPrinter(PollyIRBuilder &Builder, bool UseGPU, 102 llvm::ArrayRef<llvm::Value *> Values); 103 104 /// Print a list of Values on a GPU. 105 static void createGPUPrinterT(PollyIRBuilder &Builder, 106 llvm::ArrayRef<llvm::Value *> Values); 107 108 /// Print a list of Values on a CPU. 109 static void createCPUPrinterT(PollyIRBuilder &Builder, 110 llvm::ArrayRef<llvm::Value *> Values); 111 112 /// Get a reference to the 'printf' function. 113 /// 114 /// If the current module does not yet contain a reference to printf, we 115 /// insert a reference to it. Otherwise the existing reference is returned. 116 static llvm::Function *getPrintF(PollyIRBuilder &Builder); 117 118 /// Call printf 119 /// 120 /// @param Builder The builder used to insert the code. 121 /// @param Format The format string. 122 /// @param Values The set of values to print. 123 static void createPrintF(PollyIRBuilder &Builder, std::string Format, 124 llvm::ArrayRef<llvm::Value *> Values); 125 126 /// Get (and possibly insert) a vprintf declaration into the module. 127 static llvm::Function *getVPrintF(PollyIRBuilder &Builder); 128 129 /// Call fflush 130 /// 131 /// @parma Builder The builder used to insert the code. 132 static void createFlush(PollyIRBuilder &Builder); 133 134 /// Get (and possibly insert) a NVIDIA address space cast call. 135 static llvm::Function *getAddressSpaceCast(PollyIRBuilder &Builder, 136 unsigned Src, unsigned Dst, 137 unsigned SrcBits = 8, 138 unsigned DstBits = 8); 139 140 /// Get identifiers that describe the currently executed GPU thread. 141 /// 142 /// The result will be a vector that if passed to the GPU printer will result 143 /// into a string (initialized to values corresponding to the printing 144 /// thread): 145 /// 146 /// "> block-id: bidx bid1y bidz | thread-id: tidx tidy tidz " 147 static std::vector<llvm::Value *> 148 getGPUThreadIdentifiers(PollyIRBuilder &Builder); 149 }; 150 } // namespace polly 151 152 #endif 153