brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.7 KiB · d6581b2 Raw
163 lines · cpp
1//===-- SPIRVAPI.cpp - SPIR-V Backend API ---------------------*- C++ -*---===//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#include "SPIRVCommandLine.h"10#include "SPIRVSubtarget.h"11#include "SPIRVTargetMachine.h"12#include "llvm/Analysis/TargetLibraryInfo.h"13#include "llvm/CodeGen/CommandFlags.h"14#include "llvm/CodeGen/MachineModuleInfo.h"15#include "llvm/CodeGen/TargetPassConfig.h"16#include "llvm/CodeGen/TargetSubtargetInfo.h"17#include "llvm/IR/DataLayout.h"18#include "llvm/IR/LLVMContext.h"19#include "llvm/IR/LegacyPassManager.h"20#include "llvm/IR/Module.h"21#include "llvm/IR/Verifier.h"22#include "llvm/MC/TargetRegistry.h"23#include "llvm/Pass.h"24#include "llvm/Support/TargetSelect.h"25#include "llvm/Target/TargetLoweringObjectFile.h"26#include "llvm/Target/TargetMachine.h"27#include "llvm/TargetParser/SubtargetFeature.h"28#include "llvm/TargetParser/Triple.h"29#include <optional>30#include <string>31#include <vector>32 33using namespace llvm;34 35namespace {36 37std::once_flag InitOnceFlag;38void InitializeSPIRVTarget() {39  std::call_once(InitOnceFlag, []() {40    LLVMInitializeSPIRVTargetInfo();41    LLVMInitializeSPIRVTarget();42    LLVMInitializeSPIRVTargetMC();43    LLVMInitializeSPIRVAsmPrinter();44  });45}46} // namespace47 48namespace llvm {49 50// The goal of this function is to facilitate integration of SPIRV Backend into51// tools and libraries by means of exposing an API call that translate LLVM52// module to SPIR-V and write results into a string as binary SPIR-V output,53// providing diagnostics on fail and means of configuring translation.54extern "C" LLVM_EXTERNAL_VISIBILITY bool55SPIRVTranslate(Module *M, std::string &SpirvObj, std::string &ErrMsg,56               const std::vector<std::string> &AllowExtNames,57               llvm::CodeGenOptLevel OLevel, Triple TargetTriple) {58  // Fallbacks for option values.59  static const std::string DefaultTriple = "spirv64-unknown-unknown";60  static const std::string DefaultMArch = "";61 62  std::set<SPIRV::Extension::Extension> AllowedExtIds;63  StringRef UnknownExt =64      SPIRVExtensionsParser::checkExtensions(AllowExtNames, AllowedExtIds);65  if (!UnknownExt.empty()) {66    ErrMsg = "Unknown SPIR-V extension: " + UnknownExt.str();67    return false;68  }69 70  // SPIR-V-specific target initialization.71  InitializeSPIRVTarget();72 73  if (TargetTriple.getTriple().empty()) {74    TargetTriple.setTriple(DefaultTriple);75    M->setTargetTriple(TargetTriple);76  }77  const Target *TheTarget =78      TargetRegistry::lookupTarget(DefaultMArch, TargetTriple, ErrMsg);79  if (!TheTarget)80    return false;81 82  // A call to codegen::InitTargetOptionsFromCodeGenFlags(TargetTriple)83  // hits the following assertion: llvm/lib/CodeGen/CommandFlags.cpp:78:84  // llvm::FPOpFusion::FPOpFusionMode llvm::codegen::getFuseFPOps(): Assertion85  // `FuseFPOpsView && "RegisterCodeGenFlags not created."' failed.86  TargetOptions Options;87  std::optional<Reloc::Model> RM;88  std::optional<CodeModel::Model> CM;89  std::unique_ptr<TargetMachine> Target(TheTarget->createTargetMachine(90      TargetTriple, "", "", Options, RM, CM, OLevel));91  if (!Target) {92    ErrMsg = "Could not allocate target machine!";93    return false;94  }95 96  // Set available extensions.97  SPIRVTargetMachine *STM = static_cast<SPIRVTargetMachine *>(Target.get());98  const_cast<SPIRVSubtarget *>(STM->getSubtargetImpl())99      ->initAvailableExtensions(AllowedExtIds);100 101  if (M->getCodeModel())102    Target->setCodeModel(*M->getCodeModel());103 104  std::string DLStr = M->getDataLayoutStr();105  Expected<DataLayout> MaybeDL = DataLayout::parse(106      DLStr.empty() ? Target->createDataLayout().getStringRepresentation()107                    : DLStr);108  if (!MaybeDL) {109    ErrMsg = toString(MaybeDL.takeError());110    return false;111  }112  M->setDataLayout(MaybeDL.get());113 114  TargetLibraryInfoImpl TLII(M->getTargetTriple());115  legacy::PassManager PM;116  PM.add(new TargetLibraryInfoWrapperPass(TLII));117  std::unique_ptr<MachineModuleInfoWrapperPass> MMIWP(118      new MachineModuleInfoWrapperPass(Target.get()));119  Target->getObjFileLowering()->Initialize(MMIWP->getMMI().getContext(),120                                           *Target);121 122  SmallString<4096> OutBuffer;123  raw_svector_ostream OutStream(OutBuffer);124  if (Target->addPassesToEmitFile(PM, OutStream, nullptr,125                                  CodeGenFileType::ObjectFile)) {126    ErrMsg = "Target machine cannot emit a file of this type";127    return false;128  }129 130  PM.run(*M);131  SpirvObj = OutBuffer.str();132 133  return true;134}135 136// TODO: Remove this wrapper after existing clients switch into a newer137// implementation of SPIRVTranslate().138extern "C" LLVM_EXTERNAL_VISIBILITY bool139SPIRVTranslateModule(Module *M, std::string &SpirvObj, std::string &ErrMsg,140                     const std::vector<std::string> &AllowExtNames,141                     const std::vector<std::string> &Opts) {142  // optional: Opts[0] is a string representation of Triple,143  // take Module triple otherwise144  Triple TargetTriple = Opts.empty() || Opts[0].empty()145                            ? M->getTargetTriple()146                            : Triple(Triple::normalize(Opts[0]));147  // optional: Opts[1] is a string representation of CodeGenOptLevel,148  // no optimization otherwise149  llvm::CodeGenOptLevel OLevel = CodeGenOptLevel::None;150  if (Opts.size() > 1 && !Opts[1].empty()) {151    if (auto Level = CodeGenOpt::parseLevel(Opts[1][0])) {152      OLevel = *Level;153    } else {154      ErrMsg = "Invalid optimization level!";155      return false;156    }157  }158  return SPIRVTranslate(M, SpirvObj, ErrMsg, AllowExtNames, OLevel,159                        std::move(TargetTriple));160}161 162} // namespace llvm163