29 #include "llvm/ADT/ScopeExit.h"
30 #include "llvm/Config/Targets.h"
31 #include "llvm/Support/FileSystem.h"
32 #include "llvm/Support/FileUtilities.h"
33 #include "llvm/Support/FormatVariadic.h"
34 #include "llvm/Support/MemoryBuffer.h"
35 #include "llvm/Support/Path.h"
36 #include "llvm/Support/Process.h"
37 #include "llvm/Support/Program.h"
38 #include "llvm/Support/TargetSelect.h"
39 #include "llvm/Support/Timer.h"
40 #include "llvm/Support/raw_ostream.h"
49 #ifndef __DEFAULT_CUDATOOLKIT_PATH__
50 #define __DEFAULT_CUDATOOLKIT_PATH__ ""
58 class NVVMTargetAttrImpl
59 :
public gpu::TargetAttrInterface::FallbackModel<NVVMTargetAttrImpl> {
61 std::optional<SmallVector<char, 0>>
75 NVVMTargetAttr::attachInterface<NVVMTargetAttrImpl>(*ctx);
88 if (
const char *var = std::getenv(
"CUDA_ROOT"))
90 if (
const char *var = std::getenv(
"CUDA_HOME"))
92 if (
const char *var = std::getenv(
"CUDA_PATH"))
100 : ModuleToObject(module, target.getTriple(), target.getChip(),
101 target.getFeatures(), target.getO(),
102 targetOptions.getInitialLlvmIRCallback(),
103 targetOptions.getLinkedLlvmIRCallback(),
104 targetOptions.getOptimizedLlvmIRCallback(),
105 targetOptions.getISACallback()),
106 target(target), toolkitPath(targetOptions.getToolkitPath()),
107 librariesToLink(targetOptions.getLibrariesToLink()) {
122 static llvm::once_flag initializeBackendOnce;
123 llvm::call_once(initializeBackendOnce, []() {
125 #if LLVM_HAS_NVPTX_TARGET
126 LLVMInitializeNVPTXTarget();
127 LLVMInitializeNVPTXTargetInfo();
128 LLVMInitializeNVPTXTargetMC();
129 LLVMInitializeNVPTXAsmPrinter();
144 #if MLIR_NVVM_EMBED_LIBDEVICE
155 resourceManager.getBlobManager().lookup(
"_mlir_embedded_libdevice");
169 type, resourceManager.insert(
"_mlir_embedded_libdevice",
170 std::move(unmanagedBlob))));
173 if (!pathRef.empty()) {
175 path.insert(path.begin(), pathRef.begin(), pathRef.end());
176 pathRef = StringRef(path.data(), path.size());
177 if (!llvm::sys::fs::is_directory(pathRef)) {
179 <<
" does not exist or is not a directory.\n";
182 llvm::sys::path::append(path,
"nvvm",
"libdevice",
"libdevice.10.bc");
183 pathRef = StringRef(path.data(), path.size());
184 if (!llvm::sys::fs::is_regular_file(pathRef)) {
186 <<
" does not exist or is not a file.\n";
195 std::optional<SmallVector<std::unique_ptr<llvm::Module>>>
201 return std::move(bcFiles);
207 NVPTXSerializer(
Operation &module, NVVMTargetAttr target,
211 gpu::GPUModuleOp getOperation();
214 std::optional<SmallVector<char, 0>>
215 compileToBinary(
const std::string &ptxCode);
218 std::optional<SmallVector<char, 0>>
219 compileToBinaryNVPTX(
const std::string &ptxCode);
223 std::optional<SmallVector<char, 0>>
224 moduleToObject(llvm::Module &llvmModule)
override;
229 std::optional<int64_t> getLLVMIRToISATimeInMs();
234 std::optional<int64_t> getISAToBinaryTimeInMs();
237 using TmpFile = std::pair<llvm::SmallString<128>, llvm::FileRemover>;
240 std::optional<TmpFile> createTemp(StringRef name, StringRef suffix);
247 std::optional<std::string> findTool(StringRef tool);
253 std::optional<int64_t> llvmToISATimeInMs;
256 std::optional<int64_t> isaToBinaryTimeInMs;
260 NVPTXSerializer::NVPTXSerializer(
Operation &module, NVVMTargetAttr target,
263 targetOptions(targetOptions), llvmToISATimeInMs(std::nullopt),
264 isaToBinaryTimeInMs(std::nullopt) {}
266 std::optional<NVPTXSerializer::TmpFile>
267 NVPTXSerializer::createTemp(StringRef name, StringRef suffix) {
270 llvm::sys::fs::createTemporaryFile(name, suffix, filename);
272 getOperation().emitError() <<
"Couldn't create the temp file: `" << filename
273 <<
"`, error message: " << ec.message();
276 return TmpFile(filename, llvm::FileRemover(filename.c_str()));
279 std::optional<int64_t> NVPTXSerializer::getLLVMIRToISATimeInMs() {
280 return llvmToISATimeInMs;
283 std::optional<int64_t> NVPTXSerializer::getISAToBinaryTimeInMs() {
284 return isaToBinaryTimeInMs;
287 gpu::GPUModuleOp NVPTXSerializer::getOperation() {
291 std::optional<std::string> NVPTXSerializer::findTool(StringRef tool) {
294 StringRef pathRef = targetOptions.getToolkitPath();
296 if (!pathRef.empty()) {
297 path.insert(path.begin(), pathRef.begin(), pathRef.end());
298 llvm::sys::path::append(path,
"bin", tool);
299 if (llvm::sys::fs::can_execute(path))
300 return StringRef(path.data(), path.size()).str();
304 if (std::optional<std::string> toolPath =
305 llvm::sys::Process::FindInEnvPath(
"PATH", tool))
311 if (!pathRef.empty()) {
312 path.insert(path.begin(), pathRef.begin(), pathRef.end());
313 llvm::sys::path::append(path,
"bin", tool);
314 if (llvm::sys::fs::can_execute(path))
315 return StringRef(path.data(), path.size()).str();
317 getOperation().emitError()
318 <<
"Couldn't find the `" << tool
319 <<
"` binary. Please specify the toolkit "
320 "path, add the compiler to $PATH, or set one of the environment "
321 "variables in `NVVM::getCUDAToolkitPath()`.";
326 template <
typename T>
329 if (!target.hasCmdOptions())
332 std::optional<mlir::NamedAttribute> cmdOptions = target.getCmdOptions();
333 for (
Attribute attr : cast<ArrayAttr>(cmdOptions->getValue())) {
334 if (
auto strAttr = dyn_cast<StringAttr>(attr)) {
335 if constexpr (std::is_same_v<T, StringRef>) {
336 ptxasArgs.push_back(strAttr.getValue());
337 }
else if constexpr (std::is_same_v<T, const char *>) {
338 ptxasArgs.push_back(strAttr.getValue().data());
346 std::optional<SmallVector<char, 0>>
347 NVPTXSerializer::compileToBinary(
const std::string &ptxCode) {
350 const bool createFatbin =
351 targetOptions.getCompilationTarget() == gpu::CompilationTarget::Fatbin;
354 std::optional<std::string> ptxasCompiler = findTool(
"ptxas");
357 std::optional<std::string> fatbinaryTool;
359 fatbinaryTool = findTool(
"fatbinary");
363 Location loc = getOperation().getLoc();
366 std::string basename =
367 llvm::formatv(
"mlir-{0}-{1}-{2}", getOperation().getNameAttr().getValue(),
368 getTarget().getTriple(), getTarget().getChip());
371 std::optional<TmpFile> ptxFile = createTemp(basename,
"ptx");
374 std::optional<TmpFile> logFile = createTemp(basename,
"log");
377 std::optional<TmpFile> binaryFile = createTemp(basename,
"bin");
382 std::string cubinFilename = (ptxFile->first +
".cubin").str();
383 cubinFile = TmpFile(cubinFilename, llvm::FileRemover(cubinFilename));
385 cubinFile.first = binaryFile->first;
391 llvm::raw_fd_ostream ptxStream(ptxFile->first, ec);
393 emitError(loc) <<
"Couldn't open the file: `" << ptxFile->first
394 <<
"`, error message: " << ec.message();
397 ptxStream << ptxCode;
398 if (ptxStream.has_error()) {
399 emitError(loc) <<
"An error occurred while writing the PTX to: `"
400 << ptxFile->first <<
"`.";
407 std::optional<StringRef> redirects[] = {
414 std::pair<llvm::BumpPtrAllocator, SmallVector<const char *>> cmdOpts =
415 targetOptions.tokenizeCmdOptions();
418 std::string optLevel = std::to_string(this->optLevel);
420 {StringRef(
"ptxas"), StringRef(
"-arch"), getTarget().getChip(),
421 StringRef(ptxFile->first), StringRef(
"-o"), StringRef(cubinFile.first),
422 "--opt-level", optLevel});
424 bool useFatbin32 =
false;
425 for (
const auto *cArg : cmdOpts.second) {
429 if (StringRef arg(cArg); arg !=
"-32")
430 ptxasArgs.push_back(arg);
439 StringRef chip = getTarget().getChip();
441 chip.consume_front(
"sm_"), chip.consume_front(
"compute_");
443 std::string cubinArg =
444 llvm::formatv(
"--image3=kind=elf,sm={0},file={1}", chip, cubinFile.first)
448 llvm::formatv(
"--image3=kind=ptx,sm={0},file={1}", chip, ptxFile->first)
451 useFatbin32 ?
"-32" :
"-64", cubinArg,
452 ptxArg,
"--create", binaryFile->first});
455 #define DEBUG_TYPE "serialize-to-binary"
457 llvm::dbgs() <<
"Tool invocation for module: "
458 << getOperation().getNameAttr() <<
"\n";
459 llvm::dbgs() <<
"ptxas executable:" << ptxasCompiler.value() <<
"\n";
460 llvm::interleave(ptxasArgs, llvm::dbgs(),
" ");
461 llvm::dbgs() <<
"\n";
463 llvm::interleave(fatbinArgs, llvm::dbgs(),
" ");
464 llvm::dbgs() <<
"\n";
473 if (message.empty()) {
474 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> toolStderr =
475 llvm::MemoryBuffer::getFile(logFile->first);
477 emitError(loc) << toolName <<
" invocation failed. Log:\n"
478 << toolStderr->get()->getBuffer();
480 emitError(loc) << toolName <<
" invocation failed.";
484 <<
" invocation failed, error message: " << message;
489 if (llvm::sys::ExecuteAndWait(ptxasCompiler.value(), ptxasArgs,
495 return emitLogError(
"`ptxas`");
496 #define DEBUG_TYPE "dump-sass"
498 std::optional<std::string> nvdisasm = findTool(
"nvdisasm");
500 {StringRef(
"nvdisasm"), StringRef(cubinFile.first)});
501 if (llvm::sys::ExecuteAndWait(nvdisasm.value(), nvdisasmArgs,
507 return emitLogError(
"`nvdisasm`");
508 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> logBuffer =
509 llvm::MemoryBuffer::getFile(logFile->first);
510 if (logBuffer && !(*logBuffer)->getBuffer().empty()) {
511 llvm::dbgs() <<
"Output:\n" << (*logBuffer)->getBuffer() <<
"\n";
512 llvm::dbgs().flush();
519 if (createFatbin && llvm::sys::ExecuteAndWait(*fatbinaryTool, fatbinArgs,
525 return emitLogError(
"`fatbinary`");
528 #define DEBUG_TYPE "serialize-to-binary"
530 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> logBuffer =
531 llvm::MemoryBuffer::getFile(logFile->first);
532 if (logBuffer && !(*logBuffer)->getBuffer().empty()) {
533 llvm::dbgs() <<
"Output:\n" << (*logBuffer)->getBuffer() <<
"\n";
534 llvm::dbgs().flush();
540 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> binaryBuffer =
541 llvm::MemoryBuffer::getFile(binaryFile->first);
543 emitError(loc) <<
"Couldn't open the file: `" << binaryFile->first
544 <<
"`, error message: " << binaryBuffer.getError().message();
547 StringRef fatbin = (*binaryBuffer)->getBuffer();
551 #if MLIR_ENABLE_NVPTXCOMPILER
552 #include "nvPTXCompiler.h"
554 #define RETURN_ON_NVPTXCOMPILER_ERROR(expr) \
556 if (auto status = (expr)) { \
557 emitError(loc) << llvm::Twine(#expr).concat(" failed with error code ") \
559 return std::nullopt; \
563 #include "nvFatbin.h"
565 #define RETURN_ON_NVFATBIN_ERROR(expr) \
567 auto result = (expr); \
568 if (result != nvFatbinResult::NVFATBIN_SUCCESS) { \
569 emitError(loc) << llvm::Twine(#expr).concat(" failed with error: ") \
570 << nvFatbinGetErrorString(result); \
571 return std::nullopt; \
575 std::optional<SmallVector<char, 0>>
576 NVPTXSerializer::compileToBinaryNVPTX(
const std::string &ptxCode) {
577 Location loc = getOperation().getLoc();
578 nvPTXCompilerHandle compiler =
nullptr;
579 nvPTXCompileResult status;
583 std::string optLevel = std::to_string(this->optLevel);
584 std::pair<llvm::BumpPtrAllocator, SmallVector<const char *>> cmdOpts =
585 targetOptions.tokenizeCmdOptions();
586 cmdOpts.second.append(
587 {
"-arch", getTarget().getChip().data(),
"--opt-level", optLevel.c_str()});
592 RETURN_ON_NVPTXCOMPILER_ERROR(
593 nvPTXCompilerCreate(&compiler, ptxCode.size(), ptxCode.c_str()));
596 status = nvPTXCompilerCompile(compiler, cmdOpts.second.size(),
597 cmdOpts.second.data());
600 if (status != NVPTXCOMPILE_SUCCESS) {
601 RETURN_ON_NVPTXCOMPILER_ERROR(
602 nvPTXCompilerGetErrorLogSize(compiler, &logSize));
605 RETURN_ON_NVPTXCOMPILER_ERROR(
606 nvPTXCompilerGetErrorLog(compiler, log.data()));
607 emitError(loc) <<
"NVPTX compiler invocation failed, error log: "
610 emitError(loc) <<
"NVPTX compiler invocation failed with error code: "
617 RETURN_ON_NVPTXCOMPILER_ERROR(
618 nvPTXCompilerGetCompiledProgramSize(compiler, &elfSize));
620 RETURN_ON_NVPTXCOMPILER_ERROR(
621 nvPTXCompilerGetCompiledProgram(compiler, (
void *)binary.data()));
624 #define DEBUG_TYPE "serialize-to-binary"
626 RETURN_ON_NVPTXCOMPILER_ERROR(
627 nvPTXCompilerGetInfoLogSize(compiler, &logSize));
630 RETURN_ON_NVPTXCOMPILER_ERROR(
631 nvPTXCompilerGetInfoLog(compiler, log.data()));
632 llvm::dbgs() <<
"NVPTX compiler invocation for module: "
633 << getOperation().getNameAttr() <<
"\n";
634 llvm::dbgs() <<
"Arguments: ";
635 llvm::interleave(cmdOpts.second, llvm::dbgs(),
" ");
636 llvm::dbgs() <<
"\nOutput\n" << log.data() <<
"\n";
637 llvm::dbgs().flush();
641 RETURN_ON_NVPTXCOMPILER_ERROR(nvPTXCompilerDestroy(&compiler));
643 if (targetOptions.getCompilationTarget() == gpu::CompilationTarget::Fatbin) {
644 bool useFatbin32 = llvm::any_of(cmdOpts.second, [](
const char *option) {
645 return llvm::StringRef(option) ==
"-32";
648 const char *cubinOpts[1] = {useFatbin32 ?
"-32" :
"-64"};
649 nvFatbinHandle handle;
651 auto chip = getTarget().getChip();
652 chip.consume_front(
"sm_");
654 RETURN_ON_NVFATBIN_ERROR(nvFatbinCreate(&handle, cubinOpts, 1));
655 RETURN_ON_NVFATBIN_ERROR(nvFatbinAddCubin(
656 handle, binary.data(), binary.size(), chip.data(),
nullptr));
657 RETURN_ON_NVFATBIN_ERROR(nvFatbinAddPTX(
658 handle, ptxCode.data(), ptxCode.size(), chip.data(),
nullptr,
nullptr));
661 RETURN_ON_NVFATBIN_ERROR(nvFatbinSize(handle, &fatbinSize));
663 RETURN_ON_NVFATBIN_ERROR(nvFatbinGet(handle, (
void *)fatbin.data()));
664 RETURN_ON_NVFATBIN_ERROR(nvFatbinDestroy(&handle));
672 std::optional<SmallVector<char, 0>>
673 NVPTXSerializer::moduleToObject(llvm::Module &llvmModule) {
674 llvm::Timer moduleToObjectTimer(
675 "moduleToObjectTimer",
676 "Timer for perf llvm-ir -> isa and isa -> binary.");
677 auto clear = llvm::make_scope_exit([&]() { moduleToObjectTimer.clear(); });
679 #define DEBUG_TYPE "serialize-to-llvm"
681 llvm::dbgs() <<
"LLVM IR for module: " << getOperation().getNameAttr()
683 llvm::dbgs() << llvmModule <<
"\n";
684 llvm::dbgs().flush();
687 if (targetOptions.getCompilationTarget() == gpu::CompilationTarget::Offload)
690 #if !LLVM_HAS_NVPTX_TARGET
691 getOperation()->emitError(
692 "The `NVPTX` target was not built. Please enable it when building LLVM.");
697 std::optional<llvm::TargetMachine *> targetMachine =
698 getOrCreateTargetMachine();
699 if (!targetMachine) {
700 getOperation().emitError() <<
"Target Machine unavailable for triple "
701 << triple <<
", can't optimize with LLVM\n";
704 moduleToObjectTimer.startTimer();
705 std::optional<std::string> serializedISA =
706 translateToISA(llvmModule, **targetMachine);
707 moduleToObjectTimer.stopTimer();
708 llvmToISATimeInMs = moduleToObjectTimer.getTotalTime().getWallTime() * 1000;
709 moduleToObjectTimer.clear();
710 if (!serializedISA) {
711 getOperation().emitError() <<
"Failed translating the module to ISA.";
716 isaCallback(serializedISA.value());
718 #define DEBUG_TYPE "serialize-to-isa"
720 llvm::dbgs() <<
"PTX for module: " << getOperation().getNameAttr() <<
"\n";
721 llvm::dbgs() << *serializedISA <<
"\n";
722 llvm::dbgs().flush();
727 if (targetOptions.getCompilationTarget() == gpu::CompilationTarget::Assembly)
730 std::optional<SmallVector<char, 0>> result;
731 moduleToObjectTimer.startTimer();
733 #if MLIR_ENABLE_NVPTXCOMPILER
734 result = compileToBinaryNVPTX(*serializedISA);
736 result = compileToBinary(*serializedISA);
739 moduleToObjectTimer.stopTimer();
740 isaToBinaryTimeInMs = moduleToObjectTimer.getTotalTime().getWallTime() * 1000;
741 moduleToObjectTimer.clear();
745 std::optional<SmallVector<char, 0>>
749 assert(module &&
"The module must be non null.");
752 if (!mlir::isa<gpu::GPUModuleOp>(module)) {
753 module->
emitError(
"Module must be a GPU module.");
756 NVPTXSerializer serializer(*module, cast<NVVMTargetAttr>(attribute),
options);
758 std::optional<SmallVector<char, 0>> result = serializer.run();
759 auto llvmToISATimeInMs = serializer.getLLVMIRToISATimeInMs();
760 if (llvmToISATimeInMs.has_value())
761 module->
setAttr(
"LLVMIRToISATimeInMs",
762 builder.getI64IntegerAttr(*llvmToISATimeInMs));
763 auto isaToBinaryTimeInMs = serializer.getISAToBinaryTimeInMs();
764 if (isaToBinaryTimeInMs.has_value())
765 module->
setAttr(
"ISAToBinaryTimeInMs",
766 builder.getI64IntegerAttr(*isaToBinaryTimeInMs));
774 auto target = cast<NVVMTargetAttr>(attribute);
775 gpu::CompilationTarget format =
options.getCompilationTarget();
776 DictionaryAttr objectProps;
779 if (format == gpu::CompilationTarget::Assembly)
780 properties.push_back(
781 builder.getNamedAttr(
"O", builder.getI32IntegerAttr(target.getO())));
783 if (StringRef section =
options.getELFSection(); !section.empty())
784 properties.push_back(builder.getNamedAttr(gpu::elfSectionName,
785 builder.getStringAttr(section)));
787 for (
const auto *perfName : {
"LLVMIRToISATimeInMs",
"ISAToBinaryTimeInMs"}) {
788 if (module->
hasAttr(perfName)) {
789 IntegerAttr attr = llvm::dyn_cast<IntegerAttr>(module->
getAttr(perfName));
790 properties.push_back(builder.getNamedAttr(
791 perfName, builder.getI64IntegerAttr(attr.getInt())));
795 if (!properties.empty())
796 objectProps = builder.getDictionaryAttr(properties);
798 return builder.getAttr<gpu::ObjectAttr>(
800 builder.getStringAttr(StringRef(
object.data(),
object.size())),
801 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.