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