brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.3 KiB · 5355fe2 Raw
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