162 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9//===----------------------------------------------------------------------===//10 11#include "polly/CodeGen/RuntimeDebugBuilder.h"12#include "llvm/IR/Module.h"13#include <string>14#include <vector>15 16using namespace llvm;17using namespace polly;18 19llvm::Value *RuntimeDebugBuilder::getPrintableString(PollyIRBuilder &Builder,20 llvm::StringRef Str) {21 // FIXME: addressspace(4) is a marker for a string (for the %s conversion22 // specifier) but should be using the default address space. This only works23 // because CPU backends typically ignore the address space. For constant24 // strings as returned by getPrintableString, the format string should instead25 // directly spell out the string.26 return Builder.CreateGlobalString(Str, "", 4);27}28 29Function *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 44void RuntimeDebugBuilder::createPrinter(PollyIRBuilder &Builder,45 ArrayRef<Value *> Values) {46 createCPUPrinterT(Builder, Values);47}48 49bool 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 62static std::tuple<std::string, std::vector<Value *>>63prepareValuesForPrinting(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 else77 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 else96 FormatString += "%s";97 98 ValuesToPrint.push_back(Val);99 }100 101 return std::make_tuple(FormatString, ValuesToPrint);102}103 104void 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 117Function *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 131void 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 142void 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 NULL157 // pointer, the type we point to does conceptually not matter. However, if158 // fflush is already declared in this translation unit, we use the very same159 // type to ensure that LLVM does not complain about mismatching types.160 Builder.CreateCall(F, Constant::getNullValue(F->arg_begin()->getType()));161}162