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 
14 #include "llvm/IR/Module.h"
15 
16 using namespace llvm;
17 using namespace polly;
18 
19 Function *RuntimeDebugBuilder::getPrintF(PollyIRBuilder &Builder) {
20   Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21   const char *Name = "printf";
22   Function *F = M->getFunction(Name);
23 
24   if (!F) {
25     GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
26     FunctionType *Ty =
27         FunctionType::get(Builder.getInt32Ty(), Builder.getInt8PtrTy(), true);
28     F = Function::Create(Ty, Linkage, Name, M);
29   }
30 
31   return F;
32 }
33 
34 void RuntimeDebugBuilder::createFlush(PollyIRBuilder &Builder) {
35   Module *M = Builder.GetInsertBlock()->getParent()->getParent();
36   const char *Name = "fflush";
37   Function *F = M->getFunction(Name);
38 
39   if (!F) {
40     GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
41     FunctionType *Ty =
42         FunctionType::get(Builder.getInt32Ty(), Builder.getInt8PtrTy(), false);
43     F = Function::Create(Ty, Linkage, Name, M);
44   }
45 
46   // fflush(NULL) flushes _all_ open output streams.
47   //
48   // fflush is declared as 'int fflush(FILE *stream)'. As we only pass on a NULL
49   // pointer, the type we point to does conceptually not matter. However, if
50   // fflush is already declared in this translation unit, we use the very same
51   // type to ensure that LLVM does not complain about mismatching types.
52   Builder.CreateCall(F, Constant::getNullValue(F->arg_begin()->getType()));
53 }
54 
55 void RuntimeDebugBuilder::createStrPrinter(PollyIRBuilder &Builder,
56                                            const std::string &String) {
57   Value *StringValue = Builder.CreateGlobalStringPtr(String);
58   Builder.CreateCall(getPrintF(Builder), StringValue);
59 
60   createFlush(Builder);
61 }
62 
63 void RuntimeDebugBuilder::createValuePrinter(PollyIRBuilder &Builder,
64                                              Value *V) {
65   const char *Format = nullptr;
66 
67   Type *Ty = V->getType();
68   if (Ty->isIntegerTy())
69     Format = "%ld";
70   else if (Ty->isFloatingPointTy())
71     Format = "%lf";
72   else if (Ty->isPointerTy())
73     Format = "%p";
74 
75   assert(Format && Ty->getPrimitiveSizeInBits() <= 64 && "Bad type to print.");
76 
77   Value *FormatString = Builder.CreateGlobalStringPtr(Format);
78   Builder.CreateCall2(getPrintF(Builder), FormatString, V);
79   createFlush(Builder);
80 }
81