summaryrefslogtreecommitdiffstats
path: root/source/slang
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2020-06-18 15:06:14 -0700
committerGitHub <noreply@github.com>2020-06-18 15:06:14 -0700
commit515d8eb0cd719ae31db2f6e03751011a123bc0ba (patch)
tree3e78893a74af856fb29158078bed7099a567f5dd /source/slang
parente2d21026d115dc61296b47dcc990534f1844bc7f (diff)
parentaa6aca498cd1f7fbbdb143e72dd48b1d714c8fbb (diff)
Merge branch 'master' into feature/prelude-fix
Diffstat (limited to 'source/slang')
-rw-r--r--source/slang/slang-check-shader.cpp2
-rw-r--r--source/slang/slang-compiler.cpp95
-rw-r--r--source/slang/slang-compiler.h22
-rw-r--r--source/slang/slang-dxc-support.cpp4
-rw-r--r--source/slang/slang-emit-c-like.cpp64
-rw-r--r--source/slang/slang-emit-c-like.h23
-rw-r--r--source/slang/slang-emit-cpp.cpp195
-rw-r--r--source/slang/slang-emit-cpp.h13
-rw-r--r--source/slang/slang-emit-cuda.cpp6
-rw-r--r--source/slang/slang-emit-glsl.cpp10
-rw-r--r--source/slang/slang-emit-hlsl.cpp8
-rw-r--r--source/slang/slang-emit-spirv.cpp6
-rw-r--r--source/slang/slang-emit.cpp63
-rw-r--r--source/slang/slang-ir-glsl-legalize.cpp2
-rw-r--r--source/slang/slang-ir-inst-defs.h11
-rw-r--r--source/slang/slang-ir-insts.h23
-rw-r--r--source/slang/slang-ir-lower-generics.cpp31
-rw-r--r--source/slang/slang-ir.cpp14
-rw-r--r--source/slang/slang-lower-to-ir.cpp22
-rw-r--r--source/slang/slang-options.cpp24
-rw-r--r--source/slang/slang-parameter-binding.cpp2
-rw-r--r--source/slang/slang-profile.h8
-rw-r--r--source/slang/slang-reflection.cpp4
-rw-r--r--source/slang/slang-repro.cpp (renamed from source/slang/slang-state-serialize.cpp)93
-rw-r--r--source/slang/slang-repro.h (renamed from source/slang/slang-state-serialize.h)14
-rw-r--r--source/slang/slang-type-layout.cpp4
-rw-r--r--source/slang/slang.cpp87
-rw-r--r--source/slang/slang.vcxproj4
-rw-r--r--source/slang/slang.vcxproj.filters8
29 files changed, 558 insertions, 304 deletions
diff --git a/source/slang/slang-check-shader.cpp b/source/slang/slang-check-shader.cpp
index ab1c7f580..17ca9fc78 100644
--- a/source/slang/slang-check-shader.cpp
+++ b/source/slang/slang-check-shader.cpp
@@ -544,7 +544,7 @@ namespace Slang
auto entryPointProfile = entryPointReq->getProfile();
if( auto entryPointAttribute = entryPointFuncDecl->findModifier<EntryPointAttribute>() )
{
- auto entryPointStage = entryPointProfile.GetStage();
+ auto entryPointStage = entryPointProfile.getStage();
if( entryPointStage == Stage::Unknown )
{
entryPointProfile.setStage(entryPointAttribute->stage);
diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp
index 729c0077a..fe0f7d69c 100644
--- a/source/slang/slang-compiler.cpp
+++ b/source/slang/slang-compiler.cpp
@@ -320,7 +320,7 @@ namespace Slang
//
- Profile Profile::LookUp(char const* name)
+ Profile Profile::lookUp(char const* name)
{
#define PROFILE(TAG, NAME, STAGE, VERSION) if(strcmp(name, #NAME) == 0) return Profile::TAG;
#define PROFILE_ALIAS(TAG, DEF, NAME) if(strcmp(name, #NAME) == 0) return Profile::TAG;
@@ -408,36 +408,58 @@ namespace Slang
return session->getOrLoadDownstreamCompiler(passThrough, nullptr) ? SLANG_OK: SLANG_E_NOT_FOUND;
}
- PassThroughMode getPreludeDownstreamCompilerForTarget(Session* session, CodeGenTarget target)
+ SourceLanguage getDefaultSourceLanguageForDownstreamCompiler(PassThroughMode compiler)
{
- switch (target)
+ switch (compiler)
{
- case CodeGenTarget::None:
+ case PassThroughMode::None:
{
- return PassThroughMode::None;
+ return SourceLanguage::Unknown;
}
- case CodeGenTarget::GLSL:
+ case PassThroughMode::Fxc:
+ case PassThroughMode::Dxc:
{
- // For the prelude we'll use Glslang
- return PassThroughMode::Glslang;
+ return SourceLanguage::HLSL;
}
- case CodeGenTarget::HLSL:
+ case PassThroughMode::Glslang:
{
- // Use the default compiler for the source language if set,
- DownstreamCompiler* downstreamCompiler = session->getDefaultDownstreamCompiler(SourceLanguage::HLSL);
- if (downstreamCompiler)
- {
- return PassThroughMode(downstreamCompiler->getDesc().type);
- }
- else
- {
- // This is ambiguous, because we could use dxc or fxc. For now we'll go with Dxc.
- return PassThroughMode::Dxc;
- }
+ return SourceLanguage::GLSL;
+ }
+ case PassThroughMode::Clang:
+ case PassThroughMode::VisualStudio:
+ case PassThroughMode::Gcc:
+ case PassThroughMode::GenericCCpp:
+ {
+ // These could ingest C, but we only have this function to work out a
+ // 'default' language to ingest.
+ return SourceLanguage::CPP;
}
+ case PassThroughMode::NVRTC:
+ {
+ return SourceLanguage::CUDA;
+ }
+ default: break;
+ }
+ SLANG_ASSERT(!"Unknown compiler");
+ return SourceLanguage::Unknown;
+ }
+
+ PassThroughMode getDownstreamCompilerRequiredForTarget(CodeGenTarget target)
+ {
+ switch (target)
+ {
+ // Don't *require* a downstream compiler for source output
+ case CodeGenTarget::GLSL:
+ case CodeGenTarget::HLSL:
case CodeGenTarget::CUDASource:
+ case CodeGenTarget::CPPSource:
+ case CodeGenTarget::CSource:
{
- return PassThroughMode::NVRTC;
+ return PassThroughMode::None;
+ }
+ case CodeGenTarget::None:
+ {
+ return PassThroughMode::None;
}
case CodeGenTarget::SPIRVAssembly:
case CodeGenTarget::SPIRV:
@@ -459,12 +481,6 @@ namespace Slang
{
return PassThroughMode::Glslang;
}
- case CodeGenTarget::CPPSource:
- case CodeGenTarget::CSource:
- {
- // We'll just use the generic C/C++ compiler
- return PassThroughMode::GenericCCpp;
- }
case CodeGenTarget::HostCallable:
case CodeGenTarget::SharedLibrary:
case CodeGenTarget::Executable:
@@ -484,28 +500,9 @@ namespace Slang
return PassThroughMode::None;
}
- PassThroughMode getDownstreamCompilerRequiredForTarget(Session* session, CodeGenTarget target)
- {
- switch (target)
- {
- // Don't *require* a downstream compiler for source output
- case CodeGenTarget::GLSL:
- case CodeGenTarget::HLSL:
- case CodeGenTarget::CUDASource:
- case CodeGenTarget::CPPSource:
- case CodeGenTarget::CSource:
- {
- return PassThroughMode::None;
- }
- default: break;
- }
-
- return getPreludeDownstreamCompilerForTarget(session, target);
- }
-
SlangResult checkCompileTargetSupport(Session* session, CodeGenTarget target)
{
- const PassThroughMode mode = getDownstreamCompilerRequiredForTarget(session, target);
+ const PassThroughMode mode = getDownstreamCompilerRequiredForTarget(target);
return (mode != PassThroughMode::None) ?
checkExternalCompilerSupport(session, mode) :
SLANG_OK;
@@ -634,7 +631,7 @@ namespace Slang
}
char const* stagePrefix = nullptr;
- switch( profile.GetStage() )
+ switch( profile.getStage() )
{
// Note: All of the raytracing-related stages require
// compiling for a `lib_*` profile, even when only a
@@ -669,7 +666,7 @@ namespace Slang
}
char const* versionSuffix = nullptr;
- switch(profile.GetVersion())
+ switch(profile.getVersion())
{
#define CASE(TAG, SUFFIX) case ProfileVersion::TAG: versionSuffix = #SUFFIX; break
CASE(DX_4_0, _4_0);
diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h
index b1edbe602..e4b537e19 100644
--- a/source/slang/slang-compiler.h
+++ b/source/slang/slang-compiler.h
@@ -180,7 +180,7 @@ namespace Slang
Name* getName() { return m_name; }
/// Get the stage that the entry point is to be compiled for
- Stage getStage() { return m_profile.GetStage(); }
+ Stage getStage() { return m_profile.getStage(); }
/// Get the profile that the entry point is to be compiled for
Profile getProfile() { return m_profile; }
@@ -725,7 +725,7 @@ namespace Slang
Profile getProfile() { return m_profile; }
/// Get the stage that the entry point is for.
- Stage getStage() { return m_profile.GetStage(); }
+ Stage getStage() { return m_profile.getStage(); }
/// Get the module that contains the entry point.
Module* getModule();
@@ -1191,9 +1191,9 @@ namespace Slang
};
/// Given a target returns the required downstream compiler
- PassThroughMode getDownstreamCompilerRequiredForTarget(Session* session, CodeGenTarget target);
+ PassThroughMode getDownstreamCompilerRequiredForTarget(CodeGenTarget target);
/// Given a target returns a downstream compiler the prelude should be taken from.
- PassThroughMode getPreludeDownstreamCompilerForTarget(Session* session, CodeGenTarget target);
+ SourceLanguage getDefaultSourceLanguageForDownstreamCompiler(PassThroughMode compiler);
struct TypeCheckingCache;
@@ -2033,7 +2033,10 @@ namespace Slang
SLANG_NO_THROW SlangPassThrough SLANG_MCALL getDefaultDownstreamCompiler(SlangSourceLanguage sourceLanguage) override;
- /// Get the default cpp compiler for a language
+ SLANG_NO_THROW void SLANG_MCALL setLanguagePrelude(SlangSourceLanguage inSourceLanguage, char const* prelude) override;
+ SLANG_NO_THROW void SLANG_MCALL getLanguagePrelude(SlangSourceLanguage inSourceLanguage, ISlangBlob** outPrelude) override;
+
+ /// Get the default compiler for a language
DownstreamCompiler* getDefaultDownstreamCompiler(SourceLanguage sourceLanguage);
enum class SharedLibraryFuncType
@@ -2103,8 +2106,8 @@ namespace Slang
SlangFuncPtr getSharedLibraryFunc(SharedLibraryFuncType type, DiagnosticSink* sink);
- /// Get the downstream compiler prelude
- const String& getDownstreamCompilerPrelude(PassThroughMode mode) { return m_downstreamCompilerPreludes[int(mode)]; }
+ /// Get the prelude associated with the language
+ const String& getPreludeForLanguage(SourceLanguage language) { return m_languagePreludes[int(language)]; }
void init();
@@ -2128,12 +2131,11 @@ namespace Slang
SlangResult _loadRequest(EndToEndCompileRequest* request, const void* data, size_t size);
-
/// Linkage used for all built-in (stdlib) code.
RefPtr<Linkage> m_builtinLinkage;
- String m_downstreamCompilerPaths[int(PassThroughMode::CountOf)]; ///< Paths for each pass through
- String m_downstreamCompilerPreludes[int(PassThroughMode::CountOf)]; ///< Prelude for each type of target
+ String m_downstreamCompilerPaths[int(PassThroughMode::CountOf)]; ///< Paths for each pass through
+ String m_languagePreludes[int(SourceLanguage::CountOf)]; ///< Prelude for each source language
PassThroughMode m_defaultDownstreamCompilers[int(SourceLanguage::CountOf)];
};
diff --git a/source/slang/slang-dxc-support.cpp b/source/slang/slang-dxc-support.cpp
index 4fe8e64ca..ffcc405c8 100644
--- a/source/slang/slang-dxc-support.cpp
+++ b/source/slang/slang-dxc-support.cpp
@@ -185,7 +185,7 @@ namespace Slang
// TODO: Ideally the dxc back-end should be passed some information
// on the "capabilities" that were used and/or requested in the code.
//
- if( profile.GetVersion() >= ProfileVersion::DX_6_2 )
+ if( profile.getVersion() >= ProfileVersion::DX_6_2 )
{
args[argCount++] = L"-enable-16bit-types";
}
@@ -195,7 +195,7 @@ namespace Slang
ComPtr<IDxcOperationResult> dxcResult;
SLANG_RETURN_ON_FAIL(dxcCompiler->Compile(dxcSourceBlob,
sourcePath.toWString().begin(),
- profile.GetStage() == Stage::Unknown ? L"" : wideEntryPointName.begin(),
+ profile.getStage() == Stage::Unknown ? L"" : wideEntryPointName.begin(),
wideProfileName.begin(),
args,
argCount,
diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp
index eae3bdedc..6c004c84c 100644
--- a/source/slang/slang-emit-c-like.cpp
+++ b/source/slang/slang-emit-c-like.cpp
@@ -78,7 +78,7 @@ struct CLikeSourceEmitter::ComputeEmitActionsContext
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!! CLikeSourceEmitter !!!!!!!!!!!!!!!!!!!!!!!!!! */
-/* static */CLikeSourceEmitter::SourceStyle CLikeSourceEmitter::getSourceStyle(CodeGenTarget target)
+/* static */SourceLanguage CLikeSourceEmitter::getSourceLanguage(CodeGenTarget target)
{
switch (target)
{
@@ -86,17 +86,17 @@ struct CLikeSourceEmitter::ComputeEmitActionsContext
case CodeGenTarget::Unknown:
case CodeGenTarget::None:
{
- return SourceStyle::Unknown;
+ return SourceLanguage::Unknown;
}
case CodeGenTarget::GLSL:
case CodeGenTarget::GLSL_Vulkan:
case CodeGenTarget::GLSL_Vulkan_OneDesc:
{
- return SourceStyle::GLSL;
+ return SourceLanguage::GLSL;
}
case CodeGenTarget::HLSL:
{
- return SourceStyle::HLSL;
+ return SourceLanguage::HLSL;
}
case CodeGenTarget::PTX:
case CodeGenTarget::SPIRV:
@@ -106,19 +106,19 @@ struct CLikeSourceEmitter::ComputeEmitActionsContext
case CodeGenTarget::DXIL:
case CodeGenTarget::DXILAssembly:
{
- return SourceStyle::Unknown;
+ return SourceLanguage::Unknown;
}
case CodeGenTarget::CSource:
{
- return SourceStyle::C;
+ return SourceLanguage::C;
}
case CodeGenTarget::CPPSource:
{
- return SourceStyle::CPP;
+ return SourceLanguage::CPP;
}
case CodeGenTarget::CUDASource:
{
- return SourceStyle::CUDA;
+ return SourceLanguage::CUDA;
}
}
}
@@ -126,8 +126,8 @@ struct CLikeSourceEmitter::ComputeEmitActionsContext
CLikeSourceEmitter::CLikeSourceEmitter(const Desc& desc)
{
m_writer = desc.sourceWriter;
- m_sourceStyle = getSourceStyle(desc.target);
- SLANG_ASSERT(m_sourceStyle != SourceStyle::Unknown);
+ m_sourceLanguage = getSourceLanguage(desc.target);
+ SLANG_ASSERT(m_sourceLanguage != SourceLanguage::Unknown);
m_target = desc.target;
@@ -389,17 +389,17 @@ void CLikeSourceEmitter::maybeCloseParens(bool needClose)
bool CLikeSourceEmitter::isTargetIntrinsicModifierApplicable(const String& targetName)
{
- switch(getSourceStyle())
+ switch(getSourceLanguage())
{
default:
SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "unhandled code generation target");
return false;
- case SourceStyle::C: return targetName == "c";
- case SourceStyle::CPP: return targetName == "cpp";
- case SourceStyle::GLSL: return targetName == "glsl";
- case SourceStyle::HLSL: return targetName == "hlsl";
- case SourceStyle::CUDA: return targetName == "cuda";
+ case SourceLanguage::C: return targetName == "c";
+ case SourceLanguage::CPP: return targetName == "cpp";
+ case SourceLanguage::GLSL: return targetName == "glsl";
+ case SourceLanguage::HLSL: return targetName == "hlsl";
+ case SourceLanguage::CUDA: return targetName == "cuda";
}
}
@@ -552,7 +552,7 @@ String CLikeSourceEmitter::scrubName(const String& name)
// and write some legal characters to the output as we go.
StringBuilder sb;
- if(getSourceStyle() == SourceStyle::GLSL)
+ if(getSourceLanguage() == SourceLanguage::GLSL)
{
// GLSL reserves all names that start with `gl_`,
// so if we are in danger of collision, then make
@@ -667,7 +667,7 @@ String CLikeSourceEmitter::generateName(IRInst* inst)
auto entryPointDecor = inst->findDecoration<IREntryPointDecoration>();
if (entryPointDecor)
{
- if (getSourceStyle() == SourceStyle::GLSL)
+ if (getSourceLanguage() == SourceLanguage::GLSL)
{
// GLSL will always need to use `main` as the
// name for an entry-point function, but other
@@ -1011,7 +1011,7 @@ bool CLikeSourceEmitter::shouldFoldInstIntoUseSites(IRInst* inst)
// GLSL doesn't allow texture/resource types to
// be used as first-class values, so we need
// to fold them into their use sites in all cases
- if (getSourceStyle() == SourceStyle::GLSL)
+ if (getSourceLanguage() == SourceLanguage::GLSL)
{
if(as<IRResourceTypeBase>(type))
{
@@ -1219,12 +1219,12 @@ void CLikeSourceEmitter::emitInstResultDecl(IRInst* inst)
{
// "Ordinary" instructions at module scope are constants
- switch (getSourceStyle())
+ switch (getSourceLanguage())
{
- case SourceStyle::CUDA:
- case SourceStyle::HLSL:
- case SourceStyle::C:
- case SourceStyle::CPP:
+ case SourceLanguage::CUDA:
+ case SourceLanguage::HLSL:
+ case SourceLanguage::C:
+ case SourceLanguage::CPP:
m_writer->emit("static ");
break;
@@ -1652,7 +1652,7 @@ void CLikeSourceEmitter::emitIntrinsicCallExprImpl(
for(IRIntegerValue ii = elementCount; ii < 4; ++ii)
{
m_writer->emit(", ");
- if(getSourceStyle() == SourceStyle::GLSL)
+ if(getSourceLanguage() == SourceLanguage::GLSL)
{
emitSimpleType(elementType);
m_writer->emit("(0)");
@@ -1710,7 +1710,7 @@ void CLikeSourceEmitter::emitIntrinsicCallExprImpl(
auto arg = args[argIndex].get();
if(arg->op == kIROp_ImageSubscript)
{
- if(getSourceStyle() == SourceStyle::GLSL)
+ if(getSourceLanguage() == SourceLanguage::GLSL)
{
// TODO: we don't handle the multisample
// case correctly here, where the last
@@ -2003,7 +2003,7 @@ void CLikeSourceEmitter::defaultEmitInstExpr(IRInst* inst, const EmitOpInfo& inO
auto base = fieldExtract->getBase();
emitOperand(base, leftSide(outerPrec, prec));
m_writer->emit(".");
- if(getSourceStyle() == SourceStyle::GLSL
+ if(getSourceLanguage() == SourceLanguage::GLSL
&& as<IRUniformParameterGroupType>(base->getDataType()))
{
m_writer->emit("_data.");
@@ -2023,7 +2023,7 @@ void CLikeSourceEmitter::defaultEmitInstExpr(IRInst* inst, const EmitOpInfo& inO
auto base = ii->getBase();
emitOperand(base, leftSide(outerPrec, prec));
m_writer->emit(".");
- if(getSourceStyle() == SourceStyle::GLSL
+ if(getSourceLanguage() == SourceLanguage::GLSL
&& as<IRUniformParameterGroupType>(base->getDataType()))
{
m_writer->emit("_data.");
@@ -2120,7 +2120,7 @@ void CLikeSourceEmitter::defaultEmitInstExpr(IRInst* inst, const EmitOpInfo& inO
{
auto base = inst->getOperand(0);
emitOperand(base, outerPrec);
- if(getSourceStyle() == SourceStyle::GLSL
+ if(getSourceLanguage() == SourceLanguage::GLSL
&& as<IRUniformParameterGroupType>(base->getDataType()))
{
m_writer->emit("._data");
@@ -3240,7 +3240,7 @@ void CLikeSourceEmitter::emitStruct(IRStructType* structType)
continue;
// Note: GLSL doesn't support interpolation modifiers on `struct` fields
- if( getSourceStyle() != SourceStyle::GLSL )
+ if( getSourceLanguage() != SourceLanguage::GLSL )
{
emitInterpolationModifiers(fieldKey, fieldType, nullptr);
}
@@ -3455,9 +3455,9 @@ void CLikeSourceEmitter::emitGlobalVar(IRGlobalVar* varDecl)
// shader parameter) may need special
// modifiers to indicate it as such.
//
- switch (getSourceStyle())
+ switch (getSourceLanguage())
{
- case SourceStyle::HLSL:
+ case SourceLanguage::HLSL:
// HLSL requires the `static` modifier on any
// global variables; otherwise they are assumed
// to be uniforms.
diff --git a/source/slang/slang-emit-c-like.h b/source/slang/slang-emit-c-like.h
index bead26db3..453a8dbbf 100644
--- a/source/slang/slang-emit-c-like.h
+++ b/source/slang/slang-emit-c-like.h
@@ -38,18 +38,6 @@ public:
kThreadGroupAxisCount = 3,
};
- /// To simplify cases
- enum class SourceStyle
- {
- Unknown,
- GLSL,
- HLSL,
- C,
- CPP,
- CUDA,
- CountOf,
- };
-
typedef unsigned int ESemanticMask;
enum
{
@@ -113,7 +101,7 @@ public:
/// Get the code gen target
CodeGenTarget getTarget() { return m_target; }
/// Get the source style
- SLANG_FORCE_INLINE SourceStyle getSourceStyle() const { return m_sourceStyle; }
+ SLANG_FORCE_INLINE SourceLanguage getSourceLanguage() const { return m_sourceLanguage; }
void noteInternalErrorLoc(SourceLoc loc) { return getSink()->noteInternalErrorLoc(loc); }
@@ -298,8 +286,9 @@ public:
virtual RefObject* getExtensionTracker() { return nullptr; }
- /// Gets a source style for a target. Returns Unknown if not a known target
- static SourceStyle getSourceStyle(CodeGenTarget target);
+ /// Gets a source language for a target for a target. Returns Unknown if not a known target
+ static SourceLanguage getSourceLanguage(CodeGenTarget target);
+
/// Gets the default type name for built in scalar types. Different impls may require something different.
/// Returns an empty slice if not a built in type
static UnownedStringSlice getDefaultBuiltinTypeName(IROp op);
@@ -372,8 +361,8 @@ public:
// The target language we want to generate code for
CodeGenTarget m_target;
- // Source style - a simplification of the more nuanced m_target
- SourceStyle m_sourceStyle;
+ // Source language (based on the more nuanced m_target)
+ SourceLanguage m_sourceLanguage;
// Where source is written to
SourceWriter* m_writer;
diff --git a/source/slang/slang-emit-cpp.cpp b/source/slang/slang-emit-cpp.cpp
index c31ef3bc7..accb290fa 100644
--- a/source/slang/slang-emit-cpp.cpp
+++ b/source/slang/slang-emit-cpp.cpp
@@ -1446,6 +1446,24 @@ UnownedStringSlice CPPSourceEmitter::_getFuncName(const HLSLIntrinsic* specOp)
return m_slicePool.getSlice(handle);
}
+UnownedStringSlice CPPSourceEmitter::_getWitnessTableWrapperFuncName(IRFunc* func)
+{
+ StringSlicePool::Handle handle = StringSlicePool::kNullHandle;
+ if (m_witnessTableWrapperFuncNameMap.TryGetValue(func, handle))
+ {
+ return m_slicePool.getSlice(handle);
+ }
+
+ StringBuilder builder;
+ builder << getName(func) << "_wtwrapper";
+
+ handle = m_slicePool.add(builder);
+ m_witnessTableWrapperFuncNameMap.Add(func, handle);
+
+ SLANG_ASSERT(handle != StringSlicePool::kNullHandle);
+ return m_slicePool.getSlice(handle);
+}
+
SlangResult CPPSourceEmitter::calcFuncName(const HLSLIntrinsic* specOp, StringBuilder& outBuilder)
{
typedef HLSLIntrinsic::Op Op;
@@ -1591,6 +1609,83 @@ void CPPSourceEmitter::emitWitnessTable(IRWitnessTable* witnessTable)
pendingWitnessTableDefinitions.add(witnessTable);
}
+void CPPSourceEmitter::_emitWitnessTableWrappers()
+{
+ for (auto witnessTable : pendingWitnessTableDefinitions)
+ {
+ for (auto child : witnessTable->getChildren())
+ {
+ if (auto entry = as<IRWitnessTableEntry>(child))
+ {
+ if (auto funcVal = as<IRFunc>(entry->getSatisfyingVal()))
+ {
+ emitType(funcVal->getResultType());
+ m_writer->emit(" ");
+ m_writer->emit(_getWitnessTableWrapperFuncName(funcVal));
+ m_writer->emit("(");
+ // Emit parameter list.
+ {
+ bool isFirst = true;
+ for (auto param : funcVal->getParams())
+ {
+ if (as<IRTypeType>(param->getFullType()))
+ continue;
+
+ if (isFirst)
+ isFirst = false;
+ else
+ m_writer->emit(",");
+
+ if (param->findDecoration<IRThisPointerDecoration>())
+ {
+ m_writer->emit("void* ");
+ m_writer->emit(getName(param));
+ continue;
+ }
+ emitSimpleFuncParamImpl(param);
+ }
+ }
+ m_writer->emit(")\n{\n");
+ m_writer->indent();
+ m_writer->emit("return ");
+ m_writer->emit(getName(funcVal));
+ m_writer->emit("(");
+ // Emit argument list.
+ {
+ bool isFirst = true;
+ for (auto param : funcVal->getParams())
+ {
+ if (as<IRTypeType>(param->getFullType()))
+ continue;
+
+ if (isFirst)
+ isFirst = false;
+ else
+ m_writer->emit(", ");
+
+ if (param->findDecoration<IRThisPointerDecoration>())
+ {
+ m_writer->emit("*static_cast<");
+ emitType(param->getFullType());
+ m_writer->emit("*>(");
+ m_writer->emit(getName(param));
+ m_writer->emit(")");
+ }
+ else
+ {
+ m_writer->emit(getName(param));
+ }
+ }
+ }
+ m_writer->emit(");\n");
+ m_writer->dedent();
+ m_writer->emit("}\n");
+ }
+ }
+ }
+ }
+}
+
void CPPSourceEmitter::_emitWitnessTableDefinitions()
{
for (auto witnessTable : pendingWitnessTableDefinitions)
@@ -1612,8 +1707,9 @@ void CPPSourceEmitter::_emitWitnessTableDefinitions()
m_writer->emit(",\n");
else
isFirstEntry = false;
- m_writer->emit("&Context::");
- m_writer->emit(getName(funcVal));
+
+ m_writer->emit("&KernelContext::");
+ m_writer->emit(_getWitnessTableWrapperFuncName(funcVal));
}
else
{
@@ -1660,7 +1756,7 @@ void CPPSourceEmitter::_maybeEmitWitnessTableTypeDefinition(
else
isFirstEntry = false;
emitType(funcVal->getResultType());
- m_writer->emit(" (Context::*");
+ m_writer->emit(" (KernelContext::*");
m_writer->emit(getName(entry->requirementKey.get()));
m_writer->emit(")");
m_writer->emit("(");
@@ -1671,7 +1767,13 @@ void CPPSourceEmitter::_maybeEmitWitnessTableTypeDefinition(
m_writer->emit(", ");
else
isFirstParam = false;
- emitParamType(param->getFullType(), getName(param));
+ if (param->findDecoration<IRThisPointerDecoration>())
+ {
+ m_writer->emit("void* ");
+ m_writer->emit(getName(param));
+ continue;
+ }
+ emitSimpleFuncParamImpl(param);
}
m_writer->emit(");\n");
}
@@ -1681,7 +1783,7 @@ void CPPSourceEmitter::_maybeEmitWitnessTableTypeDefinition(
}
}
m_writer->dedent();
- m_writer->emit("\n};\n");
+ m_writer->emit("};\n");
}
bool CPPSourceEmitter::tryEmitGlobalParamImpl(IRGlobalParam* varDecl, IRType* varType)
@@ -1742,7 +1844,7 @@ void CPPSourceEmitter::emitEntryPointAttributesImpl(IRFunc* irFunc, IREntryPoint
SLANG_UNUSED(entryPointDecor);
auto profile = m_effectiveProfile;
- auto stage = profile.GetStage();
+ auto stage = profile.getStage();
switch (stage)
{
@@ -1877,6 +1979,31 @@ void CPPSourceEmitter::emitSimpleValueImpl(IRInst* inst)
}
}
+static bool isVoidPtrType(IRType* type)
+{
+ auto ptrType = as<IRPtrType>(type);
+ if (!ptrType) return false;
+ return ptrType->getValueType()->op == kIROp_VoidType;
+}
+
+void CPPSourceEmitter::emitSimpleFuncParamImpl(IRParam* param)
+{
+ // Polymorphic types are already translated to void* type in
+ // lower-generics pass. However, the current emitting logic will
+ // emit "void&" instead of "void*" for pointer types.
+ // In the future, we will handle pointer types more properly,
+ // and this override logic will not be necessary.
+ // For now we special-case this scenario.
+ if (param->findDecoration<IRPolymorphicDecoration>() &&
+ isVoidPtrType(param->getDataType()))
+ {
+ m_writer->emit("void* ");
+ m_writer->emit(getName(param));
+ return;
+ }
+ CLikeSourceEmitter::emitSimpleFuncParamImpl(param);
+}
+
void CPPSourceEmitter::emitVectorTypeNameImpl(IRType* elementType, IRIntegerValue elementCount)
{
emitSimpleType(m_typeSet.addVectorType(elementType, int(elementCount)));
@@ -2102,6 +2229,16 @@ bool CPPSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOut
m_writer->emit(")");
return true;
}
+ case kIROp_getAddr:
+ {
+ // Once we clean up the pointer emitting logic, we can
+ // just use GetElementAddress instruction in place of
+ // getAddr instruction, and this case can be removed.
+ m_writer->emit("(&(");
+ emitInstExpr(inst->getOperand(0), EmitOpInfo::get(EmitOp::General));
+ m_writer->emit("))");
+ return true;
+ }
}
}
@@ -2134,6 +2271,20 @@ void CPPSourceEmitter::emitPreprocessorDirectivesImpl()
writer->emit("\n");
+
+ if (m_target == CodeGenTarget::CPPSource)
+ {
+ // 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");
+
+ m_writer->emit("struct KernelContext;\n\n");
+ }
+
if (m_target == CodeGenTarget::CSource)
{
// For C output we need to emit type definitions.
@@ -2169,7 +2320,6 @@ void CPPSourceEmitter::emitPreprocessorDirectivesImpl()
{
_maybeEmitSpecializedOperationDefinition(intrinsic);
}
-
}
}
@@ -2293,14 +2443,14 @@ void CPPSourceEmitter::_emitEntryPointDefinitionStart(IRFunc* func, IRGlobalPara
m_writer->emit("(");
m_writer->emit(varyingTypeName);
- m_writer->emit("* varyingInput, UniformEntryPointParams* params, UniformState* uniformState)");
+ m_writer->emit("* varyingInput, void* params, void* uniformState)");
emitSemantics(func);
m_writer->emit("\n{\n");
m_writer->indent();
// Initialize when constructing so that globals are zeroed
- m_writer->emit("Context context = {};\n");
- m_writer->emit("context.uniformState = uniformState;\n");
+ m_writer->emit("KernelContext context = {};\n");
+ m_writer->emit("context.uniformState = (UniformState*)uniformState;\n");
if (entryPointGlobalParams)
{
@@ -2590,11 +2740,11 @@ void CPPSourceEmitter::emitModuleImpl(IRModule* module)
List<EmitAction> actions;
computeEmitActions(module, actions);
-
+
_emitForwardDeclarations(actions);
IRGlobalParam* entryPointGlobalParams = nullptr;
-
+
// Output the global parameters in a 'UniformState' structure
{
m_writer->emit("struct UniformState\n{\n");
@@ -2605,15 +2755,14 @@ void CPPSourceEmitter::emitModuleImpl(IRModule* module)
m_writer->dedent();
m_writer->emit("\n};\n\n");
}
-
+
// Output the 'Context' which will be used for execution
{
- m_writer->emit("struct Context\n{\n");
+ m_writer->emit("struct KernelContext\n{\n");
m_writer->indent();
m_writer->emit("UniformState* uniformState;\n");
-
m_writer->emit("uint3 dispatchThreadID;\n");
//if (m_semanticUsedFlags & SemanticUsedFlag::GroupID)
@@ -2658,13 +2807,25 @@ void CPPSourceEmitter::emitModuleImpl(IRModule* module)
}
}
+ // Emit wrapper functions for each witness table entry.
+ // These wrapper functions takes an abstract type parameter (void*)
+ // in the place of `this` parameter.
+ _emitWitnessTableWrappers();
+
m_writer->dedent();
- m_writer->emit("};\n\n");
+ m_writer->emit("};\n\n");
}
// Emit all witness table definitions.
_emitWitnessTableDefinitions();
+ if (m_target == CodeGenTarget::CPPSource)
+ {
+ // Need to close the anonymous namespace when outputting for C++
+
+ m_writer->emit("} // anonymous\n\n");
+ }
+
// Finally we need to output dll entry points
for (auto action : actions)
@@ -2675,7 +2836,7 @@ void CPPSourceEmitter::emitModuleImpl(IRModule* module)
IREntryPointDecoration* entryPointDecor = func->findDecoration<IREntryPointDecoration>();
- if (entryPointDecor && entryPointDecor->getProfile().GetStage() == Stage::Compute)
+ if (entryPointDecor && entryPointDecor->getProfile().getStage() == Stage::Compute)
{
// https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sv-dispatchthreadid
// SV_DispatchThreadID is the sum of SV_GroupID * numthreads and GroupThreadID.
diff --git a/source/slang/slang-emit-cpp.h b/source/slang/slang-emit-cpp.h
index b8afc6a76..47ba03d70 100644
--- a/source/slang/slang-emit-cpp.h
+++ b/source/slang/slang-emit-cpp.h
@@ -71,6 +71,7 @@ protected:
virtual bool tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOuterPrec) SLANG_OVERRIDE;
virtual void emitPreprocessorDirectivesImpl() SLANG_OVERRIDE;
virtual void emitSimpleValueImpl(IRInst* value) SLANG_OVERRIDE;
+ virtual void emitSimpleFuncParamImpl(IRParam* param) SLANG_OVERRIDE;
virtual void emitModuleImpl(IRModule* module) SLANG_OVERRIDE;
virtual void emitSimpleFuncImpl(IRFunc* func) SLANG_OVERRIDE;
virtual void emitOperandImpl(IRInst* inst, EmitOpInfo const& outerPrec) SLANG_OVERRIDE;
@@ -117,6 +118,10 @@ protected:
UnownedStringSlice _getFuncName(const HLSLIntrinsic* specOp);
+ // Returns a StringSlice representing the mangled name of a witness table
+ // wrapper function.
+ UnownedStringSlice _getWitnessTableWrapperFuncName(IRFunc* func);
+
UnownedStringSlice _getTypeName(IRType* type);
SlangResult _calcCPPTextureTypeName(IRTextureTypeBase* texType, StringBuilder& outName);
@@ -134,12 +139,20 @@ protected:
// of all the witness table objects in `pendingWitnessTableDefinitions`.
void _emitWitnessTableDefinitions();
+ // Emit wrapper functions that are referenced in witness tables.
+ // Wrapper functions wraps the actual member function, and takes a `void*`
+ // as the `this` parameter instead of the actual object type, so that
+ // their signature is agnostic to the object type.
+ void _emitWitnessTableWrappers();
+
HLSLIntrinsic* _addIntrinsic(HLSLIntrinsic::Op op, IRType* returnType, IRType*const* argTypes, Index argTypeCount);
static bool _isVariable(IROp op);
Dictionary<IRType*, StringSlicePool::Handle> m_typeNameMap;
Dictionary<const HLSLIntrinsic*, StringSlicePool::Handle> m_intrinsicNameMap;
+ Dictionary<IRFunc*, StringSlicePool::Handle> m_witnessTableWrapperFuncNameMap;
+
IRTypeSet m_typeSet;
RefPtr<HLSLIntrinsicOpLookup> m_opLookup;
diff --git a/source/slang/slang-emit-cuda.cpp b/source/slang/slang-emit-cuda.cpp
index 25b06027d..6272ea02e 100644
--- a/source/slang/slang-emit-cuda.cpp
+++ b/source/slang/slang-emit-cuda.cpp
@@ -799,7 +799,7 @@ void CUDASourceEmitter::emitModuleImpl(IRModule* module)
// must be prefixed to indicate to the OptiX runtime what
// stage it is to be compiled for.
//
- auto stage = entryPointDecor->getProfile().GetStage();
+ auto stage = entryPointDecor->getProfile().getStage();
switch( stage )
{
default:
@@ -866,10 +866,10 @@ void CUDASourceEmitter::emitModuleImpl(IRModule* module)
//
// At the binary level, our generated CUDA compute kernels will take
// two pointer parameters: the first points to the per-entry-point
- // `uniform` parameter data, and the second poinst to the global-scope
+ // `uniform` parameter data, and the second points to the global-scope
// parameter data (if any).
//
- m_writer->emit("(UniformEntryPointParams* entryPointShaderParameters, UniformState* uniformState)");
+ m_writer->emit("(void* entryPointShaderParameters, void* uniformState)");
}
else
{
diff --git a/source/slang/slang-emit-glsl.cpp b/source/slang/slang-emit-glsl.cpp
index a73ea529a..d09c778b9 100644
--- a/source/slang/slang-emit-glsl.cpp
+++ b/source/slang/slang-emit-glsl.cpp
@@ -49,7 +49,7 @@ void GLSLSourceEmitter::_requireGLSLExtension(const UnownedStringSlice& name)
void GLSLSourceEmitter::_requireGLSLVersion(ProfileVersion version)
{
- if (getSourceStyle() != SourceStyle::GLSL)
+ if (getSourceLanguage() != SourceLanguage::GLSL)
return;
m_glslExtensionTracker->requireVersion(version);
@@ -553,12 +553,12 @@ void GLSLSourceEmitter::_emitGLSLLayoutQualifiers(IRVarLayout* layout, EmitVarCh
{
if (!layout) return;
- switch (getSourceStyle())
+ switch (getSourceLanguage())
{
default:
return;
- case SourceStyle::GLSL:
+ case SourceLanguage::GLSL:
break;
}
@@ -806,7 +806,7 @@ void GLSLSourceEmitter::emitEntryPointAttributesImpl(IRFunc* irFunc, IREntryPoin
SLANG_ASSERT(entryPointDecor);
auto profile = entryPointDecor->getProfile();
- auto stage = profile.GetStage();
+ auto stage = profile.getStage();
switch (stage)
{
@@ -1498,7 +1498,7 @@ void GLSLSourceEmitter::emitPreprocessorDirectivesImpl()
auto effectiveProfile = m_effectiveProfile;
if (effectiveProfile.getFamily() == ProfileFamily::GLSL)
{
- _requireGLSLVersion(effectiveProfile.GetVersion());
+ _requireGLSLVersion(effectiveProfile.getVersion());
}
// HACK: We aren't picking GLSL versions carefully right now,
diff --git a/source/slang/slang-emit-hlsl.cpp b/source/slang/slang-emit-hlsl.cpp
index 83bfb8f2a..440b9bc68 100644
--- a/source/slang/slang-emit-hlsl.cpp
+++ b/source/slang/slang-emit-hlsl.cpp
@@ -135,12 +135,12 @@ void HLSLSourceEmitter::_emitHLSLRegisterSemantics(EmitVarChain* chain, char con
auto layout = chain->varLayout;
- switch (getSourceStyle())
+ switch (getSourceLanguage())
{
default:
return;
- case SourceStyle::HLSL:
+ case SourceLanguage::HLSL:
break;
}
@@ -290,11 +290,11 @@ void HLSLSourceEmitter::emitParameterGroupImpl(IRGlobalParam* varDecl, IRUniform
void HLSLSourceEmitter::emitEntryPointAttributesImpl(IRFunc* irFunc, IREntryPointDecoration* entryPointDecor)
{
auto profile = m_effectiveProfile;
- auto stage = entryPointDecor->getProfile().GetStage();
+ auto stage = entryPointDecor->getProfile().getStage();
if (profile.getFamily() == ProfileFamily::DX)
{
- if (profile.GetVersion() >= ProfileVersion::DX_6_1)
+ if (profile.getVersion() >= ProfileVersion::DX_6_1)
{
char const* stageName = getStageName(stage);
if (stageName)
diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp
index c6f2f7468..0ca523ecf 100644
--- a/source/slang/slang-emit-spirv.cpp
+++ b/source/slang/slang-emit-spirv.cpp
@@ -208,7 +208,7 @@ struct SpvInst : SpvInstParent
//
// > Word Count: The complete number of words taken by an instruction,
// > including the word holding the word count and opcode, and any optional
- // > operands. An instruction’s word count is the total space taken by the instruction.
+ // > operands. An instruction’s word count is the total space taken by the instruction.
//
SpvWord wordCount = 1 + SpvWord(operandWords.getCount());
@@ -531,7 +531,7 @@ struct SPIRVEmitContext
cursor += 4;
}
//
- // > The final word contains the string’s nul-termination character (0), and
+ // > The final word contains the string’s nul-termination character (0), and
// > all contents past the end of the string in the final word are padded with 0.
//
// For the last word, the low-order bytes will
@@ -1052,7 +1052,7 @@ struct SPIRVEmitContext
// to the new globals, which would be used in the SPIR-V emit case.
auto entryPointDecor = cast<IREntryPointDecoration>(decoration);
- auto spvStage = mapStageToExecutionModel(entryPointDecor->getProfile().GetStage());
+ auto spvStage = mapStageToExecutionModel(entryPointDecor->getProfile().getStage());
auto name = entryPointDecor->getName()->getStringSlice();
emitInst(section, decoration, SpvOpEntryPoint, spvStage, dstID, name);
}
diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp
index 4af7b5989..f2552f95d 100644
--- a/source/slang/slang-emit.cpp
+++ b/source/slang/slang-emit.cpp
@@ -308,7 +308,7 @@ Result linkAndOptimizeIR(
// We don't need the legalize pass for C/C++ based types
if(options.shouldLegalizeExistentialAndResourceTypes )
-// if (!(sourceStyle == SourceStyle::CPP || sourceStyle == SourceStyle::C))
+// if (!(sourceLanguage == SourceLanguage::CPP || sourceStyle == SourceLanguage::C))
{
// The Slang language allows interfaces to be used like
// ordinary types (including placing them in constant
@@ -495,7 +495,7 @@ Result linkAndOptimizeIR(
auto profile = targetRequest->targetProfile;
if( profile.getFamily() == ProfileFamily::DX )
{
- if(profile.GetVersion() <= ProfileVersion::DX_5_0)
+ if(profile.getVersion() <= ProfileVersion::DX_5_0)
{
// Fxc and earlier dxc versions do not support
// a templates `.Load<T>` operation on byte-address
@@ -646,27 +646,25 @@ SlangResult emitEntryPointSourceFromIR(
RefPtr<CLikeSourceEmitter> sourceEmitter;
- typedef CLikeSourceEmitter::SourceStyle SourceStyle;
-
- SourceStyle sourceStyle = CLikeSourceEmitter::getSourceStyle(target);
- switch (sourceStyle)
+ SourceLanguage sourceLanguage = CLikeSourceEmitter::getSourceLanguage(target);
+ switch (sourceLanguage)
{
- case SourceStyle::CPP:
+ case SourceLanguage::CPP:
{
sourceEmitter = new CPPSourceEmitter(desc);
break;
}
- case SourceStyle::GLSL:
+ case SourceLanguage::GLSL:
{
sourceEmitter = new GLSLSourceEmitter(desc);
break;
}
- case SourceStyle::HLSL:
+ case SourceLanguage::HLSL:
{
sourceEmitter = new HLSLSourceEmitter(desc);
break;
}
- case SourceStyle::CUDA:
+ case SourceLanguage::CUDA:
{
sourceEmitter = new CUDASourceEmitter(desc);
break;
@@ -687,14 +685,14 @@ SlangResult emitEntryPointSourceFromIR(
linkingAndOptimizationOptions.sourceEmitter = sourceEmitter;
- switch( sourceStyle )
+ switch( sourceLanguage )
{
default:
break;
- case SourceStyle::CPP:
- case SourceStyle::C:
- case SourceStyle::CUDA:
+ case SourceLanguage::CPP:
+ case SourceLanguage::C:
+ case SourceLanguage::CUDA:
linkingAndOptimizationOptions.shouldLegalizeExistentialAndResourceTypes = false;
break;
}
@@ -728,43 +726,8 @@ SlangResult emitEntryPointSourceFromIR(
// it is time to stitch together the final output.
{
- Session* session = compileRequest->getSession();
-
- // Get the downstream compiler needed for final target
- PassThroughMode passThru = getDownstreamCompilerRequiredForTarget(session, targetRequest->target);
-
- // If nothing was *needed*, we still need some idea of which downstream compiler is going to be used for the
- // prelude (the prelude is associated with each specific downstream compiler)
- if (passThru == PassThroughMode::None)
- {
- // TODO(JS):
- // NOTE! This makes the *assumption* that if we are outputting source, we don't want the
- // prelude for a specific compiler, we are happy to just use the GenericCCpp
- // If we didn't do this, we would have to do the work out what's available etc.
- //
- // This is all a bit unfortunate. The decision to associate preludes on compilers seemed like a good idea, but was perhaps a mistake.
- // That it would be simpler if prelude was based on output source type.
- passThru = getPreludeDownstreamCompilerForTarget(session, targetRequest->target);
- }
- else
- {
- // If a compiler was required that means a downstream compiler *will* be used
- // so lookup which specific compiler is used, and use it's prelude
- // Currently this distinction is only applicable to C++
- if (passThru == PassThroughMode::GenericCCpp)
- {
- const SourceLanguage sourceLanguage = (sourceStyle == SourceStyle::C) ? SourceLanguage::C : SourceLanguage::CPP;
- // Get the compiler used for the language
- DownstreamCompiler* compiler = session->getDefaultDownstreamCompiler(sourceLanguage);
- if (compiler)
- {
- passThru = PassThroughMode(compiler->getDesc().type);
- }
- }
- }
-
// If there is a prelude emit it
- const auto& prelude = compileRequest->getSession()->getDownstreamCompilerPrelude(passThru);
+ const auto& prelude = compileRequest->getSession()->getPreludeForLanguage(sourceLanguage);
if (prelude.getLength() > 0)
{
sourceWriter.emit(prelude.getUnownedSlice());
diff --git a/source/slang/slang-ir-glsl-legalize.cpp b/source/slang/slang-ir-glsl-legalize.cpp
index afb67a081..794024d46 100644
--- a/source/slang/slang-ir-glsl-legalize.cpp
+++ b/source/slang/slang-ir-glsl-legalize.cpp
@@ -1602,7 +1602,7 @@ void legalizeEntryPointForGLSL(
auto entryPointDecor = func->findDecoration<IREntryPointDecoration>();
SLANG_ASSERT(entryPointDecor);
- auto stage = entryPointDecor->getProfile().GetStage();
+ auto stage = entryPointDecor->getProfile().getStage();
auto layoutDecoration = func->findDecoration<IRLayoutDecoration>();
SLANG_ASSERT(layoutDecoration);
diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h
index f5127d0fa..58ff1a79f 100644
--- a/source/slang/slang-ir-inst-defs.h
+++ b/source/slang/slang-ir-inst-defs.h
@@ -236,6 +236,7 @@ INST(FieldAddress, get_field_addr, 2, 0)
INST(getElement, getElement, 2, 0)
INST(getElementPtr, getElementPtr, 2, 0)
+INST(getAddr, getAddr, 1, 0)
// "Subscript" an image at a pixel coordinate to get pointer
INST(ImageSubscript, imageSubscript, 2, 0)
@@ -506,6 +507,16 @@ INST(HighLevelDeclDecoration, highLevelDecl, 1, 0)
INST(BindExistentialSlotsDecoration, bindExistentialSlots, 0, 0)
+ /// A `[polymorphic]` decoration marks a function parameter that should translate to an abstract type
+ /// e.g. (void*) that are casted to actual type before use. For example, a parameter of generic type
+ /// is marked `[polymorphic]`, so that the code gen logic can emit it as a `void*` parameter,
+ /// allowing the function to be used at sites that are agnostic of the actual object type.
+ INST(PolymorphicDecoration, polymorphic, 0, 0)
+
+ /// A `[this_ptr]` decoration marks a function parameter that serves as `this` pointer.
+ INST(ThisPointerDecoration, this_ptr, 0, 0)
+
+
/// A `[format(f)]` decoration specifies that the format of an image should be `f`
INST(FormatDecoration, format, 1, 0)
diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h
index 3aab4c323..b13d52981 100644
--- a/source/slang/slang-ir-insts.h
+++ b/source/slang/slang-ir-insts.h
@@ -166,6 +166,10 @@ IR_SIMPLE_DECORATION(VulkanCallablePayloadDecoration)
/// to it.
IR_SIMPLE_DECORATION(VulkanHitAttributesDecoration)
+IR_SIMPLE_DECORATION(PolymorphicDecoration)
+IR_SIMPLE_DECORATION(ThisPointerDecoration)
+
+
struct IRRequireGLSLVersionDecoration : IRDecoration
{
enum { kOp = kIROp_RequireGLSLVersionDecoration };
@@ -1145,6 +1149,11 @@ struct IRFieldAddress : IRInst
IRInst* getField() { return field.get(); }
};
+struct IRGetAddress : IRInst
+{
+ IR_LEAF_ISA(getAddr);
+};
+
// Terminators
struct IRReturn : IRTerminatorInst
@@ -1894,6 +1903,10 @@ struct IRBuilder
IRInst* basePtr,
IRInst* index);
+ IRInst* emitGetAddress(
+ IRType* type,
+ IRInst* value);
+
IRInst* emitSwizzle(
IRType* type,
IRInst* base,
@@ -2147,6 +2160,16 @@ struct IRBuilder
addDecoration(value, kIROp_LoopControlDecoration, getIntValue(getIntType(), IRIntegerValue(mode)));
}
+ void addPolymorphicDecoration(IRInst* value)
+ {
+ addDecoration(value, kIROp_PolymorphicDecoration);
+ }
+
+ void addThisPointerDecoration(IRInst* value)
+ {
+ addDecoration(value, kIROp_ThisPointerDecoration);
+ }
+
void addSemanticDecoration(IRInst* value, UnownedStringSlice const& text, int index = 0)
{
addDecoration(value, kIROp_SemanticDecoration, getStringValue(text), getIntValue(getIntType(), index));
diff --git a/source/slang/slang-ir-lower-generics.cpp b/source/slang/slang-ir-lower-generics.cpp
index 4378d396f..f6340a633 100644
--- a/source/slang/slang-ir-lower-generics.cpp
+++ b/source/slang/slang-ir-lower-generics.cpp
@@ -79,6 +79,14 @@ namespace Slang
block->addParam(as<IRParam>(param));
}
loweredGenericFunctions[genericValue] = loweredFunc;
+ // Turn generic parameters into void pointers.
+ for (auto param : cast<IRFunc>(loweredFunc)->getParams())
+ {
+ if (param->findDecoration<IRPolymorphicDecoration>())
+ {
+ param->setFullType(builder.getPtrType(builder.getVoidType()));
+ }
+ }
addToWorkList(loweredFunc);
return loweredFunc;
}
@@ -103,8 +111,29 @@ namespace Slang
builder->sharedBuilder = &sharedBuilderStorage;
builder->setInsertBefore(inst);
List<IRInst*> args;
+ auto pp = as<IRFunc>(loweredFunc)->getParams().begin();
+ auto voidPtrType = builder->getPtrType(builder->getVoidType());
for (UInt i = 0; i < callInst->getArgCount(); i++)
- args.add(callInst->getArg(i));
+ {
+ auto arg = callInst->getArg(i);
+ if ((*pp)->getDataType() == voidPtrType &&
+ arg->getDataType() != voidPtrType)
+ {
+ // We are calling a generic function that with an argument of
+ // concrete type. We need to convert this argument o void*.
+
+ // Ideally this should just be a GetElementAddress inst.
+ // However the current code emitting logic for this instruction
+ // doesn't truly respect the pointerness and does not produce
+ // what we needed. For now we use another instruction here
+ // to keep changes minimal.
+ arg = builder->emitGetAddress(
+ voidPtrType,
+ arg);
+ }
+ args.add(arg);
+ ++pp;
+ }
for (UInt i = 0; i < specializeInst->getArgCount(); i++)
args.add(specializeInst->getArg(i));
auto newCall = builder->emitCallInst(callInst->getFullType(), loweredFunc, args);
diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp
index 34ea23b85..77011b569 100644
--- a/source/slang/slang-ir.cpp
+++ b/source/slang/slang-ir.cpp
@@ -3083,6 +3083,20 @@ namespace Slang
return inst;
}
+ IRInst* IRBuilder::emitGetAddress(
+ IRType* type,
+ IRInst* value)
+ {
+ auto inst = createInst<IRGetAddress>(
+ this,
+ kIROp_getAddr,
+ type,
+ value);
+
+ addInst(inst);
+ return inst;
+ }
+
IRInst* IRBuilder::emitSwizzle(
IRType* type,
IRInst* base,
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index 01bd0e972..ea04ea85c 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -6157,6 +6157,8 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
LoweredValInfo paramVal;
+ IRParam* irParam = nullptr;
+
switch( paramInfo.direction )
{
default:
@@ -6166,15 +6168,15 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
//
// TODO: Is this the best representation we can use?
- IRParam* irParamPtr = subBuilder->emitParam(irParamType);
+ irParam = subBuilder->emitParam(irParamType);
if(auto paramDecl = paramInfo.decl)
{
- addVarDecorations(context, irParamPtr, paramDecl);
- subBuilder->addHighLevelDeclDecoration(irParamPtr, paramDecl);
+ addVarDecorations(context, irParam, paramDecl);
+ subBuilder->addHighLevelDeclDecoration(irParam, paramDecl);
}
- addParamNameHint(irParamPtr, paramInfo);
+ addParamNameHint(irParam, paramInfo);
- paramVal = LoweredValInfo::ptr(irParamPtr);
+ paramVal = LoweredValInfo::ptr(irParam);
// TODO: We might want to copy the pointed-to value into
// a temporary at the start of the function, and then copy
@@ -6194,7 +6196,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
// We start by declaring an IR parameter of the same type.
//
auto paramDecl = paramInfo.decl;
- IRParam* irParam = subBuilder->emitParam(irParamType);
+ irParam = subBuilder->emitParam(irParamType);
if( paramDecl )
{
addVarDecorations(context, irParam, paramDecl);
@@ -6249,6 +6251,14 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
if (paramInfo.isThisParam)
{
subContext->thisVal = paramVal;
+ subBuilder->addThisPointerDecoration(irParam);
+ }
+
+ // Add a [polymorphic] decoration for generic-typed parameters.
+ if (as<IRParam>(irParamType) &&
+ as<IRTypeType>(irParamType->getFullType()))
+ {
+ subBuilder->addPolymorphicDecoration(irParam);
}
}
diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp
index 5bf0c6c9d..f3c702c26 100644
--- a/source/slang/slang-options.cpp
+++ b/source/slang/slang-options.cpp
@@ -12,7 +12,7 @@
#include "slang-file-system.h"
-#include "slang-state-serialize.h"
+#include "slang-repro.h"
#include "slang-ir-serialize.h"
#include "../core/slang-type-text-util.h"
@@ -483,7 +483,7 @@ struct OptionsParser
String reproName;
SLANG_RETURN_ON_FAIL(tryReadCommandLineArgument(sink, arg, &argCursor, argEnd, reproName));
- SLANG_RETURN_ON_FAIL(StateSerializeUtil::extractFilesToDirectory(reproName));
+ SLANG_RETURN_ON_FAIL(ReproUtil::extractFilesToDirectory(reproName));
}
else if (argStr == "-module-name")
{
@@ -498,16 +498,16 @@ struct OptionsParser
SLANG_RETURN_ON_FAIL(tryReadCommandLineArgument(sink, arg, &argCursor, argEnd, reproName));
List<uint8_t> buffer;
- SLANG_RETURN_ON_FAIL(StateSerializeUtil::loadState(reproName, buffer));
+ SLANG_RETURN_ON_FAIL(ReproUtil::loadState(reproName, buffer));
- auto requestState = StateSerializeUtil::getRequest(buffer);
+ auto requestState = ReproUtil::getRequest(buffer);
MemoryOffsetBase base;
base.set(buffer.getBuffer(), buffer.getCount());
// If we can find a directory, that exists, we will set up a file system to load from that directory
ComPtr<ISlangFileSystem> fileSystem;
String dirPath;
- if (SLANG_SUCCEEDED(StateSerializeUtil::calcDirectoryPathFromFilename(reproName, dirPath)))
+ if (SLANG_SUCCEEDED(ReproUtil::calcDirectoryPathFromFilename(reproName, dirPath)))
{
SlangPathType pathType;
if (SLANG_SUCCEEDED(Path::getPathType(dirPath, &pathType)) && pathType == SLANG_PATH_TYPE_DIRECTORY)
@@ -516,7 +516,7 @@ struct OptionsParser
}
}
- SLANG_RETURN_ON_FAIL(StateSerializeUtil::load(base, requestState, fileSystem, requestImpl));
+ SLANG_RETURN_ON_FAIL(ReproUtil::load(base, requestState, fileSystem, requestImpl));
hasLoadedRepro = true;
}
@@ -526,16 +526,16 @@ struct OptionsParser
SLANG_RETURN_ON_FAIL(tryReadCommandLineArgument(sink, arg, &argCursor, argEnd, reproName));
List<uint8_t> buffer;
- SLANG_RETURN_ON_FAIL(StateSerializeUtil::loadState(reproName, buffer));
+ SLANG_RETURN_ON_FAIL(ReproUtil::loadState(reproName, buffer));
- auto requestState = StateSerializeUtil::getRequest(buffer);
+ auto requestState = ReproUtil::getRequest(buffer);
MemoryOffsetBase base;
base.set(buffer.getBuffer(), buffer.getCount());
// If we can find a directory, that exists, we will set up a file system to load from that directory
ComPtr<ISlangFileSystem> dirFileSystem;
String dirPath;
- if (SLANG_SUCCEEDED(StateSerializeUtil::calcDirectoryPathFromFilename(reproName, dirPath)))
+ if (SLANG_SUCCEEDED(ReproUtil::calcDirectoryPathFromFilename(reproName, dirPath)))
{
SlangPathType pathType;
if (SLANG_SUCCEEDED(Path::getPathType(dirPath, &pathType)) && pathType == SLANG_PATH_TYPE_DIRECTORY)
@@ -545,7 +545,7 @@ struct OptionsParser
}
RefPtr<CacheFileSystem> cacheFileSystem;
- SLANG_RETURN_ON_FAIL(StateSerializeUtil::loadFileSystem(base, requestState, dirFileSystem, cacheFileSystem));
+ SLANG_RETURN_ON_FAIL(ReproUtil::loadFileSystem(base, requestState, dirFileSystem, cacheFileSystem));
// I might want to make the dir file system the fallback file system...
cacheFileSystem->setInnerFileSystem(dirFileSystem, cacheFileSystem->getUniqueIdentityMode(), cacheFileSystem->getPathStyle());
@@ -624,11 +624,11 @@ struct OptionsParser
{
auto profile = Profile(profileID);
- setProfileVersion(getCurrentTarget(), profile.GetVersion());
+ setProfileVersion(getCurrentTarget(), profile.getVersion());
// A `-profile` option that also specifies a stage (e.g., `-profile vs_5_0`)
// should be treated like a composite (e.g., `-profile sm_5_0 -stage vertex`)
- auto stage = profile.GetStage();
+ auto stage = profile.getStage();
if(stage != Stage::Unknown)
{
setStage(getCurrentEntryPoint(), stage);
diff --git a/source/slang/slang-parameter-binding.cpp b/source/slang/slang-parameter-binding.cpp
index ea45612ec..ee3ef1234 100644
--- a/source/slang/slang-parameter-binding.cpp
+++ b/source/slang/slang-parameter-binding.cpp
@@ -1425,7 +1425,7 @@ static RefPtr<TypeLayout> processSimpleEntryPointParameter(
//
if( isD3DTarget(context->getTargetRequest()) )
{
- auto version = context->getTargetRequest()->targetProfile.GetVersion();
+ auto version = context->getTargetRequest()->targetProfile.getVersion();
if( version <= ProfileVersion::DX_5_0 )
{
// We will address the conflict here by claiming the corresponding
diff --git a/source/slang/slang-profile.h b/source/slang/slang-profile.h
index c90ca66d0..f5b15eda6 100644
--- a/source/slang/slang-profile.h
+++ b/source/slang/slang-profile.h
@@ -89,21 +89,21 @@ namespace Slang
bool operator==(Profile const& other) const { return raw == other.raw; }
bool operator!=(Profile const& other) const { return raw != other.raw; }
- Stage GetStage() const { return Stage(uint32_t(raw) & 0xFFFF); }
+ Stage getStage() const { return Stage(uint32_t(raw) & 0xFFFF); }
void setStage(Stage stage)
{
raw = (raw & ~0xFFFF) | uint32_t(stage);
}
- ProfileVersion GetVersion() const { return ProfileVersion((uint32_t(raw) >> 16) & 0xFFFF); }
+ ProfileVersion getVersion() const { return ProfileVersion((uint32_t(raw) >> 16) & 0xFFFF); }
void setVersion(ProfileVersion version)
{
raw = (raw & 0x0000FFFF) | (uint32_t(version) << 16);
}
- ProfileFamily getFamily() const { return getProfileFamily(GetVersion()); }
+ ProfileFamily getFamily() const { return getProfileFamily(getVersion()); }
- static Profile LookUp(char const* name);
+ static Profile lookUp(char const* name);
char const* getName();
RawVal raw = Unknown;
diff --git a/source/slang/slang-reflection.cpp b/source/slang/slang-reflection.cpp
index c1e533140..4ed1c3e5d 100644
--- a/source/slang/slang-reflection.cpp
+++ b/source/slang/slang-reflection.cpp
@@ -1277,7 +1277,7 @@ SLANG_API SlangStage spReflectionEntryPoint_getStage(SlangReflectionEntryPoint*
if(!entryPointLayout) return SLANG_STAGE_NONE;
- return SlangStage(entryPointLayout->profile.GetStage());
+ return SlangStage(entryPointLayout->profile.getStage());
}
SLANG_API void spReflectionEntryPoint_getComputeThreadGroupSize(
@@ -1323,7 +1323,7 @@ SLANG_API int spReflectionEntryPoint_usesAnySampleRateInput(
if(!entryPointLayout)
return 0;
- if (entryPointLayout->profile.GetStage() != Stage::Fragment)
+ if (entryPointLayout->profile.getStage() != Stage::Fragment)
return 0;
return (entryPointLayout->flags & EntryPointLayout::Flag::usesAnySampleRateInput) != 0;
diff --git a/source/slang/slang-state-serialize.cpp b/source/slang/slang-repro.cpp
index 3d98f182d..80ef0322e 100644
--- a/source/slang/slang-state-serialize.cpp
+++ b/source/slang/slang-repro.cpp
@@ -1,5 +1,5 @@
-// slang-state-serialize.cpp
-#include "slang-state-serialize.h"
+// slang-repro.cpp
+#include "slang-repro.h"
#include "../core/slang-text-io.h"
@@ -14,8 +14,8 @@
namespace Slang {
-/* static */const RiffSemanticVersion StateSerializeUtil::g_semanticVersion =
- RiffSemanticVersion::make(StateSerializeUtil::kMajorVersion, StateSerializeUtil::kMinorVersion, StateSerializeUtil::kPatchVersion);
+/* static */const RiffSemanticVersion ReproUtil::g_semanticVersion =
+ RiffSemanticVersion::make(ReproUtil::kMajorVersion, ReproUtil::kMinorVersion, ReproUtil::kPatchVersion);
// We can't just use sizeof for the sizes of these types, because the hash will be dependent on the ptr size,
// which isn't an issue for serialization (we turn all pointers into Offset32Ptr -> uint32_t). So we use an x macro
@@ -55,7 +55,7 @@ namespace Slang {
// A function to calculate the hash related in list in part to how the types used are sized. Can catch crude breaking binary differences.
static HashCode32 _calcTypeHash()
{
- typedef StateSerializeUtil Util;
+ typedef ReproUtil Util;
const uint32_t sizes[] =
{
SLANG_STATE_TYPES(SLANG_STATE_TYPE_SIZE)
@@ -74,9 +74,9 @@ namespace { // anonymous
struct StoreContext
{
- typedef StateSerializeUtil::FileState FileState;
- typedef StateSerializeUtil::SourceFileState SourceFileState;
- typedef StateSerializeUtil::PathInfoState PathInfoState;
+ typedef ReproUtil::FileState FileState;
+ typedef ReproUtil::SourceFileState SourceFileState;
+ typedef ReproUtil::PathInfoState PathInfoState;
StoreContext(OffsetContainer* container)
{
@@ -142,7 +142,7 @@ struct StoreContext
auto& base = m_container->asBase();
- Offset32Ptr<StateSerializeUtil::SourceFileState> sourceFileState;
+ Offset32Ptr<ReproUtil::SourceFileState> sourceFileState;
if (m_sourceFileMap.TryGetValue(sourceFile, sourceFileState))
{
return sourceFileState;
@@ -265,9 +265,9 @@ struct StoreContext
return pathInfo;
}
- const Offset32Array<StateSerializeUtil::StringPair> calcDefines(const Dictionary<String, String>& srcDefines)
+ const Offset32Array<ReproUtil::StringPair> calcDefines(const Dictionary<String, String>& srcDefines)
{
- typedef StateSerializeUtil::StringPair StringPair;
+ typedef ReproUtil::StringPair StringPair;
Offset32Array<StringPair> dstDefines = m_container->newArray<StringPair>(srcDefines.Count());
@@ -304,13 +304,13 @@ struct StoreContext
Dictionary<String, Offset32Ptr<OffsetString> > m_stringMap;
- Dictionary<SourceFile*, Offset32Ptr<StateSerializeUtil::SourceFileState> > m_sourceFileMap;
+ Dictionary<SourceFile*, Offset32Ptr<ReproUtil::SourceFileState> > m_sourceFileMap;
- Dictionary<String, Offset32Ptr<StateSerializeUtil::FileState> > m_uniqueToFileMap;
+ Dictionary<String, Offset32Ptr<ReproUtil::FileState> > m_uniqueToFileMap;
Dictionary<const CacheFileSystem::PathInfo*, Offset32Ptr<PathInfoState> > m_pathInfoMap;
- List<Offset32Ptr<StateSerializeUtil::FileState> > m_files;
+ List<Offset32Ptr<ReproUtil::FileState> > m_files;
OffsetContainer* m_container;
};
@@ -332,7 +332,7 @@ static bool _isStorable(const PathInfo::Type type)
}
}
-/* static */SlangResult StateSerializeUtil::store(EndToEndCompileRequest* request, OffsetContainer& inOutContainer, Offset32Ptr<RequestState>& outRequest)
+/* static */SlangResult ReproUtil::store(EndToEndCompileRequest* request, OffsetContainer& inOutContainer, Offset32Ptr<RequestState>& outRequest)
{
StoreContext context(&inOutContainer);
@@ -628,9 +628,9 @@ namespace { // anonymous
struct LoadContext
{
- typedef StateSerializeUtil::SourceFileState SourceFileState;
- typedef StateSerializeUtil::FileState FileState;
- typedef StateSerializeUtil::PathInfoState PathInfoState;
+ typedef ReproUtil::SourceFileState SourceFileState;
+ typedef ReproUtil::FileState FileState;
+ typedef ReproUtil::PathInfoState PathInfoState;
CacheFileSystem::PathInfo* getPathInfoFromFile(FileState* file)
{
@@ -778,7 +778,7 @@ struct LoadContext
}
- void loadDefines(const Offset32Array<StateSerializeUtil::StringPair>& in, Dictionary<String, String>& out)
+ void loadDefines(const Offset32Array<ReproUtil::StringPair>& in, Dictionary<String, String>& out)
{
out.Clear();
@@ -809,7 +809,7 @@ struct LoadContext
} // anonymous
-/* static */SlangResult StateSerializeUtil::loadFileSystem(OffsetBase& base, RequestState* requestState, ISlangFileSystem* fileSystem, RefPtr<CacheFileSystem>& outFileSystem)
+/* static */SlangResult ReproUtil::loadFileSystem(OffsetBase& base, RequestState* requestState, ISlangFileSystem* fileSystem, RefPtr<CacheFileSystem>& outFileSystem)
{
LoadContext context(nullptr, fileSystem, &base);
@@ -862,7 +862,7 @@ struct LoadContext
return SLANG_OK;
}
-/* static */SlangResult StateSerializeUtil::load(OffsetBase& base, RequestState* requestState, ISlangFileSystem* fileSystem, EndToEndCompileRequest* request)
+/* static */SlangResult ReproUtil::load(OffsetBase& base, RequestState* requestState, ISlangFileSystem* fileSystem, EndToEndCompileRequest* request)
{
auto externalRequest = asExternal(request);
@@ -1001,7 +1001,7 @@ struct LoadContext
const char* name = srcEntryPoint.name ? base.asRaw(srcEntryPoint.name)->getCstr() : nullptr;
- Stage stage = srcEntryPoint.profile.GetStage();
+ Stage stage = srcEntryPoint.profile.getStage();
List<const char*> args = context.toList(srcEntryPoint.specializationArgStrings);
@@ -1044,7 +1044,7 @@ struct LoadContext
}
-/* static */SlangResult StateSerializeUtil::saveState(EndToEndCompileRequest* request, Stream* stream)
+/* static */SlangResult ReproUtil::saveState(EndToEndCompileRequest* request, Stream* stream)
{
OffsetContainer container;
Offset32Ptr<RequestState> requestState;
@@ -1058,13 +1058,13 @@ struct LoadContext
return RiffUtil::writeData(&header.m_chunk, sizeof(header),container.getData(), container.getDataCount(), stream);
}
-/* static */SlangResult StateSerializeUtil::saveState(EndToEndCompileRequest* request, const String& filename)
+/* static */SlangResult ReproUtil::saveState(EndToEndCompileRequest* request, const String& filename)
{
RefPtr<Stream> stream(new FileStream(filename, FileMode::Create, FileAccess::Write, FileShare::ReadWrite));
return saveState(request, stream);
}
-/* static */ SlangResult StateSerializeUtil::loadState(const String& filename, List<uint8_t>& outBuffer)
+/* static */ SlangResult ReproUtil::loadState(const String& filename, List<uint8_t>& outBuffer)
{
RefPtr<Stream> stream;
try
@@ -1079,7 +1079,7 @@ struct LoadContext
return loadState(stream, outBuffer);
}
-/* static */ SlangResult StateSerializeUtil::loadState(Stream* stream, List<uint8_t>& buffer)
+/* static */ SlangResult ReproUtil::loadState(Stream* stream, List<uint8_t>& buffer)
{
Header header;
@@ -1102,18 +1102,18 @@ struct LoadContext
return SLANG_OK;
}
-/* static */SlangResult StateSerializeUtil::loadState(const uint8_t* data, size_t size, List<uint8_t>& outBuffer)
+/* static */SlangResult ReproUtil::loadState(const uint8_t* data, size_t size, List<uint8_t>& outBuffer)
{
MemoryStreamBase stream(FileAccess::Read, data, size);
return loadState(&stream, outBuffer);
}
-/* static */ StateSerializeUtil::RequestState* StateSerializeUtil::getRequest(const List<uint8_t>& buffer)
+/* static */ ReproUtil::RequestState* ReproUtil::getRequest(const List<uint8_t>& buffer)
{
- return (StateSerializeUtil::RequestState*)(buffer.getBuffer() + kStartOffset);
+ return (ReproUtil::RequestState*)(buffer.getBuffer() + kStartOffset);
}
-/* static */SlangResult StateSerializeUtil::calcDirectoryPathFromFilename(const String& filename, String& outPath)
+/* static */SlangResult ReproUtil::calcDirectoryPathFromFilename(const String& filename, String& outPath)
{
String absPath;
SLANG_RETURN_ON_FAIL(Path::getCanonical(filename, absPath));
@@ -1134,18 +1134,18 @@ struct LoadContext
return SLANG_OK;
}
-/* static */SlangResult StateSerializeUtil::extractFilesToDirectory(const String& filename)
+/* static */SlangResult ReproUtil::extractFilesToDirectory(const String& filename)
{
List<uint8_t> buffer;
- SLANG_RETURN_ON_FAIL(StateSerializeUtil::loadState(filename, buffer));
+ SLANG_RETURN_ON_FAIL(ReproUtil::loadState(filename, buffer));
MemoryOffsetBase base;
base.set(buffer.getBuffer(), buffer.getCount());
- RequestState* requestState = StateSerializeUtil::getRequest(buffer);
+ RequestState* requestState = ReproUtil::getRequest(buffer);
String dirPath;
- SLANG_RETURN_ON_FAIL(StateSerializeUtil::calcDirectoryPathFromFilename(filename, dirPath));
+ SLANG_RETURN_ON_FAIL(ReproUtil::calcDirectoryPathFromFilename(filename, dirPath));
Path::createDirectory(dirPath);
// Set up a file system to write into this directory
@@ -1154,7 +1154,7 @@ struct LoadContext
return extractFiles(base, requestState, &relFileSystem);
}
-static void _calcPreprocessorDefines(OffsetBase& base, const Offset32Array<StateSerializeUtil::StringPair>& srcDefines, CommandLine& cmd)
+static void _calcPreprocessorDefines(OffsetBase& base, const Offset32Array<ReproUtil::StringPair>& srcDefines, CommandLine& cmd)
{
for (const auto& define : srcDefines)
{
@@ -1169,10 +1169,10 @@ static void _calcPreprocessorDefines(OffsetBase& base, const Offset32Array<State
}
}
-static SlangResult _calcCommandLine(OffsetBase& base, StateSerializeUtil::RequestState* requestState, CommandLine& cmd)
+static SlangResult _calcCommandLine(OffsetBase& base, ReproUtil::RequestState* requestState, CommandLine& cmd)
{
- typedef StateSerializeUtil::TargetRequestState TargetRequestState;
- typedef StateSerializeUtil::SourceFileState SourceFileState;
+ typedef ReproUtil::TargetRequestState TargetRequestState;
+ typedef ReproUtil::SourceFileState SourceFileState;
{
SlangCompileFlags flags = (SlangCompileFlags)requestState->compileFlags;
@@ -1198,7 +1198,9 @@ static SlangResult _calcCommandLine(OffsetBase& base, StateSerializeUtil::Reques
case SLANG_LINE_DIRECTIVE_MODE_DEFAULT: break;
case SLANG_LINE_DIRECTIVE_MODE_NONE:
{
- cmd.addArg("-line-directive-mode none"); break;
+ cmd.addArg("-line-directive-mode");
+ cmd.addArg("none");
+ break;
}
default: break;
}
@@ -1255,8 +1257,11 @@ static SlangResult _calcCommandLine(OffsetBase& base, StateSerializeUtil::Reques
cmd.addArg("-target");
cmd.addArg(TypeTextUtil::getCompileTargetName(SlangCompileTarget(src.target)));
- cmd.addArg("-profile");
- cmd.addArg(Profile(src.profile).getName());
+ if (src.profile != Profile::Unknown)
+ {
+ cmd.addArg("-profile");
+ cmd.addArg(Profile(src.profile).getName());
+ }
if (src.targetFlags & SLANG_TARGET_FLAG_PARAMETER_BLOCKS_USE_REGISTER_SPACES)
{
@@ -1361,7 +1366,7 @@ static SlangResult _calcCommandLine(OffsetBase& base, StateSerializeUtil::Reques
cmd.addArg(name);
cmd.addArg("-stage");
- UnownedStringSlice stageText = getStageText(srcEntryPoint.profile.GetStage());
+ UnownedStringSlice stageText = getStageText(srcEntryPoint.profile.getStage());
cmd.addArg(stageText);
//cmd.addArg("-profile");
@@ -1377,7 +1382,7 @@ static SlangResult _calcCommandLine(OffsetBase& base, StateSerializeUtil::Reques
return SLANG_OK;
}
-/* static */SlangResult StateSerializeUtil::extractFiles(OffsetBase& base, RequestState* requestState, ISlangFileSystemExt* fileSystem)
+/* static */SlangResult ReproUtil::extractFiles(OffsetBase& base, RequestState* requestState, ISlangFileSystemExt* fileSystem)
{
StringBuilder builder;
@@ -1519,7 +1524,7 @@ static SlangResult _findFirstSourcePath(EndToEndCompileRequest* request, String&
return SLANG_FAIL;
}
-/* static */SlangResult StateSerializeUtil::findUniqueReproDumpStream(EndToEndCompileRequest* request, String& outFileName, RefPtr<Stream>& outStream)
+/* static */SlangResult ReproUtil::findUniqueReproDumpStream(EndToEndCompileRequest* request, String& outFileName, RefPtr<Stream>& outStream)
{
String sourcePath;
diff --git a/source/slang/slang-state-serialize.h b/source/slang/slang-repro.h
index 9a404138e..bd35d3ee9 100644
--- a/source/slang/slang-state-serialize.h
+++ b/source/slang/slang-repro.h
@@ -1,6 +1,6 @@
-// slang-state-serialize.h
-#ifndef SLANG_STATE_SERIALIZE_H_INCLUDED
-#define SLANG_STATE_SERIALIZE_H_INCLUDED
+// slang-repro.h
+#ifndef SLANG_REPRO_H_INCLUDED
+#define SLANG_REPRO_H_INCLUDED
#include "../core/slang-riff.h"
#include "../core/slang-string.h"
@@ -14,7 +14,13 @@
namespace Slang {
-struct StateSerializeUtil
+/* Facilities to be able to save and load the full state of a compilation, including source files,
+and all compilation options into 'slang-repro' files. Repro is short for 'reproducible' and it's
+main purposes is to make compilations easily reproducible as everything that is needed from
+a compilation environment is packaged up into a single file. The single file can be used to
+repeat the compilation, or extracted such that everything that was specified in the compilation
+can be inspected and modified. */
+struct ReproUtil
{
enum
{
diff --git a/source/slang/slang-type-layout.cpp b/source/slang/slang-type-layout.cpp
index 3b30e6ee0..d6138f2af 100644
--- a/source/slang/slang-type-layout.cpp
+++ b/source/slang/slang-type-layout.cpp
@@ -1487,7 +1487,7 @@ static bool isSM5OrEarlier(TargetRequest* targetReq)
if(profile.getFamily() == ProfileFamily::DX)
{
- if(profile.GetVersion() <= ProfileVersion::DX_5_0)
+ if(profile.getVersion() <= ProfileVersion::DX_5_0)
return true;
}
@@ -1503,7 +1503,7 @@ static bool isSM5_1OrLater(TargetRequest* targetReq)
if(profile.getFamily() == ProfileFamily::DX)
{
- if(profile.GetVersion() >= ProfileVersion::DX_5_1)
+ if(profile.getVersion() >= ProfileVersion::DX_5_1)
return true;
}
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index 1710359bf..5279b2a40 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -16,7 +16,7 @@
#include "slang-ast-dump.h"
-#include "slang-state-serialize.h"
+#include "slang-repro.h"
#include "slang-file-system.h"
@@ -231,7 +231,7 @@ SLANG_NO_THROW SlangResult SLANG_MCALL Session::createSession(
SLANG_NO_THROW SlangProfileID SLANG_MCALL Session::findProfile(
char const* name)
{
- return Slang::Profile::LookUp(name).raw;
+ return Slang::Profile::lookUp(name).raw;
}
SLANG_NO_THROW void SLANG_MCALL Session::setDownstreamCompilerPath(
@@ -254,20 +254,51 @@ SLANG_NO_THROW void SLANG_MCALL Session::setDownstreamCompilerPrelude(
SlangPassThrough inPassThrough,
char const* prelude)
{
- PassThroughMode passThrough = PassThroughMode(inPassThrough);
- SLANG_ASSERT(int(passThrough) > int(PassThroughMode::None) && int(passThrough) < int(PassThroughMode::CountOf));
-
- m_downstreamCompilerPreludes[int(passThrough)] = prelude;
+ PassThroughMode downstreamCompiler = PassThroughMode(inPassThrough);
+ SLANG_ASSERT(int(downstreamCompiler) > int(PassThroughMode::None) && int(downstreamCompiler) < int(PassThroughMode::CountOf));
+ const SourceLanguage sourceLanguage = getDefaultSourceLanguageForDownstreamCompiler(downstreamCompiler);
+ setLanguagePrelude(SlangSourceLanguage(sourceLanguage), prelude);
}
SLANG_NO_THROW void SLANG_MCALL Session::getDownstreamCompilerPrelude(
SlangPassThrough inPassThrough,
ISlangBlob** outPrelude)
{
- PassThroughMode passThrough = PassThroughMode(inPassThrough);
- SLANG_ASSERT(int(passThrough) > int(PassThroughMode::None) && int(passThrough) < int(PassThroughMode::CountOf));
+ PassThroughMode downstreamCompiler = PassThroughMode(inPassThrough);
+ SLANG_ASSERT(int(downstreamCompiler) > int(PassThroughMode::None) && int(downstreamCompiler) < int(PassThroughMode::CountOf));
+ const SourceLanguage sourceLanguage = getDefaultSourceLanguageForDownstreamCompiler(downstreamCompiler);
+ getLanguagePrelude(SlangSourceLanguage(sourceLanguage), outPrelude);
+}
+
+SLANG_NO_THROW void SLANG_MCALL Session::setLanguagePrelude(
+ SlangSourceLanguage inSourceLanguage,
+ char const* prelude)
+{
+ SourceLanguage sourceLanguage = SourceLanguage(inSourceLanguage);
+ SLANG_ASSERT(int(sourceLanguage) > int(SourceLanguage::Unknown) && int(sourceLanguage) < int(SourceLanguage::CountOf));
+
+ SLANG_ASSERT(sourceLanguage != SourceLanguage::Unknown);
- *outPrelude = Slang::StringUtil::createStringBlob(m_downstreamCompilerPreludes[int(passThrough)]).detach();
+ if (sourceLanguage != SourceLanguage::Unknown)
+ {
+ m_languagePreludes[int(sourceLanguage)] = prelude;
+ }
+}
+
+SLANG_NO_THROW void SLANG_MCALL Session::getLanguagePrelude(
+ SlangSourceLanguage inSourceLanguage,
+ ISlangBlob** outPrelude)
+{
+ SourceLanguage sourceLanguage = SourceLanguage(inSourceLanguage);
+ SLANG_ASSERT(int(sourceLanguage) > int(SourceLanguage::Unknown) && int(sourceLanguage) < int(SourceLanguage::CountOf));
+
+ SLANG_ASSERT(sourceLanguage != SourceLanguage::Unknown);
+
+ *outPrelude = nullptr;
+ if (sourceLanguage != SourceLanguage::Unknown)
+ {
+ *outPrelude = Slang::StringUtil::createStringBlob(m_languagePreludes[int(sourceLanguage)]).detach();
+ }
}
SLANG_NO_THROW const char* SLANG_MCALL Session::getBuildTagString()
@@ -426,8 +457,8 @@ Profile getEffectiveProfile(EntryPoint* entryPoint, TargetRequest* target)
break;
}
- auto entryPointProfileVersion = entryPointProfile.GetVersion();
- auto targetProfileVersion = targetProfile.GetVersion();
+ auto entryPointProfileVersion = entryPointProfile.getVersion();
+ auto targetProfileVersion = targetProfile.getVersion();
// Default to the entry point profile, since we know that has the right stage.
Profile effectiveProfile = entryPointProfile;
@@ -450,7 +481,7 @@ Profile getEffectiveProfile(EntryPoint* entryPoint, TargetRequest* target)
switch( effectiveProfile.getFamily() )
{
case ProfileFamily::DX:
- switch(effectiveProfile.GetStage())
+ switch(effectiveProfile.getStage())
{
default:
break;
@@ -472,7 +503,7 @@ Profile getEffectiveProfile(EntryPoint* entryPoint, TargetRequest* target)
break;
case ProfileFamily::GLSL:
- switch(effectiveProfile.GetStage())
+ switch(effectiveProfile.getStage())
{
default:
break;
@@ -494,7 +525,7 @@ Profile getEffectiveProfile(EntryPoint* entryPoint, TargetRequest* target)
break;
}
- if( stageMinVersion > effectiveProfile.GetVersion() )
+ if( stageMinVersion > effectiveProfile.getVersion() )
{
effectiveProfile.setVersion(stageMinVersion);
}
@@ -3166,7 +3197,7 @@ SLANG_API SlangProfileID spFindProfile(
SlangSession*,
char const* name)
{
- return Slang::Profile::LookUp(name).raw;
+ return Slang::Profile::lookUp(name).raw;
}
SLANG_API int spAddEntryPoint(
@@ -3327,7 +3358,7 @@ SLANG_API SlangResult spCompile(
{
if (req->dumpRepro.getLength())
{
- SlangResult saveRes = StateSerializeUtil::saveState(req, req->dumpRepro);
+ SlangResult saveRes = ReproUtil::saveState(req, req->dumpRepro);
if (SLANG_FAILED(saveRes))
{
req->getSink()->diagnose(SourceLoc(), Diagnostics::unableToWriteReproFile, req->dumpRepro);
@@ -3340,9 +3371,9 @@ SLANG_API SlangResult spCompile(
SlangResult saveRes = SLANG_FAIL;
RefPtr<Stream> stream;
- if (SLANG_SUCCEEDED(StateSerializeUtil::findUniqueReproDumpStream(req, reproFileName, stream)))
+ if (SLANG_SUCCEEDED(ReproUtil::findUniqueReproDumpStream(req, reproFileName, stream)))
{
- saveRes = StateSerializeUtil::saveState(req, stream);
+ saveRes = ReproUtil::saveState(req, stream);
}
if (SLANG_FAILED(saveRes))
@@ -3566,14 +3597,14 @@ SLANG_API SlangResult spLoadRepro(
auto request = asInternal(inRequest);
List<uint8_t> buffer;
- SLANG_RETURN_ON_FAIL(StateSerializeUtil::loadState((const uint8_t*)data, size, buffer));
+ SLANG_RETURN_ON_FAIL(ReproUtil::loadState((const uint8_t*)data, size, buffer));
MemoryOffsetBase base;
base.set(buffer.getBuffer(), buffer.getCount());
- StateSerializeUtil::RequestState* requestState = StateSerializeUtil::getRequest(buffer);
+ ReproUtil::RequestState* requestState = ReproUtil::getRequest(buffer);
- SLANG_RETURN_ON_FAIL(StateSerializeUtil::load(base, requestState, fileSystem, request));
+ SLANG_RETURN_ON_FAIL(ReproUtil::load(base, requestState, fileSystem, request));
return SLANG_OK;
}
@@ -3586,7 +3617,7 @@ SLANG_API SlangResult spSaveRepro(
OwnedMemoryStream stream(FileAccess::Write);
- SLANG_RETURN_ON_FAIL(StateSerializeUtil::saveState(request, &stream));
+ SLANG_RETURN_ON_FAIL(ReproUtil::saveState(request, &stream));
RefPtr<ListBlob> listBlob(new ListBlob);
@@ -3615,14 +3646,14 @@ SLANG_API SlangResult spExtractRepro(SlangSession* session, const void* reproDat
List<uint8_t> buffer;
{
MemoryStreamBase memoryStream(FileAccess::Read, reproData, reproDataSize);
- SLANG_RETURN_ON_FAIL(StateSerializeUtil::loadState(&memoryStream, buffer));
+ SLANG_RETURN_ON_FAIL(ReproUtil::loadState(&memoryStream, buffer));
}
MemoryOffsetBase base;
base.set(buffer.getBuffer(), buffer.getCount());
- StateSerializeUtil::RequestState* requestState = StateSerializeUtil::getRequest(buffer);
- return StateSerializeUtil::extractFiles(base, requestState, fileSystem);
+ ReproUtil::RequestState* requestState = ReproUtil::getRequest(buffer);
+ return ReproUtil::extractFiles(base, requestState, fileSystem);
}
SLANG_API SlangResult spLoadReproAsFileSystem(
@@ -3639,14 +3670,14 @@ SLANG_API SlangResult spLoadReproAsFileSystem(
MemoryStreamBase stream(FileAccess::Read, reproData, reproDataSize);
List<uint8_t> buffer;
- SLANG_RETURN_ON_FAIL(StateSerializeUtil::loadState(&stream, buffer));
+ SLANG_RETURN_ON_FAIL(ReproUtil::loadState(&stream, buffer));
- auto requestState = StateSerializeUtil::getRequest(buffer);
+ auto requestState = ReproUtil::getRequest(buffer);
MemoryOffsetBase base;
base.set(buffer.getBuffer(), buffer.getCount());
RefPtr<CacheFileSystem> cacheFileSystem;
- SLANG_RETURN_ON_FAIL(StateSerializeUtil::loadFileSystem(base, requestState, replaceFileSystem, cacheFileSystem));
+ SLANG_RETURN_ON_FAIL(ReproUtil::loadFileSystem(base, requestState, replaceFileSystem, cacheFileSystem));
*outFileSystem = cacheFileSystem.detach();
return SLANG_OK;
diff --git a/source/slang/slang.vcxproj b/source/slang/slang.vcxproj
index f6b321b7d..3be09765d 100644
--- a/source/slang/slang.vcxproj
+++ b/source/slang/slang.vcxproj
@@ -265,8 +265,8 @@
<ClInclude Include="slang-profile-defs.h" />
<ClInclude Include="slang-profile.h" />
<ClInclude Include="slang-reflection.h" />
+ <ClInclude Include="slang-repro.h" />
<ClInclude Include="slang-source-loc.h" />
- <ClInclude Include="slang-state-serialize.h" />
<ClInclude Include="slang-syntax.h" />
<ClInclude Include="slang-token-defs.h" />
<ClInclude Include="slang-token.h" />
@@ -352,8 +352,8 @@
<ClCompile Include="slang-preprocessor.cpp" />
<ClCompile Include="slang-profile.cpp" />
<ClCompile Include="slang-reflection.cpp" />
+ <ClCompile Include="slang-repro.cpp" />
<ClCompile Include="slang-source-loc.cpp" />
- <ClCompile Include="slang-state-serialize.cpp" />
<ClCompile Include="slang-stdlib.cpp" />
<ClCompile Include="slang-syntax.cpp" />
<ClCompile Include="slang-token.cpp" />
diff --git a/source/slang/slang.vcxproj.filters b/source/slang/slang.vcxproj.filters
index a636e338a..64f912110 100644
--- a/source/slang/slang.vcxproj.filters
+++ b/source/slang/slang.vcxproj.filters
@@ -246,10 +246,10 @@
<ClInclude Include="slang-reflection.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="slang-source-loc.h">
+ <ClInclude Include="slang-repro.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="slang-state-serialize.h">
+ <ClInclude Include="slang-source-loc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="slang-syntax.h">
@@ -503,10 +503,10 @@
<ClCompile Include="slang-reflection.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="slang-source-loc.cpp">
+ <ClCompile Include="slang-repro.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="slang-state-serialize.cpp">
+ <ClCompile Include="slang-source-loc.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="slang-stdlib.cpp">