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::interleave(ptxasArgs, llvm::dbgs(),
" ");
459 llvm::dbgs() <<
"\n";
461 llvm::interleave(fatbinArgs, llvm::dbgs(),
" ");
462 llvm::dbgs() <<
"\n";
471 if (message.empty()) {
472 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> toolStderr =
473 llvm::MemoryBuffer::getFile(logFile->first);
475 emitError(loc) << toolName <<
" invocation failed. Log:\n"
476 << toolStderr->get()->getBuffer();
478 emitError(loc) << toolName <<
" invocation failed.";
482 <<
" invocation failed, error message: " << message;
487 if (llvm::sys::ExecuteAndWait(ptxasCompiler.value(), ptxasArgs,
493 return emitLogError(
"`ptxas`");
494 #define DEBUG_TYPE "dump-sass"
496 std::optional<std::string> nvdisasm = findTool(
"nvdisasm");
498 {StringRef(
"nvdisasm"), StringRef(cubinFile.first)});
499 if (llvm::sys::ExecuteAndWait(nvdisasm.value(), nvdisasmArgs,
505 return emitLogError(
"`nvdisasm`");
506 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> logBuffer =
507 llvm::MemoryBuffer::getFile(logFile->first);
508 if (logBuffer && !(*logBuffer)->getBuffer().empty()) {
509 llvm::dbgs() <<
"Output:\n" << (*logBuffer)->getBuffer() <<
"\n";
510 llvm::dbgs().flush();
517 if (createFatbin && llvm::sys::ExecuteAndWait(*fatbinaryTool, fatbinArgs,
523 return emitLogError(
"`fatbinary`");
526 #define DEBUG_TYPE "serialize-to-binary"
528 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> logBuffer =
529 llvm::MemoryBuffer::getFile(logFile->first);
530 if (logBuffer && !(*logBuffer)->getBuffer().empty()) {
531 llvm::dbgs() <<
"Output:\n" << (*logBuffer)->getBuffer() <<
"\n";
532 llvm::dbgs().flush();
538 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> binaryBuffer =
539 llvm::MemoryBuffer::getFile(binaryFile->first);
541 emitError(loc) <<
"Couldn't open the file: `" << binaryFile->first
542 <<
"`, error message: " << binaryBuffer.getError().message();
545 StringRef fatbin = (*binaryBuffer)->getBuffer();
549 #if MLIR_ENABLE_NVPTXCOMPILER
550 #include "nvPTXCompiler.h"
552 #define RETURN_ON_NVPTXCOMPILER_ERROR(expr) \
554 if (auto status = (expr)) { \
555 emitError(loc) << llvm::Twine(#expr).concat(" failed with error code ") \
557 return std::nullopt; \
561 #include "nvFatbin.h"
563 #define RETURN_ON_NVFATBIN_ERROR(expr) \
565 auto result = (expr); \
566 if (result != nvFatbinResult::NVFATBIN_SUCCESS) { \
567 emitError(loc) << llvm::Twine(#expr).concat(" failed with error: ") \
568 << nvFatbinGetErrorString(result); \
569 return std::nullopt; \
573 std::optional<SmallVector<char, 0>>
574 NVPTXSerializer::compileToBinaryNVPTX(
const std::string &ptxCode) {
575 Location loc = getOperation().getLoc();
576 nvPTXCompilerHandle compiler =
nullptr;
577 nvPTXCompileResult status;
581 std::string optLevel = std::to_string(this->optLevel);
582 std::pair<llvm::BumpPtrAllocator, SmallVector<const char *>> cmdOpts =
583 targetOptions.tokenizeCmdOptions();
584 cmdOpts.second.append(
585 {
"-arch", getTarget().getChip().data(),
"--opt-level", optLevel.c_str()});
590 RETURN_ON_NVPTXCOMPILER_ERROR(
591 nvPTXCompilerCreate(&compiler, ptxCode.size(), ptxCode.c_str()));
594 status = nvPTXCompilerCompile(compiler, cmdOpts.second.size(),
595 cmdOpts.second.data());
598 if (status != NVPTXCOMPILE_SUCCESS) {
599 RETURN_ON_NVPTXCOMPILER_ERROR(
600 nvPTXCompilerGetErrorLogSize(compiler, &logSize));
603 RETURN_ON_NVPTXCOMPILER_ERROR(
604 nvPTXCompilerGetErrorLog(compiler, log.data()));
605 emitError(loc) <<
"NVPTX compiler invocation failed, error log: "
608 emitError(loc) <<
"NVPTX compiler invocation failed with error code: "
615 RETURN_ON_NVPTXCOMPILER_ERROR(
616 nvPTXCompilerGetCompiledProgramSize(compiler, &elfSize));
618 RETURN_ON_NVPTXCOMPILER_ERROR(
619 nvPTXCompilerGetCompiledProgram(compiler, (
void *)binary.data()));
622 #define DEBUG_TYPE "serialize-to-binary"
624 RETURN_ON_NVPTXCOMPILER_ERROR(
625 nvPTXCompilerGetInfoLogSize(compiler, &logSize));
628 RETURN_ON_NVPTXCOMPILER_ERROR(
629 nvPTXCompilerGetInfoLog(compiler, log.data()));
630 llvm::dbgs() <<
"NVPTX compiler invocation for module: "
631 << getOperation().getNameAttr() <<
"\n";
632 llvm::dbgs() <<
"Arguments: ";
633 llvm::interleave(cmdOpts.second, llvm::dbgs(),
" ");
634 llvm::dbgs() <<
"\nOutput\n" << log.data() <<
"\n";
635 llvm::dbgs().flush();
639 RETURN_ON_NVPTXCOMPILER_ERROR(nvPTXCompilerDestroy(&compiler));
641 if (targetOptions.getCompilationTarget() == gpu::CompilationTarget::Fatbin) {
642 bool useFatbin32 = llvm::any_of(cmdOpts.second, [](
const char *option) {
643 return llvm::StringRef(option) ==
"-32";
646 const char *cubinOpts[1] = {useFatbin32 ?
"-32" :
"-64"};
647 nvFatbinHandle handle;
649 auto chip = getTarget().getChip();
650 chip.consume_front(
"sm_");
652 RETURN_ON_NVFATBIN_ERROR(nvFatbinCreate(&handle, cubinOpts, 1));
653 RETURN_ON_NVFATBIN_ERROR(nvFatbinAddCubin(
654 handle, binary.data(), binary.size(), chip.data(),
nullptr));
655 RETURN_ON_NVFATBIN_ERROR(nvFatbinAddPTX(
656 handle, ptxCode.data(), ptxCode.size(), chip.data(),
nullptr,
nullptr));
659 RETURN_ON_NVFATBIN_ERROR(nvFatbinSize(handle, &fatbinSize));
661 RETURN_ON_NVFATBIN_ERROR(nvFatbinGet(handle, (
void *)fatbin.data()));
662 RETURN_ON_NVFATBIN_ERROR(nvFatbinDestroy(&handle));
670 std::optional<SmallVector<char, 0>>
671 NVPTXSerializer::moduleToObject(llvm::Module &llvmModule) {
672 llvm::Timer moduleToObjectTimer(
673 "moduleToObjectTimer",
674 "Timer for perf llvm-ir -> isa and isa -> binary.");
675 moduleToObjectTimer.startTimer();
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 std::optional<std::string> serializedISA =
703 translateToISA(llvmModule, **targetMachine);
704 if (!serializedISA) {
705 getOperation().emitError() <<
"Failed translating the module to ISA.";
709 moduleToObjectTimer.stopTimer();
710 llvmToISATimeInMs = moduleToObjectTimer.getTotalTime().getWallTime() * 1000;
711 moduleToObjectTimer.clear();
712 moduleToObjectTimer.startTimer();
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;
734 #if MLIR_ENABLE_NVPTXCOMPILER
735 result = compileToBinaryNVPTX(*serializedISA);
737 result = compileToBinary(*serializedISA);
740 moduleToObjectTimer.stopTimer();
741 isaToBinaryTimeInMs = moduleToObjectTimer.getTotalTime().getWallTime() * 1000;
742 moduleToObjectTimer.clear();
746 std::optional<SmallVector<char, 0>>
750 assert(module &&
"The module must be non null.");
753 if (!mlir::isa<gpu::GPUModuleOp>(module)) {
754 module->
emitError(
"Module must be a GPU module.");
757 NVPTXSerializer serializer(*module, cast<NVVMTargetAttr>(attribute),
options);
759 std::optional<SmallVector<char, 0>> result = serializer.run();
760 auto llvmToISATimeInMs = serializer.getLLVMIRToISATimeInMs();
761 if (llvmToISATimeInMs.has_value())
762 module->
setAttr(
"LLVMIRToISATimeInMs",
763 builder.getI64IntegerAttr(*llvmToISATimeInMs));
764 auto isaToBinaryTimeInMs = serializer.getISAToBinaryTimeInMs();
765 if (isaToBinaryTimeInMs.has_value())
766 module->
setAttr(
"ISAToBinaryTimeInMs",
767 builder.getI64IntegerAttr(*isaToBinaryTimeInMs));
775 auto target = cast<NVVMTargetAttr>(attribute);
776 gpu::CompilationTarget format =
options.getCompilationTarget();
777 DictionaryAttr objectProps;
780 if (format == gpu::CompilationTarget::Assembly)
781 properties.push_back(
782 builder.getNamedAttr(
"O", builder.getI32IntegerAttr(target.getO())));
784 if (StringRef section =
options.getELFSection(); !section.empty())
785 properties.push_back(builder.getNamedAttr(gpu::elfSectionName,
786 builder.getStringAttr(section)));
788 for (
const auto *perfName : {
"LLVMIRToISATimeInMs",
"ISAToBinaryTimeInMs"}) {
789 if (module->
hasAttr(perfName)) {
790 IntegerAttr attr = llvm::dyn_cast<IntegerAttr>(module->
getAttr(perfName));
791 properties.push_back(builder.getNamedAttr(
792 perfName, builder.getI64IntegerAttr(attr.getInt())));
796 if (!properties.empty())
797 objectProps = builder.getDictionaryAttr(properties);
799 return builder.getAttr<gpu::ObjectAttr>(
801 builder.getStringAttr(StringRef(
object.data(),
object.size())),
802 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.