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