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