xref: /llvm-project/polly/lib/CodeGen/RuntimeDebugBuilder.cpp (revision ecb98f9fed65801d9ad2c138da7194496e18aeec)
1 //===--- RuntimeDebugBuilder.cpp - Helper to insert prints into LLVM-IR ---===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 //===----------------------------------------------------------------------===//
10 
11 #include "polly/CodeGen/RuntimeDebugBuilder.h"
12 #include "llvm/IR/Module.h"
13 #include <string>
14 #include <vector>
15 
16 using namespace llvm;
17 using namespace polly;
18 
19 llvm::Value *RuntimeDebugBuilder::getPrintableString(PollyIRBuilder &Builder,
20                                                      llvm::StringRef Str) {
21   // FIXME: addressspace(4) is a marker for a string (for the %s conversion
22   // specifier) but should be using the default address space. This only works
23   // because CPU backends typically ignore the address space. For constant
24   // strings as returned by getPrintableString, the format string should instead
25   // directly spell out the string.
26   return Builder.CreateGlobalString(Str, "", 4);
27 }
28 
29 Function *RuntimeDebugBuilder::getVPrintF(PollyIRBuilder &Builder) {
30   Module *M = Builder.GetInsertBlock()->getParent()->getParent();
31   const char *Name = "vprintf";
32   Function *F = M->getFunction(Name);
33 
34   if (!F) {
35     GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
36     FunctionType *Ty = FunctionType::get(
37         Builder.getInt32Ty(), {Builder.getPtrTy(), Builder.getPtrTy()}, false);
38     F = Function::Create(Ty, Linkage, Name, M);
39   }
40 
41   return F;
42 }
43 
44 void RuntimeDebugBuilder::createPrinter(PollyIRBuilder &Builder,
45                                         ArrayRef<Value *> Values) {
46   createCPUPrinterT(Builder, Values);
47 }
48 
49 bool RuntimeDebugBuilder::isPrintable(Type *Ty) {
50   if (Ty->isFloatingPointTy())
51     return true;
52 
53   if (Ty->isIntegerTy())
54     return Ty->getIntegerBitWidth() <= 64;
55 
56   if (isa<PointerType>(Ty))
57     return true;
58 
59   return false;
60 }
61 
62 static std::tuple<std::string, std::vector<Value *>>
63 prepareValuesForPrinting(PollyIRBuilder &Builder, ArrayRef<Value *> Values) {
64   std::string FormatString;
65   std::vector<Value *> ValuesToPrint;
66 
67   for (auto Val : Values) {
68     Type *Ty = Val->getType();
69 
70     if (Ty->isFloatingPointTy()) {
71       if (!Ty->isDoubleTy())
72         Val = Builder.CreateFPExt(Val, Builder.getDoubleTy());
73     } else if (Ty->isIntegerTy()) {
74       if (Ty->getIntegerBitWidth() < 64)
75         Val = Builder.CreateSExt(Val, Builder.getInt64Ty());
76       else
77         assert(Ty->getIntegerBitWidth() &&
78                "Integer types larger 64 bit not supported");
79     } else if (isa<PointerType>(Ty)) {
80       if (Ty == Builder.getPtrTy(4)) {
81         Val = Builder.CreateGEP(Builder.getInt8Ty(), Val, Builder.getInt64(0));
82       } else {
83         Val = Builder.CreatePtrToInt(Val, Builder.getInt64Ty());
84       }
85     } else {
86       llvm_unreachable("Unknown type");
87     }
88 
89     Ty = Val->getType();
90 
91     if (Ty->isFloatingPointTy())
92       FormatString += "%f";
93     else if (Ty->isIntegerTy())
94       FormatString += "%ld";
95     else
96       FormatString += "%s";
97 
98     ValuesToPrint.push_back(Val);
99   }
100 
101   return std::make_tuple(FormatString, ValuesToPrint);
102 }
103 
104 void RuntimeDebugBuilder::createCPUPrinterT(PollyIRBuilder &Builder,
105                                             ArrayRef<Value *> Values) {
106 
107   std::string FormatString;
108   std::vector<Value *> ValuesToPrint;
109 
110   std::tie(FormatString, ValuesToPrint) =
111       prepareValuesForPrinting(Builder, Values);
112 
113   createPrintF(Builder, FormatString, ValuesToPrint);
114   createFlush(Builder);
115 }
116 
117 Function *RuntimeDebugBuilder::getPrintF(PollyIRBuilder &Builder) {
118   Module *M = Builder.GetInsertBlock()->getParent()->getParent();
119   const char *Name = "printf";
120   Function *F = M->getFunction(Name);
121 
122   if (!F) {
123     GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
124     FunctionType *Ty = FunctionType::get(Builder.getInt32Ty(), true);
125     F = Function::Create(Ty, Linkage, Name, M);
126   }
127 
128   return F;
129 }
130 
131 void RuntimeDebugBuilder::createPrintF(PollyIRBuilder &Builder,
132                                        std::string Format,
133                                        ArrayRef<Value *> Values) {
134   Value *FormatString = Builder.CreateGlobalString(Format);
135   std::vector<Value *> Arguments;
136 
137   Arguments.push_back(FormatString);
138   Arguments.insert(Arguments.end(), Values.begin(), Values.end());
139   Builder.CreateCall(getPrintF(Builder), Arguments);
140 }
141 
142 void RuntimeDebugBuilder::createFlush(PollyIRBuilder &Builder) {
143   Module *M = Builder.GetInsertBlock()->getParent()->getParent();
144   const char *Name = "fflush";
145   Function *F = M->getFunction(Name);
146 
147   if (!F) {
148     GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
149     FunctionType *Ty =
150         FunctionType::get(Builder.getInt32Ty(), Builder.getPtrTy(), false);
151     F = Function::Create(Ty, Linkage, Name, M);
152   }
153 
154   // fflush(NULL) flushes _all_ open output streams.
155   //
156   // fflush is declared as 'int fflush(FILE *stream)'. As we only pass on a NULL
157   // pointer, the type we point to does conceptually not matter. However, if
158   // fflush is already declared in this translation unit, we use the very same
159   // type to ensure that LLVM does not complain about mismatching types.
160   Builder.CreateCall(F, Constant::getNullValue(F->arg_begin()->getType()));
161 }
162