29 #include "llvm/Config/llvm-config.h"
30 #include "llvm/Support/FileSystem.h"
31 #include "llvm/Support/FileUtilities.h"
32 #include "llvm/Support/FormatVariadic.h"
33 #include "llvm/Support/MemoryBuffer.h"
34 #include "llvm/Support/Path.h"
35 #include "llvm/Support/Process.h"
36 #include "llvm/Support/Program.h"
37 #include "llvm/Support/TargetSelect.h"
38 #include "llvm/Support/Timer.h"
39 #include "llvm/Support/raw_ostream.h"
48 #ifndef __DEFAULT_CUDATOOLKIT_PATH__
49 #define __DEFAULT_CUDATOOLKIT_PATH__ ""
57 class NVVMTargetAttrImpl
58 :
public gpu::TargetAttrInterface::FallbackModel<NVVMTargetAttrImpl> {
60 std::optional<SmallVector<char, 0>>
74 NVVMTargetAttr::attachInterface<NVVMTargetAttrImpl>(*ctx);
87 if (
const char *var = std::getenv(
"CUDA_ROOT"))
89 if (
const char *var = std::getenv(
"CUDA_HOME"))
91 if (
const char *var = std::getenv(
"CUDA_PATH"))
99 : ModuleToObject(module, target.getTriple(), target.getChip(),
100 target.getFeatures(), target.getO(),
101 targetOptions.getInitialLlvmIRCallback(),
102 targetOptions.getLinkedLlvmIRCallback(),
103 targetOptions.getOptimizedLlvmIRCallback(),
104 targetOptions.getISACallback()),
105 target(target), toolkitPath(targetOptions.getToolkitPath()),
106 librariesToLink(targetOptions.getLibrariesToLink()) {
121 static llvm::once_flag initializeBackendOnce;
122 llvm::call_once(initializeBackendOnce, []() {
124 #if LLVM_HAS_NVPTX_TARGET
125 LLVMInitializeNVPTXTarget();
126 LLVMInitializeNVPTXTargetInfo();
127 LLVMInitializeNVPTXTargetMC();
128 LLVMInitializeNVPTXAsmPrinter();
143 #if MLIR_NVVM_EMBED_LIBDEVICE
154 resourceManager.getBlobManager().lookup(
"_mlir_embedded_libdevice");
168 type, resourceManager.insert(
"_mlir_embedded_libdevice",
169 std::move(unmanagedBlob))));
172 if (!pathRef.empty()) {
174 path.insert(path.begin(), pathRef.begin(), pathRef.end());
175 pathRef = StringRef(path.data(), path.size());
176 if (!llvm::sys::fs::is_directory(pathRef)) {
178 <<
" does not exist or is not a directory.\n";
181 llvm::sys::path::append(path,
"nvvm",
"libdevice",
"libdevice.10.bc");
182 pathRef = StringRef(path.data(), path.size());
183 if (!llvm::sys::fs::is_regular_file(pathRef)) {
185 <<
" does not exist or is not a file.\n";
194 std::optional<SmallVector<std::unique_ptr<llvm::Module>>>
200 return std::move(bcFiles);
206 NVPTXSerializer(
Operation &module, NVVMTargetAttr target,
210 gpu::GPUModuleOp getOperation();
213 std::optional<SmallVector<char, 0>>
214 compileToBinary(
const std::string &ptxCode);
217 std::optional<SmallVector<char, 0>>
218 compileToBinaryNVPTX(
const std::string &ptxCode);
222 std::optional<SmallVector<char, 0>>
223 moduleToObject(llvm::Module &llvmModule)
override;
228 std::optional<int64_t> getLLVMIRToISATimeInMs();
233 std::optional<int64_t> getISAToBinaryTimeInMs();
236 using TmpFile = std::pair<llvm::SmallString<128>, llvm::FileRemover>;
239 std::optional<TmpFile> createTemp(StringRef name, StringRef suffix);
246 std::optional<std::string> findTool(StringRef tool);
252 std::optional<int64_t> llvmToISATimeInMs;
255 std::optional<int64_t> isaToBinaryTimeInMs;
259 NVPTXSerializer::NVPTXSerializer(
Operation &module, NVVMTargetAttr target,
262 targetOptions(targetOptions), llvmToISATimeInMs(std::nullopt),
263 isaToBinaryTimeInMs(std::nullopt) {}
265 std::optional<NVPTXSerializer::TmpFile>
266 NVPTXSerializer::createTemp(StringRef name, StringRef suffix) {
269 llvm::sys::fs::createTemporaryFile(name, suffix, filename);
271 getOperation().emitError() <<
"Couldn't create the temp file: `" << filename
272 <<
"`, error message: " << ec.message();
275 return TmpFile(filename, llvm::FileRemover(filename.c_str()));
278 std::optional<int64_t> NVPTXSerializer::getLLVMIRToISATimeInMs() {
279 return llvmToISATimeInMs;
282 std::optional<int64_t> NVPTXSerializer::getISAToBinaryTimeInMs() {
283 return isaToBinaryTimeInMs;
286 gpu::GPUModuleOp NVPTXSerializer::getOperation() {
290 std::optional<std::string> NVPTXSerializer::findTool(StringRef tool) {
293 StringRef pathRef = targetOptions.getToolkitPath();
295 if (!pathRef.empty()) {
296 path.insert(path.begin(), pathRef.begin(), pathRef.end());
297 llvm::sys::path::append(path,
"bin", tool);
298 if (llvm::sys::fs::can_execute(path))
299 return StringRef(path.data(), path.size()).str();
303 if (std::optional<std::string> toolPath =
304 llvm::sys::Process::FindInEnvPath(
"PATH", tool))
310 if (!pathRef.empty()) {
311 path.insert(path.begin(), pathRef.begin(), pathRef.end());
312 llvm::sys::path::append(path,
"bin", tool);
313 if (llvm::sys::fs::can_execute(path))
314 return StringRef(path.data(), path.size()).str();
316 getOperation().emitError()
317 <<
"Couldn't find the `" << tool
318 <<
"` binary. Please specify the toolkit "
319 "path, add the compiler to $PATH, or set one of the environment "
320 "variables in `NVVM::getCUDAToolkitPath()`.";
325 template <
typename T>
328 if (!target.hasCmdOptions())
331 std::optional<mlir::NamedAttribute> cmdOptions = target.getCmdOptions();
332 for (
Attribute attr : cast<ArrayAttr>(cmdOptions->getValue())) {
333 if (
auto strAttr = dyn_cast<StringAttr>(attr)) {
334 if constexpr (std::is_same_v<T, StringRef>) {
335 ptxasArgs.push_back(strAttr.getValue());
336 }
else if constexpr (std::is_same_v<T, const char *>) {
337 ptxasArgs.push_back(strAttr.getValue().data());
345 std::optional<SmallVector<char, 0>>
346 NVPTXSerializer::compileToBinary(
const std::string &ptxCode) {
349 const bool createFatbin =
350 targetOptions.getCompilationTarget() == gpu::CompilationTarget::Fatbin;
353 std::optional<std::string> ptxasCompiler = findTool(
"ptxas");
356 std::optional<std::string> fatbinaryTool;
358 fatbinaryTool = findTool(
"fatbinary");
362 Location loc = getOperation().getLoc();
365 std::string basename =
366 llvm::formatv(
"mlir-{0}-{1}-{2}", getOperation().getNameAttr().getValue(),
367 getTarget().getTriple(), getTarget().getChip());
370 std::optional<TmpFile> ptxFile = createTemp(basename,
"ptx");
373 std::optional<TmpFile> logFile = createTemp(basename,
"log");
376 std::optional<TmpFile> binaryFile = createTemp(basename,
"bin");
381 std::string cubinFilename = (ptxFile->first +
".cubin").str();
382 cubinFile = TmpFile(cubinFilename, llvm::FileRemover(cubinFilename));
384 cubinFile.first = binaryFile->first;
390 llvm::raw_fd_ostream ptxStream(ptxFile->first, ec);
392 emitError(loc) <<
"Couldn't open the file: `" << ptxFile->first
393 <<
"`, error message: " << ec.message();
396 ptxStream << ptxCode;
397 if (ptxStream.has_error()) {
398 emitError(loc) <<
"An error occurred while writing the PTX to: `"
399 << ptxFile->first <<
"`.";
406 std::optional<StringRef> redirects[] = {
413 std::pair<llvm::BumpPtrAllocator, SmallVector<const char *>> cmdOpts =
414 targetOptions.tokenizeCmdOptions();
417 std::string optLevel = std::to_string(this->optLevel);
419 {StringRef(
"ptxas"), StringRef(
"-arch"), getTarget().getChip(),
420 StringRef(ptxFile->first), StringRef(
"-o"), StringRef(cubinFile.first),
421 "--opt-level", optLevel});
423 bool useFatbin32 =
false;
424 for (
const auto *cArg : cmdOpts.second) {
428 if (StringRef arg(cArg); arg !=
"-32")
429 ptxasArgs.push_back(arg);
438 StringRef chip = getTarget().getChip();
440 chip.consume_front(
"sm_"), chip.consume_front(
"compute_");
442 std::string cubinArg =
443 llvm::formatv(
"--image3=kind=elf,sm={0},file={1}", chip, cubinFile.first)
447 llvm::formatv(
"--image3=kind=ptx,sm={0},file={1}", chip, ptxFile->first)
450 useFatbin32 ?
"-32" :
"-64", cubinArg,
451 ptxArg,
"--create", binaryFile->first});
454 #define DEBUG_TYPE "serialize-to-binary"
456 llvm::dbgs() <<
"Tool invocation for module: "
457 << getOperation().getNameAttr() <<
"\n";
458 llvm::dbgs() <<
"ptxas executable:" << ptxasCompiler.value() <<
"\n";
459 llvm::interleave(ptxasArgs, llvm::dbgs(),
" ");
460 llvm::dbgs() <<
"\n";
462 llvm::interleave(fatbinArgs, llvm::dbgs(),
" ");
463 llvm::dbgs() <<
"\n";
472 if (message.empty()) {
473 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> toolStderr =
474 llvm::MemoryBuffer::getFile(logFile->first);
476 emitError(loc) << toolName <<
" invocation failed. Log:\n"
477 << toolStderr->get()->getBuffer();
479 emitError(loc) << toolName <<
" invocation failed.";
483 <<
" invocation failed, error message: " << message;
488 if (llvm::sys::ExecuteAndWait(ptxasCompiler.value(), ptxasArgs,
494 return emitLogError(
"`ptxas`");
495 #define DEBUG_TYPE "dump-sass"
497 std::optional<std::string> nvdisasm = findTool(
"nvdisasm");
499 {StringRef(
"nvdisasm"), StringRef(cubinFile.first)});
500 if (llvm::sys::ExecuteAndWait(nvdisasm.value(), nvdisasmArgs,
506 return emitLogError(
"`nvdisasm`");
507 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> logBuffer =
508 llvm::MemoryBuffer::getFile(logFile->first);
509 if (logBuffer && !(*logBuffer)->getBuffer().empty()) {
510 llvm::dbgs() <<
"Output:\n" << (*logBuffer)->getBuffer() <<
"\n";
511 llvm::dbgs().flush();
518 if (createFatbin && llvm::sys::ExecuteAndWait(*fatbinaryTool, fatbinArgs,
524 return emitLogError(
"`fatbinary`");
527 #define DEBUG_TYPE "serialize-to-binary"
529 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> logBuffer =
530 llvm::MemoryBuffer::getFile(logFile->first);
531 if (logBuffer && !(*logBuffer)->getBuffer().empty()) {
532 llvm::dbgs() <<
"Output:\n" << (*logBuffer)->getBuffer() <<
"\n";
533 llvm::dbgs().flush();
539 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> binaryBuffer =
540 llvm::MemoryBuffer::getFile(binaryFile->first);
542 emitError(loc) <<
"Couldn't open the file: `" << binaryFile->first
543 <<
"`, error message: " << binaryBuffer.getError().message();
546 StringRef fatbin = (*binaryBuffer)->getBuffer();
550 #if MLIR_ENABLE_NVPTXCOMPILER
551 #include "nvPTXCompiler.h"
553 #define RETURN_ON_NVPTXCOMPILER_ERROR(expr) \
555 if (auto status = (expr)) { \
556 emitError(loc) << llvm::Twine(#expr).concat(" failed with error code ") \
558 return std::nullopt; \
562 #include "nvFatbin.h"
564 #define RETURN_ON_NVFATBIN_ERROR(expr) \
566 auto result = (expr); \
567 if (result != nvFatbinResult::NVFATBIN_SUCCESS) { \
568 emitError(loc) << llvm::Twine(#expr).concat(" failed with error: ") \
569 << nvFatbinGetErrorString(result); \
570 return std::nullopt; \
574 std::optional<SmallVector<char, 0>>
575 NVPTXSerializer::compileToBinaryNVPTX(
const std::string &ptxCode) {
576 Location loc = getOperation().getLoc();
577 nvPTXCompilerHandle compiler =
nullptr;
578 nvPTXCompileResult status;
582 std::string optLevel = std::to_string(this->optLevel);
583 std::pair<llvm::BumpPtrAllocator, SmallVector<const char *>> cmdOpts =
584 targetOptions.tokenizeCmdOptions();
585 cmdOpts.second.append(
586 {
"-arch", getTarget().getChip().data(),
"--opt-level", optLevel.c_str()});
591 RETURN_ON_NVPTXCOMPILER_ERROR(
592 nvPTXCompilerCreate(&compiler, ptxCode.size(), ptxCode.c_str()));
595 status = nvPTXCompilerCompile(compiler, cmdOpts.second.size(),
596 cmdOpts.second.data());
599 if (status != NVPTXCOMPILE_SUCCESS) {
600 RETURN_ON_NVPTXCOMPILER_ERROR(
601 nvPTXCompilerGetErrorLogSize(compiler, &logSize));
604 RETURN_ON_NVPTXCOMPILER_ERROR(
605 nvPTXCompilerGetErrorLog(compiler, log.data()));
606 emitError(loc) <<
"NVPTX compiler invocation failed, error log: "
609 emitError(loc) <<
"NVPTX compiler invocation failed with error code: "
616 RETURN_ON_NVPTXCOMPILER_ERROR(
617 nvPTXCompilerGetCompiledProgramSize(compiler, &elfSize));
619 RETURN_ON_NVPTXCOMPILER_ERROR(
620 nvPTXCompilerGetCompiledProgram(compiler, (
void *)binary.data()));
623 #define DEBUG_TYPE "serialize-to-binary"
625 RETURN_ON_NVPTXCOMPILER_ERROR(
626 nvPTXCompilerGetInfoLogSize(compiler, &logSize));
629 RETURN_ON_NVPTXCOMPILER_ERROR(
630 nvPTXCompilerGetInfoLog(compiler, log.data()));
631 llvm::dbgs() <<
"NVPTX compiler invocation for module: "
632 << getOperation().getNameAttr() <<
"\n";
633 llvm::dbgs() <<
"Arguments: ";
634 llvm::interleave(cmdOpts.second, llvm::dbgs(),
" ");
635 llvm::dbgs() <<
"\nOutput\n" << log.data() <<
"\n";
636 llvm::dbgs().flush();
640 RETURN_ON_NVPTXCOMPILER_ERROR(nvPTXCompilerDestroy(&compiler));
642 if (targetOptions.getCompilationTarget() == gpu::CompilationTarget::Fatbin) {
643 bool useFatbin32 = llvm::any_of(cmdOpts.second, [](
const char *option) {
644 return llvm::StringRef(option) ==
"-32";
647 const char *cubinOpts[1] = {useFatbin32 ?
"-32" :
"-64"};
648 nvFatbinHandle handle;
650 auto chip = getTarget().getChip();
651 chip.consume_front(
"sm_");
653 RETURN_ON_NVFATBIN_ERROR(nvFatbinCreate(&handle, cubinOpts, 1));
654 RETURN_ON_NVFATBIN_ERROR(nvFatbinAddCubin(
655 handle, binary.data(), binary.size(), chip.data(),
nullptr));
656 RETURN_ON_NVFATBIN_ERROR(nvFatbinAddPTX(
657 handle, ptxCode.data(), ptxCode.size(), chip.data(),
nullptr,
nullptr));
660 RETURN_ON_NVFATBIN_ERROR(nvFatbinSize(handle, &fatbinSize));
662 RETURN_ON_NVFATBIN_ERROR(nvFatbinGet(handle, (
void *)fatbin.data()));
663 RETURN_ON_NVFATBIN_ERROR(nvFatbinDestroy(&handle));
671 std::optional<SmallVector<char, 0>>
672 NVPTXSerializer::moduleToObject(llvm::Module &llvmModule) {
673 llvm::Timer moduleToObjectTimer(
674 "moduleToObjectTimer",
675 "Timer for perf llvm-ir -> isa and isa -> binary.");
677 #define DEBUG_TYPE "serialize-to-llvm"
679 llvm::dbgs() <<
"LLVM IR for module: " << getOperation().getNameAttr()
681 llvm::dbgs() << llvmModule <<
"\n";
682 llvm::dbgs().flush();
685 if (targetOptions.getCompilationTarget() == gpu::CompilationTarget::Offload)
688 #if !LLVM_HAS_NVPTX_TARGET
689 getOperation()->emitError(
690 "The `NVPTX` target was not built. Please enable it when building LLVM.");
695 std::optional<llvm::TargetMachine *> targetMachine =
696 getOrCreateTargetMachine();
697 if (!targetMachine) {
698 getOperation().emitError() <<
"Target Machine unavailable for triple "
699 << triple <<
", can't optimize with LLVM\n";
702 moduleToObjectTimer.startTimer();
703 std::optional<std::string> serializedISA =
704 translateToISA(llvmModule, **targetMachine);
705 moduleToObjectTimer.stopTimer();
706 llvmToISATimeInMs = moduleToObjectTimer.getTotalTime().getWallTime() * 1000;
707 moduleToObjectTimer.clear();
708 if (!serializedISA) {
709 getOperation().emitError() <<
"Failed translating the module to ISA.";
714 isaCallback(serializedISA.value());
716 #define DEBUG_TYPE "serialize-to-isa"
718 llvm::dbgs() <<
"PTX for module: " << getOperation().getNameAttr() <<
"\n";
719 llvm::dbgs() << *serializedISA <<
"\n";
720 llvm::dbgs().flush();
725 if (targetOptions.getCompilationTarget() ==
726 gpu::CompilationTarget::Assembly) {
728 StringRef bin(serializedISA->c_str(), serializedISA->size() + 1);
732 std::optional<SmallVector<char, 0>> result;
733 moduleToObjectTimer.startTimer();
735 #if MLIR_ENABLE_NVPTXCOMPILER
736 result = compileToBinaryNVPTX(*serializedISA);
738 result = compileToBinary(*serializedISA);
741 moduleToObjectTimer.stopTimer();
742 isaToBinaryTimeInMs = moduleToObjectTimer.getTotalTime().getWallTime() * 1000;
743 moduleToObjectTimer.clear();
747 std::optional<SmallVector<char, 0>>
751 assert(module &&
"The module must be non null.");
754 if (!mlir::isa<gpu::GPUModuleOp>(module)) {
755 module->
emitError(
"Module must be a GPU module.");
758 NVPTXSerializer serializer(*module, cast<NVVMTargetAttr>(attribute),
options);
760 std::optional<SmallVector<char, 0>> result = serializer.run();
761 auto llvmToISATimeInMs = serializer.getLLVMIRToISATimeInMs();
762 if (llvmToISATimeInMs.has_value())
763 module->
setAttr(
"LLVMIRToISATimeInMs",
764 builder.getI64IntegerAttr(*llvmToISATimeInMs));
765 auto isaToBinaryTimeInMs = serializer.getISAToBinaryTimeInMs();
766 if (isaToBinaryTimeInMs.has_value())
767 module->
setAttr(
"ISAToBinaryTimeInMs",
768 builder.getI64IntegerAttr(*isaToBinaryTimeInMs));
776 auto target = cast<NVVMTargetAttr>(attribute);
777 gpu::CompilationTarget format =
options.getCompilationTarget();
778 DictionaryAttr objectProps;
781 if (format == gpu::CompilationTarget::Assembly)
782 properties.push_back(
783 builder.getNamedAttr(
"O", builder.getI32IntegerAttr(target.getO())));
785 if (StringRef section =
options.getELFSection(); !section.empty())
786 properties.push_back(builder.getNamedAttr(gpu::elfSectionName,
787 builder.getStringAttr(section)));
789 for (
const auto *perfName : {
"LLVMIRToISATimeInMs",
"ISAToBinaryTimeInMs"}) {
790 if (module->
hasAttr(perfName)) {
791 IntegerAttr attr = llvm::dyn_cast<IntegerAttr>(module->
getAttr(perfName));
792 properties.push_back(builder.getNamedAttr(
793 perfName, builder.getI64IntegerAttr(attr.getInt())));
797 if (!properties.empty())
798 objectProps = builder.getDictionaryAttr(properties);
800 return builder.getAttr<gpu::ObjectAttr>(
802 builder.getStringAttr(StringRef(
object.data(),
object.size())),
803 objectProps,
nullptr);
static void setOptionalCommandlineArguments(NVVMTargetAttr target, SmallVectorImpl< T > &ptxasArgs)
Adds optional command-line arguments to existing arguments.
const unsigned _mlir_embedded_libdevice_size
#define __DEFAULT_CUDATOOLKIT_PATH__
const unsigned char _mlir_embedded_libdevice[]
static llvm::ManagedStatic< PassManagerOptions > options
Attributes are known-constant values of operations.
MLIRContext * getContext() const
Return the context this attribute belongs to.
This class is a general helper class for creating context-global objects like types,...
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
The class represents an individual entry of a blob.
LogicalResult loadBitcodeFilesFromList(llvm::LLVMContext &context, ArrayRef< Attribute > librariesToLink, SmallVector< std::unique_ptr< llvm::Module >> &llvmModules, bool failureOnError=true)
Loads multiple bitcode files.
virtual std::optional< SmallVector< char, 0 > > moduleToObject(llvm::Module &llvmModule)
Serializes the LLVM IR bitcode to an object file, by default it serializes to LLVM bitcode.
Operation & getOperation()
Returns the operation being serialized.
Operation & module
Module to transform to a binary object.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
void appendDialectRegistry(const DialectRegistry ®istry)
Append the contents of the given dialect registry to the registry associated with this context.
Dialect * getLoadedDialect(StringRef name)
Get a registered IR dialect with the given namespace.
Base class for all NVVM serializations from GPU modules into binary strings.
ArrayRef< Attribute > getLibrariesToLink() const
Returns the bitcode libraries to be linked into the gpu module after translation to LLVM IR.
SerializeGPUModuleBase(Operation &module, NVVMTargetAttr target, const gpu::TargetOptions &targetOptions={})
Initializes the toolkitPath with the path in targetOptions or if empty with the path in getCUDAToolki...
NVVMTargetAttr target
NVVM target attribute.
std::string toolkitPath
CUDA toolkit path.
SmallVector< Attribute > librariesToLink
List of LLVM bitcode to link into after translation to LLVM IR.
std::optional< SmallVector< std::unique_ptr< llvm::Module > > > loadBitcodeFiles(llvm::Module &module) override
Loads the bitcode files in librariesToLink.
LogicalResult appendStandardLibs()
Appends nvvm/libdevice.bc into librariesToLink.
static void init()
Initializes the LLVM NVPTX target by safely calling LLVMInitializeNVPTX* methods if available.
StringRef getToolkitPath() const
Returns the CUDA toolkit path.
NVVMTargetAttr getTarget() const
Returns the target attribute.
Operation is the basic unit of execution within MLIR.
Attribute getAttr(StringAttr name)
Return the specified attribute if present, null otherwise.
bool hasAttr(StringAttr name)
Return true if the operation has an attribute with the provided name, false otherwise.
MLIRContext * getContext()
Return the context this operation is associated with.
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
void setAttr(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
static AsmResourceBlob allocateInferAlign(ArrayRef< T > data, AsmResourceBlob::DeleterFn deleter={}, bool dataIsMutable=false)
This class serves as an opaque interface for passing options to the TargetAttrInterface methods.
void registerNVVMTargetInterfaceExternalModels(DialectRegistry ®istry)
Registers the TargetAttrInterface for the #nvvm.target attribute in the given registry.
StringRef getCUDAToolkitPath()
Searches & returns the path CUDA toolkit path, the search order is:
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
DialectResourceBlobHandle< BuiltinDialect > DenseResourceElementsHandle
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
static ManagerInterface & getManagerInterface(MLIRContext *ctx)
Get the interface for the dialect that owns handles of this type.