1 //===--- RuntimeDebugBuilder.cpp - 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 #include "polly/CodeGen/RuntimeDebugBuilder.h"
13 #include "llvm/IR/Module.h"
14 #include "llvm/Support/Debug.h"
15 #include <string>
16 #include <vector>
17 
18 using namespace llvm;
19 using namespace polly;
20 
21 Function *RuntimeDebugBuilder::getVPrintF(PollyIRBuilder &Builder) {
22   Module *M = Builder.GetInsertBlock()->getParent()->getParent();
23   const char *Name = "vprintf";
24   Function *F = M->getFunction(Name);
25 
26   if (!F) {
27     GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
28     FunctionType *Ty = FunctionType::get(
29         Builder.getInt32Ty(), {Builder.getInt8PtrTy(), Builder.getInt8PtrTy()},
30         false);
31     F = Function::Create(Ty, Linkage, Name, M);
32   }
33 
34   return F;
35 }
36 
37 Function *RuntimeDebugBuilder::getAddressSpaceCast(PollyIRBuilder &Builder,
38                                                    unsigned Src, unsigned Dst,
39                                                    unsigned SrcBits,
40                                                    unsigned DstBits) {
41   Module *M = Builder.GetInsertBlock()->getParent()->getParent();
42   auto Name = std::string("llvm.nvvm.ptr.constant.to.gen.p") +
43               std::to_string(Dst) + "i" + std::to_string(DstBits) + ".p" +
44               std::to_string(Src) + "i" + std::to_string(SrcBits);
45   Function *F = M->getFunction(Name);
46 
47   if (!F) {
48     GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
49     FunctionType *Ty = FunctionType::get(
50         PointerType::get(Builder.getIntNTy(DstBits), Dst),
51         PointerType::get(Builder.getIntNTy(SrcBits), Src), false);
52     F = Function::Create(Ty, Linkage, Name, M);
53   }
54 
55   return F;
56 }
57 
58 void RuntimeDebugBuilder::createGPUVAPrinter(PollyIRBuilder &Builder,
59                                              ArrayRef<Value *> Values) {
60   std::string str;
61 
62   // Allocate print buffer (assuming 2*32 bit per element)
63   auto T = ArrayType::get(Builder.getInt32Ty(), Values.size() * 2);
64   Value *Data = new AllocaInst(
65       T, "polly.vprint.buffer",
66       Builder.GetInsertBlock()->getParent()->getEntryBlock().begin());
67 
68   auto *Zero = Builder.getInt64(0);
69   auto *DataPtr = Builder.CreateGEP(Data, {Zero, Zero});
70 
71   int Offset = 0;
72   for (auto Val : Values) {
73     auto Ptr = Builder.CreateGEP(DataPtr, {Builder.getInt64(Offset)});
74     Type *Ty = Val->getType();
75 
76     if (Ty->isFloatingPointTy()) {
77       if (!Ty->isDoubleTy()) {
78         Ty = Builder.getDoubleTy();
79         Val = Builder.CreateFPExt(Val, Ty);
80       }
81     } else if (Ty->isIntegerTy()) {
82       auto Int64Bitwidth = Builder.getInt64Ty()->getIntegerBitWidth();
83       assert(Ty->getIntegerBitWidth() <= Int64Bitwidth);
84       if (Ty->getIntegerBitWidth() < Int64Bitwidth) {
85         Ty = Builder.getInt64Ty();
86         Val = Builder.CreateSExt(Val, Ty);
87       }
88     } else {
89       // If it is not a number, it must be a string type.
90       Val = Builder.CreateGEP(Val, Builder.getInt64(0));
91       assert((Val->getType() == Builder.getInt8PtrTy(4)) &&
92              "Expected i8 ptr placed in constant address space");
93       auto F = RuntimeDebugBuilder::getAddressSpaceCast(Builder, 4, 0);
94       Val = Builder.CreateCall(F, Val);
95       Ty = Val->getType();
96     }
97 
98     Ptr = Builder.CreatePointerBitCastOrAddrSpaceCast(Ptr, Ty->getPointerTo(5));
99     Builder.CreateAlignedStore(Val, Ptr, 4);
100 
101     if (Ty->isFloatingPointTy())
102       str += "%f";
103     else if (Ty->isIntegerTy())
104       str += "%ld";
105     else
106       str += "%s";
107 
108     Offset += 2;
109   }
110 
111   Value *Format = Builder.CreateGlobalStringPtr(str, "polly.vprintf.buffer", 4);
112   Format = Builder.CreateCall(getAddressSpaceCast(Builder, 4, 0), Format);
113 
114   Data = Builder.CreateBitCast(Data, Builder.getInt8PtrTy());
115 
116   Builder.CreateCall(getVPrintF(Builder), {Format, Data});
117 }
118 
119 Function *RuntimeDebugBuilder::getPrintF(PollyIRBuilder &Builder) {
120   Module *M = Builder.GetInsertBlock()->getParent()->getParent();
121   const char *Name = "printf";
122   Function *F = M->getFunction(Name);
123 
124   if (!F) {
125     GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
126     FunctionType *Ty =
127         FunctionType::get(Builder.getInt32Ty(), Builder.getInt8PtrTy(), true);
128     F = Function::Create(Ty, Linkage, Name, M);
129   }
130 
131   return F;
132 }
133 
134 void RuntimeDebugBuilder::createFlush(PollyIRBuilder &Builder) {
135   Module *M = Builder.GetInsertBlock()->getParent()->getParent();
136   const char *Name = "fflush";
137   Function *F = M->getFunction(Name);
138 
139   if (!F) {
140     GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
141     FunctionType *Ty =
142         FunctionType::get(Builder.getInt32Ty(), Builder.getInt8PtrTy(), false);
143     F = Function::Create(Ty, Linkage, Name, M);
144   }
145 
146   // fflush(NULL) flushes _all_ open output streams.
147   //
148   // fflush is declared as 'int fflush(FILE *stream)'. As we only pass on a NULL
149   // pointer, the type we point to does conceptually not matter. However, if
150   // fflush is already declared in this translation unit, we use the very same
151   // type to ensure that LLVM does not complain about mismatching types.
152   Builder.CreateCall(F, Constant::getNullValue(F->arg_begin()->getType()));
153 }
154 
155 void RuntimeDebugBuilder::createStrPrinter(PollyIRBuilder &Builder,
156                                            const std::string &String) {
157   Value *StringValue = Builder.CreateGlobalStringPtr(String);
158   Builder.CreateCall(getPrintF(Builder), StringValue);
159 
160   createFlush(Builder);
161 }
162 
163 void RuntimeDebugBuilder::createValuePrinter(PollyIRBuilder &Builder,
164                                              Value *V) {
165   const char *Format = nullptr;
166 
167   Type *Ty = V->getType();
168   if (Ty->isIntegerTy())
169     Format = "%ld";
170   else if (Ty->isFloatingPointTy())
171     Format = "%lf";
172   else if (Ty->isPointerTy())
173     Format = "%p";
174 
175   assert(Format && Ty->getPrimitiveSizeInBits() <= 64 && "Bad type to print.");
176 
177   Value *FormatString = Builder.CreateGlobalStringPtr(Format);
178   Builder.CreateCall(getPrintF(Builder), {FormatString, V});
179   createFlush(Builder);
180 }
181