diff options
Diffstat (limited to 'source')
25 files changed, 239 insertions, 295 deletions
diff --git a/source/compiler-core/slang-downstream-compiler.h b/source/compiler-core/slang-downstream-compiler.h index dc9e29185..e40ffc13a 100644 --- a/source/compiler-core/slang-downstream-compiler.h +++ b/source/compiler-core/slang-downstream-compiler.h @@ -274,7 +274,7 @@ public: OptimizationLevel optimizationLevel = OptimizationLevel::Default; DebugInfoType debugInfoType = DebugInfoType::Standard; - SlangCompileTarget targetType = SLANG_EXECUTABLE; + SlangCompileTarget targetType = SLANG_HOST_EXECUTABLE; SlangSourceLanguage sourceLanguage = SLANG_SOURCE_LANGUAGE_CPP; FloatingPointMode floatingPointMode = FloatingPointMode::Default; PipelineType pipelineType = PipelineType::Unknown; @@ -302,6 +302,9 @@ public: List<String> includePaths; List<String> libraryPaths; + /// Libraries to link against. + List<String> libraries; + List<CapabilityVersion> requiredCapabilityVersions; /// For compilers/compiles that require an entry point name, else can be empty diff --git a/source/compiler-core/slang-gcc-compiler-util.cpp b/source/compiler-core/slang-gcc-compiler-util.cpp index b5c359247..8d1b87b68 100644 --- a/source/compiler-core/slang-gcc-compiler-util.cpp +++ b/source/compiler-core/slang-gcc-compiler-util.cpp @@ -415,12 +415,12 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse switch (options.targetType) { - case SLANG_SHARED_LIBRARY: + case SLANG_SHADER_SHARED_LIBRARY: { outPath << SharedLibrary::calcPlatformPath(options.modulePath.getUnownedSlice()); return SLANG_OK; } - case SLANG_EXECUTABLE: + case SLANG_HOST_EXECUTABLE: { outPath << options.modulePath; outPath << Process::getExecutableSuffix(); @@ -547,7 +547,7 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse switch (options.targetType) { - case SLANG_SHARED_LIBRARY: + case SLANG_SHADER_SHARED_LIBRARY: { // Shared library cmdLine.addArg("-shared"); @@ -559,7 +559,7 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse } break; } - case SLANG_EXECUTABLE: + case SLANG_HOST_EXECUTABLE: { break; } @@ -601,7 +601,7 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse //cmdLine.addArg(linkOptions); } - if (options.targetType == SLANG_SHARED_LIBRARY) + if (options.targetType == SLANG_SHADER_SHARED_LIBRARY) { if (!PlatformUtil::isFamily(PlatformFamily::Apple, platformKind)) { diff --git a/source/compiler-core/slang-visual-studio-compiler-util.cpp b/source/compiler-core/slang-visual-studio-compiler-util.cpp index 9bdfd406a..2ba69c1ce 100644 --- a/source/compiler-core/slang-visual-studio-compiler-util.cpp +++ b/source/compiler-core/slang-visual-studio-compiler-util.cpp @@ -23,12 +23,12 @@ namespace Slang switch (options.targetType) { - case SLANG_SHARED_LIBRARY: + case SLANG_SHADER_SHARED_LIBRARY: { outPath << options.modulePath << ".dll"; return SLANG_OK; } - case SLANG_EXECUTABLE: + case SLANG_HOST_EXECUTABLE: { outPath << options.modulePath << ".exe"; return SLANG_OK; @@ -60,7 +60,7 @@ namespace Slang { outPaths.add(options.modulePath + ".ilk"); - if (options.targetType == SLANG_SHARED_LIBRARY) + if (options.targetType == SLANG_SHADER_SHARED_LIBRARY) { outPaths.add(options.modulePath + ".exp"); outPaths.add(options.modulePath + ".lib"); @@ -191,7 +191,7 @@ namespace Slang switch (options.targetType) { - case SLANG_SHARED_LIBRARY: + case SLANG_SHADER_SHARED_LIBRARY: { // Create dynamic link library if (options.debugInfoType == DebugInfoType::None) @@ -206,7 +206,7 @@ namespace Slang cmdLine.addPrefixPathArg("/Fe", options.modulePath, ".dll"); break; } - case SLANG_EXECUTABLE: + case SLANG_HOST_EXECUTABLE: { cmdLine.addPrefixPathArg("/Fe", options.modulePath, ".exe"); break; @@ -256,6 +256,12 @@ namespace Slang cmdLine.addPrefixPathArg("/LIBPATH:", libPath); } + // Link libraries. + for (const auto& lib : options.libraries) + { + cmdLine.addPrefixPathArg("", lib, ".lib"); + } + return SLANG_OK; } diff --git a/source/core/slang-common.h b/source/core/slang-common.h index f17660e0d..694162f1d 100644 --- a/source/core/slang-common.h +++ b/source/core/slang-common.h @@ -94,3 +94,22 @@ template<typename T> void slang_use_obj(T&) {} #define SLANG_UNREFERENCED_PARAMETER(P) slang_use_obj(P) #define SLANG_UNREFERENCED_VARIABLE(P) slang_use_obj(P) #endif + +#if defined(SLANG_RT_DYNAMIC) +#if defined(_MSC_VER) +# ifdef SLANG_RT_DYNAMIC_EXPORT +# define SLANG_RT_API SLANG_DLL_EXPORT +# else +# define SLANG_RT_API __declspec(dllimport) +# endif +#else +// TODO: need to consider compiler capabilities +//# ifdef SLANG_RT_DYNAMIC_EXPORT +# define SLANG_RT_API SLANG_DLL_EXPORT +//# endif +#endif +#endif + +#ifndef SLANG_RT_API +#define SLANG_RT_API +#endif diff --git a/source/core/slang-smart-pointer.h b/source/core/slang-smart-pointer.h index 2e5821ffd..a6aa35906 100644 --- a/source/core/slang-smart-pointer.h +++ b/source/core/slang-smart-pointer.h @@ -10,7 +10,7 @@ namespace Slang { // Base class for all reference-counted objects - class RefObject + class SLANG_RT_API RefObject { private: UInt referenceCount; @@ -86,8 +86,7 @@ namespace Slang SLANG_FORCE_INLINE const T* as(const RefObject* obj) { return dynamicCast<T>(obj); } // "Smart" pointer to a reference-counted object - template<typename T> - struct RefPtr + template<typename T> struct SLANG_RT_API RefPtr { RefPtr() : pointer(nullptr) diff --git a/source/core/slang-string.h b/source/core/slang-string.h index cb13ec415..6dc3275eb 100644 --- a/source/core/slang-string.h +++ b/source/core/slang-string.h @@ -62,7 +62,7 @@ namespace Slang return (((unsigned char)ch) & 0xC0) == 0x80; } - struct UnownedStringSlice + struct SLANG_RT_API UnownedStringSlice { public: typedef UnownedStringSlice ThisType; @@ -190,7 +190,7 @@ namespace Slang // A `StringRepresentation` provides the backing storage for // all reference-counted string-related types. - class StringRepresentation : public RefObject + class SLANG_RT_API StringRepresentation : public RefObject { public: Index length; @@ -286,7 +286,7 @@ namespace Slang - struct UnownedTerminatedStringSlice : public UnownedStringSlice + struct SLANG_RT_API UnownedTerminatedStringSlice : public UnownedStringSlice { public: UnownedTerminatedStringSlice(char const* b) @@ -294,7 +294,7 @@ namespace Slang {} }; - struct StringSlice + struct SLANG_RT_API StringSlice { public: StringSlice(); @@ -333,7 +333,7 @@ namespace Slang }; /// String as expected by underlying platform APIs - class OSString + class SLANG_RT_API OSString { public: /// Default @@ -394,7 +394,7 @@ namespace Slang @brief Represents a UTF-8 encoded string. */ - class String + class SLANG_RT_API String { friend struct StringSlice; friend class StringBuilder; @@ -837,7 +837,7 @@ namespace Slang } }; - class StringBuilder : public String + class SLANG_RT_API StringBuilder : public String { private: enum { InitialSize = 1024 }; diff --git a/source/core/slang-token-reader.cpp b/source/core/slang-token-reader.cpp index 3be010751..7ffbc12fa 100644 --- a/source/core/slang-token-reader.cpp +++ b/source/core/slang-token-reader.cpp @@ -681,9 +681,6 @@ namespace Misc { { switch (data[i]) { - case ' ': - sb << "\\s"; - break; case '\n': sb << "\\n"; break; diff --git a/source/core/slang-token-reader.h b/source/core/slang-token-reader.h index 26539732c..bf5ca4cdc 100644 --- a/source/core/slang-token-reader.h +++ b/source/core/slang-token-reader.h @@ -295,6 +295,8 @@ namespace Misc { return result; } + String EscapeStringLiteral(String str); + String UnescapeStringLiteral(String str); } // namespace Misc } // namespace Slang diff --git a/source/core/slang-type-convert-util.cpp b/source/core/slang-type-convert-util.cpp index fbf385319..6e6598357 100644 --- a/source/core/slang-type-convert-util.cpp +++ b/source/core/slang-type-convert-util.cpp @@ -17,6 +17,7 @@ namespace Slang case SLANG_HLSL: return SLANG_SOURCE_LANGUAGE_HLSL; case SLANG_C_SOURCE: return SLANG_SOURCE_LANGUAGE_C; case SLANG_CPP_SOURCE: return SLANG_SOURCE_LANGUAGE_CPP; + case SLANG_HOST_CPP_SOURCE: return SLANG_SOURCE_LANGUAGE_CPP; case SLANG_CUDA_SOURCE: return SLANG_SOURCE_LANGUAGE_CUDA; default: break; } diff --git a/source/core/slang-type-text-util.cpp b/source/core/slang-type-text-util.cpp index 5be097d15..13bf439ce 100644 --- a/source/core/slang-type-text-util.cpp +++ b/source/core/slang-type-text-util.cpp @@ -68,11 +68,12 @@ static const CompileTargetInfo s_compileTargetInfos[] = { SLANG_SPIRV_ASM, "spv.asm", "spirv-asm,spirv-assembly" }, { SLANG_C_SOURCE, "c", "c" }, { SLANG_CPP_SOURCE, "cpp,c++,cxx", "cpp,c++,cxx" }, - { SLANG_EXECUTABLE, "exe", "exe,executable" }, - { SLANG_SHARED_LIBRARY, "dll,so", "sharedlib,sharedlibrary,dll" }, + { SLANG_HOST_CPP_SOURCE, "cpp,c++,cxx", "cpp,c++,cxx"}, + { SLANG_HOST_EXECUTABLE,"exe", "exe,executable" }, + { SLANG_SHADER_SHARED_LIBRARY, "dll,so", "sharedlib,sharedlibrary,dll" }, { SLANG_CUDA_SOURCE, "cu", "cuda,cu" }, { SLANG_PTX, "ptx", "ptx" }, - { SLANG_HOST_CALLABLE, "", "host-callable,callable" }, + { SLANG_SHADER_HOST_CALLABLE, "", "host-callable,callable" }, { SLANG_OBJECT_CODE, "obj,o", "object-code" }, }; diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang index 779900fd5..c8e05d769 100644 --- a/source/slang/core.meta.slang +++ b/source/slang/core.meta.slang @@ -66,22 +66,10 @@ syntax snorm : SNormModifier; /// Modifier to indicate that a function name should not be mangled /// by the Slang compiler. /// -/// The `__unmangled` modifier should only be valid on functions -/// and is mainly useful for the experimental heterogeneous -/// features of Slang. +/// The `__extern_cpp` modifier makes a symbol to have unmangled +/// name in source/output C++ code. /// -syntax __unmangled : UnmangledModifier; - -/// Modifier to indicate that a function name should be exported -/// directly. Used in tandem with `__unmangled` in heterogeneous -/// features of Slang. -/// -syntax __exportDirectly : __exportDirectly; - -/// Modifier to indicate that a struct is defined externally and -/// should therefore not be exported by Slang. -/// -syntax __externLib : __externLib; +syntax __extern_cpp : ExternCppModifier; /// A type that can be used as an operand for builtins [sealed] diff --git a/source/slang/slang-ast-modifier.h b/source/slang/slang-ast-modifier.h index ae9e0924e..35a8ea317 100644 --- a/source/slang/slang-ast-modifier.h +++ b/source/slang/slang-ast-modifier.h @@ -28,9 +28,7 @@ class PostfixModifier : public Modifier { SLANG_AST_CLASS(PostfixModifier)}; class ExportedModifier : public Modifier { SLANG_AST_CLASS(ExportedModifier)}; class ConstExprModifier : public Modifier { SLANG_AST_CLASS(ConstExprModifier)}; class GloballyCoherentModifier : public Modifier { SLANG_AST_CLASS(GloballyCoherentModifier)}; -class UnmangledModifier : public Modifier { SLANG_AST_CLASS(UnmangledModifier)}; -class __exportDirectly : public Modifier { SLANG_AST_CLASS(__exportDirectly)}; -class __externLib : public Modifier { SLANG_AST_CLASS(__externLib)}; +class ExternCppModifier : public Modifier { SLANG_AST_CLASS(ExternCppModifier)}; /// A modifier that indicates an `InheritanceDecl` should be ignored during name lookup (and related checks). class IgnoreForLookupModifier : public Modifier { SLANG_AST_CLASS(IgnoreForLookupModifier) }; diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index 39d558c01..14912d719 100644 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -55,7 +55,19 @@ namespace Slang // !!!!!!!!!!!!!!!!!!!!!! free functions for DiagnosicSink !!!!!!!!!!!!!!!!!!!!!!!!!!!!! - void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val) +bool isHeterogeneousTarget(CodeGenTarget target) +{ + switch (target) + { + case CodeGenTarget::HostCPPSource: + case CodeGenTarget::HostExecutable: + return true; + default: + return false; + } +} + +void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val) { switch (val) { @@ -527,6 +539,7 @@ namespace Slang case CodeGenTarget::HLSL: case CodeGenTarget::CUDASource: case CodeGenTarget::CPPSource: + case CodeGenTarget::HostCPPSource: case CodeGenTarget::CSource: { return PassThroughMode::None; @@ -555,9 +568,9 @@ namespace Slang { return PassThroughMode::Glslang; } - case CodeGenTarget::HostCallable: - case CodeGenTarget::SharedLibrary: - case CodeGenTarget::Executable: + case CodeGenTarget::ShaderHostCallable: + case CodeGenTarget::ShaderSharedLibrary: + case CodeGenTarget::HostExecutable: { // We need some C/C++ compiler return PassThroughMode::GenericCCpp; @@ -973,12 +986,11 @@ namespace Slang { switch (target) { - case CodeGenTarget::HostCallable: - case CodeGenTarget::SharedLibrary: - case CodeGenTarget::Executable: - { + case CodeGenTarget::ShaderHostCallable: + case CodeGenTarget::ShaderSharedLibrary: return CodeGenTarget::CPPSource; - } + case CodeGenTarget::HostExecutable: + return CodeGenTarget::HostCPPSource; case CodeGenTarget::PTX: return CodeGenTarget::CUDASource; case CodeGenTarget::DXBytecode: return CodeGenTarget::HLSL; case CodeGenTarget::DXIL: return CodeGenTarget::HLSL; @@ -988,6 +1000,17 @@ namespace Slang return CodeGenTarget::Unknown; } + static bool _isCPUHostTarget(CodeGenTarget target) + { + switch (target) + { + case CodeGenTarget::HostCPPSource: + case CodeGenTarget::HostExecutable: + return true; + default: + return false; + } + } SlangResult emitWithDownstreamForEntryPoints( ComponentType* program, @@ -1027,7 +1050,7 @@ namespace Slang return SLANG_FAIL; } } - + SLANG_ASSERT(compilerType != PassThroughMode::None); // Get the required downstream compiler @@ -1259,9 +1282,18 @@ namespace Slang } // If we aren't using LLVM 'host callable', we want downstream compile to produce a shared library - if (compilerType != PassThroughMode::LLVM && target == CodeGenTarget::HostCallable) + if (compilerType != PassThroughMode::LLVM && target == CodeGenTarget::ShaderHostCallable) { - target = CodeGenTarget::SharedLibrary; + target = CodeGenTarget::ShaderSharedLibrary; + } + + if (!isPassThroughEnabled(endToEndReq)) + { + if (_isCPUHostTarget(target)) + { + options.libraryPaths.add(Path::getParentDirectory(Path::getExecutablePath())); + options.libraries.add("slang-rt"); + } } options.targetType = (SlangCompileTarget)target; @@ -1527,9 +1559,9 @@ namespace Slang case CodeGenTarget::DXIL: case CodeGenTarget::DXBytecode: case CodeGenTarget::PTX: - case CodeGenTarget::HostCallable: - case CodeGenTarget::SharedLibrary: - case CodeGenTarget::Executable: + case CodeGenTarget::ShaderHostCallable: + case CodeGenTarget::ShaderSharedLibrary: + case CodeGenTarget::HostExecutable: { RefPtr<DownstreamCompileResult> downstreamResult; @@ -1583,9 +1615,9 @@ namespace Slang case CodeGenTarget::DXIL: case CodeGenTarget::DXBytecode: case CodeGenTarget::PTX: - case CodeGenTarget::HostCallable: - case CodeGenTarget::SharedLibrary: - case CodeGenTarget::Executable: + case CodeGenTarget::ShaderHostCallable: + case CodeGenTarget::ShaderSharedLibrary: + case CodeGenTarget::HostExecutable: { RefPtr<DownstreamCompileResult> downstreamResult; @@ -1606,6 +1638,7 @@ namespace Slang case CodeGenTarget::HLSL: case CodeGenTarget::CUDASource: case CodeGenTarget::CPPSource: + case CodeGenTarget::HostCPPSource: case CodeGenTarget::CSource: { RefPtr<ExtensionTracker> extensionTracker = _newExtensionTracker(target); @@ -1796,7 +1829,7 @@ namespace Slang ComPtr<ISlangBlob> blob; if (SLANG_FAILED(result.getBlob(blob))) { - if (targetReq->getTarget() == CodeGenTarget::HostCallable) + if (targetReq->getTarget() == CodeGenTarget::ShaderHostCallable) { // Some HostCallable are not directly representable as a 'binary'. // So here, we just ignore if that appears the case, and don't output an unexpected error. @@ -1840,9 +1873,9 @@ namespace Slang case CodeGenTarget::PTX: // For now we just dump PTX out as hex - case CodeGenTarget::HostCallable: - case CodeGenTarget::SharedLibrary: - case CodeGenTarget::Executable: + case CodeGenTarget::ShaderHostCallable: + case CodeGenTarget::ShaderSharedLibrary: + case CodeGenTarget::HostExecutable: HexDumpUtil::dumpWithMarkers((const uint8_t*)blobData, blobSize, 24, writer); break; @@ -2453,11 +2486,12 @@ namespace Slang case CodeGenTarget::CSource: return ".c"; case CodeGenTarget::CUDASource: return ".cu"; case CodeGenTarget::CPPSource: return ".cpp"; + case CodeGenTarget::HostCPPSource: return ".cpp"; // What these should be called is target specific, but just use these exts to make clear for now // for now - case CodeGenTarget::Executable: return ".exe"; - case CodeGenTarget::HostCallable: - case CodeGenTarget::SharedLibrary: return ".shared-lib"; + case CodeGenTarget::HostExecutable: return ".exe"; + case CodeGenTarget::ShaderHostCallable: + case CodeGenTarget::ShaderSharedLibrary: return ".shared-lib"; default: break; } return nullptr; @@ -2475,6 +2509,7 @@ namespace Slang switch (target) { case CodeGenTarget::CPPSource: + case CodeGenTarget::HostCPPSource: case CodeGenTarget::CUDASource: case CodeGenTarget::CSource: case CodeGenTarget::DXILAssembly: @@ -2513,9 +2548,9 @@ namespace Slang break; } - case CodeGenTarget::HostCallable: - case CodeGenTarget::SharedLibrary: - case CodeGenTarget::Executable: + case CodeGenTarget::ShaderHostCallable: + case CodeGenTarget::ShaderSharedLibrary: + case CodeGenTarget::HostExecutable: { dumpIntermediateBinary(compileRequest, data, size, _getTargetExtension(target)); break; diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index 5f14fb4f6..7f8257777 100755 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -71,15 +71,18 @@ namespace Slang DXILAssembly = SLANG_DXIL_ASM, CSource = SLANG_C_SOURCE, CPPSource = SLANG_CPP_SOURCE, - Executable = SLANG_EXECUTABLE, - SharedLibrary = SLANG_SHARED_LIBRARY, - HostCallable = SLANG_HOST_CALLABLE, + HostCPPSource = SLANG_HOST_CPP_SOURCE, + HostExecutable = SLANG_HOST_EXECUTABLE, + ShaderSharedLibrary = SLANG_SHADER_SHARED_LIBRARY, + ShaderHostCallable = SLANG_SHADER_HOST_CALLABLE, CUDASource = SLANG_CUDA_SOURCE, PTX = SLANG_PTX, ObjectCode = SLANG_OBJECT_CODE, CountOf = SLANG_TARGET_COUNT_OF, }; + bool isHeterogeneousTarget(CodeGenTarget target); + void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val); enum class ContainerFormat : SlangContainerFormat @@ -1457,6 +1460,7 @@ namespace Slang { lineDirectiveMode = mode; } + void setDumpIntermediates(bool value) { dumpIntermediates = value; @@ -1658,9 +1662,6 @@ namespace Slang bool m_obfuscateCode = false; - // Determine whether to output heterogeneity-related code - bool m_heterogeneous = false; - /// Holds any args that are destined for downstream compilers/tools etc DownstreamArgs m_downstreamArgs; diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp index d3dd0e5b8..eb178a366 100644 --- a/source/slang/slang-emit-c-like.cpp +++ b/source/slang/slang-emit-c-like.cpp @@ -78,6 +78,7 @@ struct CLikeSourceEmitter::ComputeEmitActionsContext return SourceLanguage::C; } case CodeGenTarget::CPPSource: + case CodeGenTarget::HostCPPSource: { return SourceLanguage::CPP; } @@ -741,28 +742,6 @@ String CLikeSourceEmitter::_generateUniqueName(const UnownedStringSlice& name) String CLikeSourceEmitter::generateName(IRInst* inst) { - // Handle `__exportDirectly` decoration before all else - if (inst->findDecoration<IR__exportDirectly>()) - { - // If instruction has a NameHint, we naively emit it as a namespace - // This is automatically handled in `getNameforNameHint` when the - // `__exportDirectly` decoration is found, so we can just return it. - // TODO: This is a very hacky solution. - // - // Another option would be to have two separate decorations, one that - // handles this namespace, and a separate decoration for unmangled names. - if (auto nameHintDecoration = inst->findDecoration<IRNameHintDecoration>()) - { - return nameHintDecoration->getName(); - } - // Otherwise, we just want the instruction to not be mangled, which is - // similarly handled in `getMangledName`. - if (auto linkageDecoration = inst->findDecoration<IRLinkageDecoration>()) - { - return linkageDecoration->getMangledName(); - } - } - // If the instruction names something // that should be emitted as a target intrinsic, // then use that name instead. @@ -802,6 +781,13 @@ String CLikeSourceEmitter::generateName(IRInst* inst) return generateEntryPointNameImpl(entryPointDecor); } + // If the instruction has a linkage decoration, just use that. + if (auto externCppDecoration = inst->findDecoration<IRExternCppDecoration>()) + { + // Just use the linkages mangled name directly. + return externCppDecoration->getName(); + } + // If we have a name hint on the instruction, then we will try to use that // to provide the basis for the actual name in the output code. if(auto nameHintDecoration = inst->findDecoration<IRNameHintDecoration>()) @@ -2915,13 +2901,6 @@ void CLikeSourceEmitter::emitStruct(IRStructType* structType) return; } - // If the selected `struct` type is externally defined - // then we also don't want to emit anything. - if (auto externLibDecoration = structType->findDecoration<IR__externLib>()) - { - return; - } - m_writer->emit("struct "); emitPostKeywordTypeAttributes(structType); diff --git a/source/slang/slang-emit-cpp.cpp b/source/slang/slang-emit-cpp.cpp index e06aa8372..e7b7af991 100644 --- a/source/slang/slang-emit-cpp.cpp +++ b/source/slang/slang-emit-cpp.cpp @@ -2,7 +2,7 @@ #include "slang-emit-cpp.h" #include "../core/slang-writer.h" - +#include "../core/slang-token-reader.h" #include "slang-emit-source-writer.h" #include "slang-mangled-lexer.h" @@ -167,6 +167,31 @@ static UnownedStringSlice _getCTypeVecPostFix(IROp op) } } +static bool _isCppTarget(CodeGenTarget target) +{ + switch (target) + { + case CodeGenTarget::CPPSource: + case CodeGenTarget::HostCPPSource: + return true; + default: + return false; + } +} + +static bool _isCppOrCudaTarget(CodeGenTarget target) +{ + switch (target) + { + case CodeGenTarget::CPPSource: + case CodeGenTarget::HostCPPSource: + case CodeGenTarget::CUDASource: + return true; + default: + return false; + } +} + /* !!!!!!!!!!!!!!!!!!!!!!!! CPPEmitHandler !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ /* static */ UnownedStringSlice CPPSourceEmitter::getBuiltinTypeName(IROp op) @@ -198,7 +223,7 @@ static UnownedStringSlice _getCTypeVecPostFix(IROp op) void CPPSourceEmitter::emitTypeDefinition(IRType* inType) { - if (m_target == CodeGenTarget::CPPSource) + if (_isCppTarget(m_target)) { // All types are templates in C++ return; @@ -432,7 +457,7 @@ SlangResult CPPSourceEmitter::calcTypeName(IRType* type, CodeGenTarget target, S auto vecCount = int(getIntVal(vecType->getElementCount())); auto elemType = vecType->getElementType(); - if (target == CodeGenTarget::CPPSource || target == CodeGenTarget::CUDASource) + if (_isCppOrCudaTarget(target)) { out << "Vector<" << _getTypeName(elemType) << ", " << vecCount << ">"; } @@ -458,7 +483,7 @@ SlangResult CPPSourceEmitter::calcTypeName(IRType* type, CodeGenTarget target, S const auto rowCount = int(getIntVal(matType->getRowCount())); const auto colCount = int(getIntVal(matType->getColumnCount())); - if (target == CodeGenTarget::CPPSource || target == CodeGenTarget::CUDASource) + if (_isCppOrCudaTarget(target)) { out << "Matrix<" << _getTypeName(elementType) << ", " << rowCount << ", " << colCount << ">"; } @@ -542,6 +567,11 @@ SlangResult CPPSourceEmitter::calcTypeName(IRType* type, CodeGenTarget target, S out << "TypeInfo*"; return SLANG_OK; } + case kIROp_StringType: + { + out << "String"; + return SLANG_OK; + } default: { if (isNominalOp(type->getOp())) @@ -2326,6 +2356,14 @@ bool CPPSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOut m_writer->emit("))"); return true; } + case kIROp_StringLit: + { + m_writer->emit("String("); + m_writer->emit(Slang::Misc::EscapeStringLiteral(as<IRStringLit>(inst)->getStringSlice())); + m_writer->emit(")"); + return true; + } + } } @@ -2361,10 +2399,9 @@ void CPPSourceEmitter::emitPreprocessorDirectivesImpl() if (m_target == CodeGenTarget::CPPSource) { - // Put all into an anonymous namespace - // This includes any generated types, and generated intrinsics - if (!m_compileRequest->getLinkage()->m_heterogeneous) - m_writer->emit("namespace { // anonymous \n\n"); + // When generating kernel code in C++, put all into an anonymous namespace + // This includes any generated types, and generated intrinsics. + m_writer->emit("namespace { // anonymous \n\n"); m_writer->emit("#ifdef SLANG_PRELUDE_NAMESPACE\n"); m_writer->emit("using namespace SLANG_PRELUDE_NAMESPACE;\n"); m_writer->emit("#endif\n\n"); @@ -2629,130 +2666,7 @@ void CPPSourceEmitter::_emitForwardDeclarations(const List<EmitAction>& actions) void CPPSourceEmitter::emitModuleImpl(IRModule* module, DiagnosticSink* sink) { - // If we are emitting a heterogeneous program - // Emit the binary blob of each non-CPP target - ComponentType* program = m_compileRequest->getProgram(); - auto linkage = m_compileRequest->getLinkage(); - if (linkage->m_heterogeneous) - { - for (auto inst : module->getGlobalInsts()) - { - auto func = as<IRFunc>(inst); - if (!func) - continue; - if (auto entryPointDecoration = func->findDecoration<IREntryPointDecoration>()) - { - String entryPointName = entryPointDecoration->getName()->getStringSlice(); - String moduleName = entryPointDecoration->getModuleName()->getStringSlice(); - for (int index = 0; index < program->getEntryPointCount(); index++) - { - auto entryPoint = program->getEntryPoint(index); - if (entryPointName == entryPoint->getName()->text) - { - for (auto targetRequest : linkage->targets) - { - // Emit for all non-CPU targets - switch (targetRequest->getTarget()) - { - case(CodeGenTarget::CPPSource): - case(CodeGenTarget::CSource): - case(CodeGenTarget::HostCallable): - case(CodeGenTarget::CUDASource): - - break; - - default: - - auto targetProgram = program->getTargetProgram(targetRequest); - CompileResult result = - targetProgram->getOrCreateEntryPointResult(index, sink); - - Slang::ComPtr<ISlangBlob> blob; - if (SLANG_FAILED(result.getBlob(blob))) - { - sink->diagnoseRaw(Severity::Error, - "Slang heterogeneous error: No blob to emit\n"); - m_writer->emit("size_t __"); - m_writer->emit(entryPointName); - m_writer->emit("Size = 0;\n"); - m_writer->emit("unsigned char __"); - m_writer->emit(entryPointName); - m_writer->emit("[1];\n"); - } - - else - { - // auto ptr = (const unsigned char*)blob->getBufferPointer(); - - // m_writer->emit("size_t __"); - // m_writer->emit(entryPointName); - // m_writer->emit("Size = "); - // m_writer->emitInt64(blob->getBufferSize()); - // m_writer->emit(";\n"); - - // m_writer->emit("unsigned char __"); - // m_writer->emit(entryPointName); - // m_writer->emit("[] = {"); - // every 20 bytes, emit a newline - // size_t j = 0; - // for (size_t i = 0; i < blob->getBufferSize(); i++) { - // m_writer->emitUInt64(ptr[i]); - // m_writer->emit(", "); - // if (j == 20) - // { - // m_writer->emit("\n"); - // j = 0; - // } - // j++; - // } - // m_writer->emit("};\n"); - } - } - } - // Hardcode in (for now) an include for slang-gfx.h so that we can make use - // of the gfx namespace - // - // TODO: Aside from making sure this approach is viable, it would also be - // much better to allow this to be done by the programmer in the Slang file. - m_writer->emit("#include \"slang-gfx.h\"\n\n"); - - // Emit boilerplate that requires gfx. - // This is required by the wrapper, so that will be the next place to look - // as far as removing boilerplate goes. - m_writer->emit("gfx::IShaderProgram* loadShaderProgram(gfx::IDevice* _0, char* _1, char* _2);\n"); - m_writer->emit("gfx::ITransientResourceHeap* buildTransientHeap(gfx::IDevice* _0);\n"); - m_writer->emit("gfx::IPipelineState* buildPipelineState(gfx::IDevice* _0, gfx::IShaderProgram* _1);\n"); - m_writer->emit("void dispatchComputation(gfx::IDevice* _0, gfx::ITransientResourceHeap* _1, gfx::IPipelineState* _2, gfx::IResourceView* _3, uint32_t gridDimsX, uint32_t gridDimsY, uint32_t gridDimsZ);\n"); - m_writer->emit("gfx::IResourceView* createBufferView(gfx::IDevice* _0, gfx::IBufferResource* _1);\n"); - m_writer->emit("gfx::IBufferResource* unconvertBuffer(RWStructuredBuffer<float> _0);\n\n"); - - // Emit a wrapper function for calling the shader blob - m_writer->emit("void "); - m_writer->emit(entryPointName); - m_writer->emit("_wrapper(gfx::IDevice* device, Vector<uint32_t, 3> gridDims, \n"); - m_writer->emit("\tRWStructuredBuffer<float> buffer)\n{"); - /* m_writer->emit("\n\tgfx_ShaderProgram_0* shaderProgram = loadShaderProgram_0(device, __"); - m_writer->emit(entryPointName); - m_writer->emit(", __"); - m_writer->emit(entryPointName); - m_writer->emit("Size);");*/ - m_writer->emit("\n\tgfx::IShaderProgram* shaderProgram = loadShaderProgram(device, \""); - m_writer->emit(entryPointName); - m_writer->emit("\", \""); - m_writer->emit(moduleName); - m_writer->emit("\");"); - m_writer->emit("\n\tgfx::ITransientResourceHeap* transientHeap = buildTransientHeap(device);"); - m_writer->emit("\n\tgfx::IPipelineState* pipelineState = "); - m_writer->emit("buildPipelineState(device, shaderProgram);"); - m_writer->emit("\n\tgfx::IResourceView* bufferView = createBufferView(device, unconvertBuffer(buffer));"); - m_writer->emit("\n\tdispatchComputation(device, transientHeap, pipelineState, "); - m_writer->emit("bufferView, gridDims.x, gridDims.y, gridDims.z);"); - m_writer->emit("\n}\n"); - } - } - } - } - } + SLANG_UNUSED(sink); // Setup all built in types used in the module m_typeSet.addAllBuiltinTypes(module); @@ -2790,9 +2704,8 @@ void CPPSourceEmitter::emitModuleImpl(IRModule* module, DiagnosticSink* sink) if (m_target == CodeGenTarget::CPPSource) { - // Need to close the anonymous namespace when outputting for C++ - if (!linkage->m_heterogeneous) - m_writer->emit("} // anonymous\n\n"); + // Need to close the anonymous namespace when outputting for C++ kernel. + m_writer->emit("} // anonymous\n\n"); } // Finally we need to output dll entry points diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp index a0ac30857..23f06e8e9 100644 --- a/source/slang/slang-emit.cpp +++ b/source/slang/slang-emit.cpp @@ -59,6 +59,8 @@ #include <assert.h> +Slang::String get_slang_cpp_host_prelude(); + namespace Slang { EntryPointLayout* findEntryPointLayout( @@ -257,6 +259,8 @@ Result linkAndOptimizeIR( CollectEntryPointUniformParamsOptions passOptions; switch( target ) { + case CodeGenTarget::HostCPPSource: + break; case CodeGenTarget::CUDASource: collectOptiXEntryPointUniformParams(irModule); #if 0 @@ -286,7 +290,7 @@ Result linkAndOptimizeIR( #endif validateIRModuleIfEnabled(compileRequest, irModule); break; - + case CodeGenTarget::HostCPPSource: case CodeGenTarget::CPPSource: case CodeGenTarget::CUDASource: break; @@ -873,6 +877,11 @@ SlangResult emitEntryPointsSourceFromIR( sourceEmitter->emitPreludeDirectives(); + if (isHeterogeneousTarget(target)) + { + sourceWriter.emit(get_slang_cpp_host_prelude()); + } + else { // If there is a prelude emit it const auto& prelude = compileRequest->getSession()->getPreludeForLanguage(sourceLanguage); diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h index a3486ee68..bcc42ad9e 100644 --- a/source/slang/slang-ir-inst-defs.h +++ b/source/slang/slang-ir-inst-defs.h @@ -558,9 +558,6 @@ INST(HighLevelDeclDecoration, highLevelDecl, 1, 0) INST(InstanceDecoration, instance, 1, 0) INST(NumThreadsDecoration, numThreads, 3, 0) - INST(__exportDirectly, __exportDirectly, 0, 0) - INST(__externLib, __externLib, 0, 0) - // Added to IRParam parameters to an entry point /* GeometryInputPrimitiveTypeDecoration */ INST(PointInputPrimitiveTypeDecoration, pointPrimitiveType, 0, 0) @@ -604,6 +601,9 @@ INST(HighLevelDeclDecoration, highLevelDecl, 1, 0) INST(ExportDecoration, export, 1, 0) INST_RANGE(LinkageDecoration, ImportDecoration, ExportDecoration) + /// An extern_cpp decoration marks the inst to emit its name without mangling for C++ interop. + INST(ExternCppDecoration, externCpp, 1, 0) + /* Decorations for RTTI objects */ INST(RTTITypeSizeDecoration, RTTI_typeSize, 1, 0) INST(AnyValueSizeDecoration, AnyValueSize, 1, 0) diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index 09a3bdbb3..102c48495 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -269,8 +269,6 @@ IR_SIMPLE_DECORATION(PublicDecoration) IR_SIMPLE_DECORATION(KeepAliveDecoration) IR_SIMPLE_DECORATION(RequiresNVAPIDecoration) IR_SIMPLE_DECORATION(NoInlineDecoration) -IR_SIMPLE_DECORATION(__exportDirectly) -IR_SIMPLE_DECORATION(__externLib) struct IRNVAPIMagicDecoration : IRDecoration { @@ -419,6 +417,19 @@ struct IRExportDecoration : IRLinkageDecoration IR_LEAF_ISA(ExportDecoration) }; +struct IRExternCppDecoration : IRDecoration +{ + enum + { + kOp = kIROp_ExternCppDecoration + }; + IR_LEAF_ISA(ExternCppDecoration) + + IRStringLit* getNameOperand() { return cast<IRStringLit>(getOperand(0)); } + + UnownedStringSlice getName() { return getNameOperand()->getStringSlice(); } +}; + struct IRFormatDecoration : IRDecoration { enum { kOp = kIROp_FormatDecoration }; @@ -2795,6 +2806,11 @@ public: addDecoration(value, kIROp_ExportDecoration, getStringValue(mangledName)); } + void addExternCppDecoration(IRInst* value, UnownedStringSlice const& mangledName) + { + addDecoration(value, kIROp_ExternCppDecoration, getStringValue(mangledName)); + } + void addEntryPointDecoration(IRInst* value, Profile profile, UnownedStringSlice const& name, UnownedStringSlice const& moduleName) { IRInst* operands[] = { getIntValue(getIntType(), profile.raw), getStringValue(name), getStringValue(moduleName) }; @@ -2866,16 +2882,6 @@ public: { addDecoration(inst, kIROp_SequentialIDDecoration, getIntValue(getUIntType(), id)); } - - void addExportDirectlyDecoration(IRInst* value) - { - addDecoration(value, kIROp___exportDirectly); - } - - void addExternLibDecoration(IRInst* value) - { - addDecoration(value, kIROp___externLib); - } }; void addHoistableInst( diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index 9ec8c1c71..779034979 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -1047,13 +1047,9 @@ static void addLinkageDecoration( builder->addPublicDecoration(inst); builder->addKeepAliveDecoration(inst); } - if (decl->findModifier<__exportDirectly>()) + if (decl->findModifier<ExternCppModifier>()) { - builder->addExportDirectlyDecoration(inst); - } - if (decl->findModifier<__externLib>()) - { - builder->addExternLibDecoration(inst); + builder->addExternCppDecoration(inst, mangledName); } } @@ -1994,12 +1990,7 @@ static String getNameForNameHint( StringBuilder sb; sb.append(parentName); - if (decl->hasModifier<__exportDirectly>()) { - sb.append("::"); - } - else { - sb.append("."); - } + sb.append("."); sb.append(leafName->text); return sb.ProduceString(); diff --git a/source/slang/slang-mangle.cpp b/source/slang/slang-mangle.cpp index acb561531..e6c0a8e7f 100644 --- a/source/slang/slang-mangle.cpp +++ b/source/slang/slang-mangle.cpp @@ -455,9 +455,9 @@ namespace Slang auto decl = declRef.getDecl(); - // Handle `__unmangled` modifier by simply emitting + // Handle `__extern_cpp` modifier by simply emitting // the given name. - if (decl->hasModifier<UnmangledModifier>()) + if (decl->hasModifier<ExternCppModifier>()) { emit(context, decl->getName()->text); return; diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp index b40dedc99..2d5e1aeea 100644 --- a/source/slang/slang-options.cpp +++ b/source/slang/slang-options.cpp @@ -1161,10 +1161,6 @@ struct OptionsParser rawEntryPoints.add(rawEntryPoint); } - else if (argValue == "-heterogeneous") - { - requestImpl->getLinkage()->m_heterogeneous = true; - } else if (argValue == "-lang") { CommandLineArg name; @@ -1995,9 +1991,9 @@ struct OptionsParser case CodeGenTarget::CPPSource: case CodeGenTarget::PTX: case CodeGenTarget::CUDASource: - case CodeGenTarget::HostCallable: - case CodeGenTarget::Executable: - case CodeGenTarget::SharedLibrary: + case CodeGenTarget::ShaderHostCallable: + case CodeGenTarget::HostExecutable: + case CodeGenTarget::ShaderSharedLibrary: rawOutput.isWholeProgram = true; break; default: diff --git a/source/slang/slang-parameter-binding.cpp b/source/slang/slang-parameter-binding.cpp index 7fbc59dc7..7bff7118e 100644 --- a/source/slang/slang-parameter-binding.cpp +++ b/source/slang/slang-parameter-binding.cpp @@ -3033,9 +3033,9 @@ static bool _isCPUTarget(CodeGenTarget target) { case CodeGenTarget::CPPSource: case CodeGenTarget::CSource: - case CodeGenTarget::Executable: - case CodeGenTarget::SharedLibrary: - case CodeGenTarget::HostCallable: + case CodeGenTarget::HostExecutable: + case CodeGenTarget::ShaderSharedLibrary: + case CodeGenTarget::ShaderHostCallable: { return true; } diff --git a/source/slang/slang-type-layout.cpp b/source/slang/slang-type-layout.cpp index b48e70eae..cd81c6173 100644 --- a/source/slang/slang-type-layout.cpp +++ b/source/slang/slang-type-layout.cpp @@ -1403,9 +1403,9 @@ LayoutRulesFamilyImpl* getDefaultLayoutRulesFamilyForTarget(TargetRequest* targe case CodeGenTarget::SPIRVAssembly: return &kGLSLLayoutRulesFamilyImpl; - case CodeGenTarget::HostCallable: - case CodeGenTarget::Executable: - case CodeGenTarget::SharedLibrary: + case CodeGenTarget::ShaderHostCallable: + case CodeGenTarget::HostExecutable: + case CodeGenTarget::ShaderSharedLibrary: case CodeGenTarget::CPPSource: case CodeGenTarget::CSource: { @@ -1610,9 +1610,9 @@ bool isCPUTarget(TargetRequest* targetReq) case CodeGenTarget::CPPSource: case CodeGenTarget::CSource: - case CodeGenTarget::HostCallable: - case CodeGenTarget::Executable: - case CodeGenTarget::SharedLibrary: + case CodeGenTarget::ShaderHostCallable: + case CodeGenTarget::HostExecutable: + case CodeGenTarget::ShaderSharedLibrary: return true; } } diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index e0b11604c..e83ab2da3 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -215,8 +215,8 @@ void Session::_initCodeGenTransitionMap() // We *don't* add a default for host callable, as we will determine what is suitable depending on what // is available. We prefer LLVM if that's available. If it's not we can use generic C/C++ compiler - map.addTransition(source, CodeGenTarget::SharedLibrary, PassThroughMode::GenericCCpp); - map.addTransition(source, CodeGenTarget::Executable, PassThroughMode::GenericCCpp); + map.addTransition(source, CodeGenTarget::ShaderSharedLibrary, PassThroughMode::GenericCCpp); + map.addTransition(source, CodeGenTarget::HostExecutable, PassThroughMode::GenericCCpp); map.addTransition(source, CodeGenTarget::ObjectCode, PassThroughMode::GenericCCpp); } } @@ -666,7 +666,7 @@ SlangPassThrough Session::getDownstreamCompilerForTransition(SlangCompileTarget } // Special case host-callable - if (target == CodeGenTarget::HostCallable) + if (target == CodeGenTarget::ShaderHostCallable) { if (source == CodeGenTarget::CSource || source == CodeGenTarget::CPPSource) { @@ -1326,9 +1326,9 @@ CapabilitySet TargetRequest::getTargetCaps() break; case CodeGenTarget::CPPSource: - case CodeGenTarget::Executable: - case CodeGenTarget::SharedLibrary: - case CodeGenTarget::HostCallable: + case CodeGenTarget::HostExecutable: + case CodeGenTarget::ShaderSharedLibrary: + case CodeGenTarget::ShaderHostCallable: atoms.add(CapabilityAtom::CPP); break; |
