1 //===--- RuntimeDebugBuilder.cpp - Helper to insert prints into LLVM-IR ---===//
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
7 //===----------------------------------------------------------------------===//
9 //===----------------------------------------------------------------------===//
11 #include "polly/CodeGen/RuntimeDebugBuilder.h"
12 #include "llvm/IR/Module.h"
17 using namespace polly
;
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
.CreateGlobalStringPtr(Str
, "", 4);
29 Function
*RuntimeDebugBuilder::getVPrintF(PollyIRBuilder
&Builder
) {
30 Module
*M
= Builder
.GetInsertBlock()->getParent()->getParent();
31 const char *Name
= "vprintf";
32 Function
*F
= M
->getFunction(Name
);
35 GlobalValue::LinkageTypes Linkage
= Function::ExternalLinkage
;
36 FunctionType
*Ty
= FunctionType::get(
37 Builder
.getInt32Ty(), {Builder
.getInt8PtrTy(), Builder
.getInt8PtrTy()},
39 F
= Function::Create(Ty
, Linkage
, Name
, M
);
45 void RuntimeDebugBuilder::createPrinter(PollyIRBuilder
&Builder
,
46 ArrayRef
<Value
*> Values
) {
47 createCPUPrinterT(Builder
, Values
);
50 bool RuntimeDebugBuilder::isPrintable(Type
*Ty
) {
51 if (Ty
->isFloatingPointTy())
54 if (Ty
->isIntegerTy())
55 return Ty
->getIntegerBitWidth() <= 64;
57 if (isa
<PointerType
>(Ty
))
63 static std::tuple
<std::string
, std::vector
<Value
*>>
64 prepareValuesForPrinting(PollyIRBuilder
&Builder
, ArrayRef
<Value
*> Values
) {
65 std::string FormatString
;
66 std::vector
<Value
*> ValuesToPrint
;
68 for (auto Val
: Values
) {
69 Type
*Ty
= Val
->getType();
71 if (Ty
->isFloatingPointTy()) {
72 if (!Ty
->isDoubleTy())
73 Val
= Builder
.CreateFPExt(Val
, Builder
.getDoubleTy());
74 } else if (Ty
->isIntegerTy()) {
75 if (Ty
->getIntegerBitWidth() < 64)
76 Val
= Builder
.CreateSExt(Val
, Builder
.getInt64Ty());
78 assert(Ty
->getIntegerBitWidth() &&
79 "Integer types larger 64 bit not supported");
80 } else if (isa
<PointerType
>(Ty
)) {
81 if (Ty
== Builder
.getInt8PtrTy(4)) {
82 Val
= Builder
.CreateGEP(Builder
.getInt8Ty(), Val
, Builder
.getInt64(0));
84 Val
= Builder
.CreatePtrToInt(Val
, Builder
.getInt64Ty());
87 llvm_unreachable("Unknown type");
92 if (Ty
->isFloatingPointTy())
94 else if (Ty
->isIntegerTy())
95 FormatString
+= "%ld";
99 ValuesToPrint
.push_back(Val
);
102 return std::make_tuple(FormatString
, ValuesToPrint
);
105 void RuntimeDebugBuilder::createCPUPrinterT(PollyIRBuilder
&Builder
,
106 ArrayRef
<Value
*> Values
) {
108 std::string FormatString
;
109 std::vector
<Value
*> ValuesToPrint
;
111 std::tie(FormatString
, ValuesToPrint
) =
112 prepareValuesForPrinting(Builder
, Values
);
114 createPrintF(Builder
, FormatString
, ValuesToPrint
);
115 createFlush(Builder
);
118 Function
*RuntimeDebugBuilder::getPrintF(PollyIRBuilder
&Builder
) {
119 Module
*M
= Builder
.GetInsertBlock()->getParent()->getParent();
120 const char *Name
= "printf";
121 Function
*F
= M
->getFunction(Name
);
124 GlobalValue::LinkageTypes Linkage
= Function::ExternalLinkage
;
125 FunctionType
*Ty
= FunctionType::get(Builder
.getInt32Ty(), true);
126 F
= Function::Create(Ty
, Linkage
, Name
, M
);
132 void RuntimeDebugBuilder::createPrintF(PollyIRBuilder
&Builder
,
134 ArrayRef
<Value
*> Values
) {
135 Value
*FormatString
= Builder
.CreateGlobalStringPtr(Format
);
136 std::vector
<Value
*> Arguments
;
138 Arguments
.push_back(FormatString
);
139 Arguments
.insert(Arguments
.end(), Values
.begin(), Values
.end());
140 Builder
.CreateCall(getPrintF(Builder
), Arguments
);
143 void RuntimeDebugBuilder::createFlush(PollyIRBuilder
&Builder
) {
144 Module
*M
= Builder
.GetInsertBlock()->getParent()->getParent();
145 const char *Name
= "fflush";
146 Function
*F
= M
->getFunction(Name
);
149 GlobalValue::LinkageTypes Linkage
= Function::ExternalLinkage
;
151 FunctionType::get(Builder
.getInt32Ty(), Builder
.getInt8PtrTy(), false);
152 F
= Function::Create(Ty
, Linkage
, Name
, M
);
155 // fflush(NULL) flushes _all_ open output streams.
157 // fflush is declared as 'int fflush(FILE *stream)'. As we only pass on a NULL
158 // pointer, the type we point to does conceptually not matter. However, if
159 // fflush is already declared in this translation unit, we use the very same
160 // type to ensure that LLVM does not complain about mismatching types.
161 Builder
.CreateCall(F
, Constant::getNullValue(F
->arg_begin()->getType()));