LLVM 20.0.0git
SPIRVAPI.cpp
Go to the documentation of this file.
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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "SPIRVCommandLine.h"
10#include "SPIRVSubtarget.h"
17#include "llvm/IR/DataLayout.h"
18#include "llvm/IR/LLVMContext.h"
20#include "llvm/IR/Module.h"
21#include "llvm/IR/Verifier.h"
25#include "llvm/Pass.h"
34#include <optional>
35#include <string>
36#include <utility>
37#include <vector>
38
39using namespace llvm;
40
41namespace {
42
43// Mimic limited number of command line flags from llc to provide a better
44// user experience when passing options into the translate API call.
45static cl::opt<char> SpvOptLevel(" O", cl::Hidden, cl::Prefix, cl::init('0'));
46static cl::opt<std::string> SpvTargetTriple(" mtriple", cl::Hidden,
47 cl::init(""));
48
49// Utility to accept options in a command line style.
50void parseSPIRVCommandLineOptions(const std::vector<std::string> &Options,
51 raw_ostream *Errs) {
52 static constexpr const char *Origin = "SPIRVTranslateModule";
53 if (!Options.empty()) {
54 std::vector<const char *> Argv(1, Origin);
55 for (const auto &Arg : Options)
56 Argv.push_back(Arg.c_str());
57 cl::ParseCommandLineOptions(Argv.size(), Argv.data(), Origin, Errs);
58 }
59}
60
61std::once_flag InitOnceFlag;
62void InitializeSPIRVTarget() {
63 std::call_once(InitOnceFlag, []() {
68 });
69}
70} // namespace
71
72namespace llvm {
73
74// The goal of this function is to facilitate integration of SPIRV Backend into
75// tools and libraries by means of exposing an API call that translate LLVM
76// module to SPIR-V and write results into a string as binary SPIR-V output,
77// providing diagnostics on fail and means of configuring translation in a style
78// of command line options.
79extern "C" LLVM_EXTERNAL_VISIBILITY bool
80SPIRVTranslateModule(Module *M, std::string &SpirvObj, std::string &ErrMsg,
81 const std::vector<std::string> &AllowExtNames,
82 const std::vector<std::string> &Opts) {
83 // Fallbacks for option values.
84 static const std::string DefaultTriple = "spirv64-unknown-unknown";
85 static const std::string DefaultMArch = "";
86
87 // Parse Opts as if it'd be command line arguments.
88 std::string Errors;
89 raw_string_ostream ErrorStream(Errors);
90 parseSPIRVCommandLineOptions(Opts, &ErrorStream);
91 if (!Errors.empty()) {
92 ErrMsg = Errors;
93 return false;
94 }
95
97 if (auto Level = CodeGenOpt::parseLevel(SpvOptLevel)) {
98 OLevel = *Level;
99 } else {
100 ErrMsg = "Invalid optimization level!";
101 return false;
102 }
103
104 // Overrides/ammends `-spirv-ext` command line switch (if present) by the
105 // explicit list of allowed SPIR-V extensions.
106 std::set<SPIRV::Extension::Extension> AllowedExtIds;
107 StringRef UnknownExt =
108 SPIRVExtensionsParser::checkExtensions(AllowExtNames, AllowedExtIds);
109 if (!UnknownExt.empty()) {
110 ErrMsg = "Unknown SPIR-V extension: " + UnknownExt.str();
111 return false;
112 }
114
115 // SPIR-V-specific target initialization.
116 InitializeSPIRVTarget();
117
118 Triple TargetTriple(SpvTargetTriple.empty()
119 ? M->getTargetTriple()
120 : Triple::normalize(SpvTargetTriple));
121 if (TargetTriple.getTriple().empty()) {
122 TargetTriple.setTriple(DefaultTriple);
123 M->setTargetTriple(DefaultTriple);
124 }
125 const Target *TheTarget =
126 TargetRegistry::lookupTarget(DefaultMArch, TargetTriple, ErrMsg);
127 if (!TheTarget)
128 return false;
129
130 // A call to codegen::InitTargetOptionsFromCodeGenFlags(TargetTriple)
131 // hits the following assertion: llvm/lib/CodeGen/CommandFlags.cpp:78:
132 // llvm::FPOpFusion::FPOpFusionMode llvm::codegen::getFuseFPOps(): Assertion
133 // `FuseFPOpsView && "RegisterCodeGenFlags not created."' failed.
135 std::optional<Reloc::Model> RM;
136 std::optional<CodeModel::Model> CM;
137 std::unique_ptr<TargetMachine> Target =
138 std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(
139 TargetTriple.getTriple(), "", "", Options, RM, CM, OLevel));
140 if (!Target) {
141 ErrMsg = "Could not allocate target machine!";
142 return false;
143 }
144
145 if (M->getCodeModel())
146 Target->setCodeModel(*M->getCodeModel());
147
148 std::string DLStr = M->getDataLayoutStr();
150 DLStr.empty() ? Target->createDataLayout().getStringRepresentation()
151 : DLStr);
152 if (!MaybeDL) {
153 ErrMsg = toString(MaybeDL.takeError());
154 return false;
155 }
156 M->setDataLayout(MaybeDL.get());
157
158 TargetLibraryInfoImpl TLII(Triple(M->getTargetTriple()));
160 PM.add(new TargetLibraryInfoWrapperPass(TLII));
163 const_cast<TargetLoweringObjectFile *>(Target->getObjFileLowering())
164 ->Initialize(MMIWP->getMMI().getContext(), *Target);
165
166 SmallString<4096> OutBuffer;
167 raw_svector_ostream OutStream(OutBuffer);
168 if (Target->addPassesToEmitFile(PM, OutStream, nullptr,
170 ErrMsg = "Target machine cannot emit a file of this type";
171 return false;
172 }
173
174 PM.run(*M);
175 SpirvObj = OutBuffer.str();
176
177 return true;
178}
179
180} // namespace llvm
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:128
Module.h This file contains the declarations for the Module class.
static LVOptions Options
Definition: LVOptions.cpp:25
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSPIRVAsmPrinter()
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSPIRVTargetMC()
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSPIRVTargetInfo()
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSPIRVTarget()
Target-Independent Code Generator Pass Configuration Options pass.
static Expected< DataLayout > parse(StringRef LayoutString)
Parse a data layout string and return the layout.
Definition: DataLayout.cpp:264
Tagged union holding either a T or a Error.
Definition: Error.h:481
Error takeError()
Take ownership of the stored error.
Definition: Error.h:608
reference get()
Returns a reference to the stored T value.
Definition: Error.h:578
const MCContext & getContext() const
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
static void addExtensionsToClOpt(const std::set< SPIRV::Extension::Extension > &AllowList)
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
StringRef str() const
Explicit conversion to StringRef.
Definition: SmallString.h:254
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:229
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:147
Implementation of the target library information.
Target - Wrapper for Target specific information.
TargetMachine * createTargetMachine(StringRef TT, StringRef CPU, StringRef Features, const TargetOptions &Options, std::optional< Reloc::Model > RM, std::optional< CodeModel::Model > CM=std::nullopt, CodeGenOptLevel OL=CodeGenOptLevel::Default, bool JIT=false) const
createTargetMachine - Create a target specific machine implementation for the specified Triple.
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
std::string normalize() const
Return the normalized form of this triple's string.
Definition: Triple.h:376
void setTriple(const Twine &Str)
Set all components to the new triple Str.
Definition: Triple.cpp:1544
const std::string & getTriple() const
Definition: Triple.h:452
PassManager manages ModulePassManagers.
void add(Pass *P) override
Add a pass to the queue of passes to run.
bool run(Module &M)
run - Execute all of the passes scheduled for execution.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:661
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:691
std::optional< CodeGenOptLevel > parseLevel(char C)
Parse C as a single digit integer and get matching CodeGenLevel.
Definition: CodeGen.h:73
bool ParseCommandLineOptions(int argc, const char *const *argv, StringRef Overview="", raw_ostream *Errs=nullptr, const char *EnvVar=nullptr, bool LongOptionsUseDoubleDash=false)
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:443
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
CodeGenOptLevel
Code generation optimization level.
Definition: CodeGen.h:54
LLVM_EXTERNAL_VISIBILITY bool SPIRVTranslateModule(Module *M, std::string &SpirvObj, std::string &ErrMsg, const std::vector< std::string > &AllowExtNames, const std::vector< std::string > &Opts)
Definition: SPIRVAPI.cpp:80
const char * toString(DWARFSectionKind Kind)
static llvm::StringRef checkExtensions(const std::vector< std::string > &ExtNames, std::set< SPIRV::Extension::Extension > &AllowedExtensions)
Validates and converts extension names into internal enum values.
static const Target * lookupTarget(StringRef Triple, std::string &Error)
lookupTarget - Lookup a target based on a target triple.