summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/core/slang-string.cpp17
-rw-r--r--source/core/slang-string.h2
-rw-r--r--source/slang/emit.cpp88
-rw-r--r--source/slang/ir-constexpr.cpp11
-rw-r--r--source/slang/ir-inst-defs.h33
-rw-r--r--source/slang/ir-insts.h52
-rw-r--r--source/slang/ir-legalize-types.cpp31
-rw-r--r--source/slang/ir-serialize.cpp172
-rw-r--r--source/slang/ir.cpp785
-rw-r--r--source/slang/ir.h88
-rw-r--r--source/slang/legalize-types.cpp1
-rw-r--r--source/slang/lower-to-ir.cpp191
-rw-r--r--source/slang/mangle.cpp92
-rw-r--r--source/slang/mangle.h2
-rw-r--r--source/slang/slang.natvis31
15 files changed, 819 insertions, 777 deletions
diff --git a/source/core/slang-string.cpp b/source/core/slang-string.cpp
index 648249b2c..28acde6ac 100644
--- a/source/core/slang-string.cpp
+++ b/source/core/slang-string.cpp
@@ -45,6 +45,23 @@ namespace Slang
// UnownedStringSlice
+ bool UnownedStringSlice::startsWith(UnownedStringSlice const& other) const
+ {
+ UInt thisSize = size();
+ UInt otherSize = other.size();
+
+ if (otherSize > thisSize)
+ return false;
+
+ return UnownedStringSlice(begin(), begin() + otherSize) == other;
+ }
+
+ bool UnownedStringSlice::startsWith(char const* str) const
+ {
+ return startsWith(UnownedTerminatedStringSlice(str));
+ }
+
+
bool UnownedStringSlice::endsWith(UnownedStringSlice const& other) const
{
UInt thisSize = size();
diff --git a/source/core/slang-string.h b/source/core/slang-string.h
index 435e2b29b..5a20d8b75 100644
--- a/source/core/slang-string.h
+++ b/source/core/slang-string.h
@@ -133,6 +133,8 @@ namespace Slang
return !(*this == other);
}
+ bool startsWith(UnownedStringSlice const& other) const;
+ bool startsWith(char const* str) const;
bool endsWith(UnownedStringSlice const& other) const;
bool endsWith(char const* str) const;
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index f83ea894a..930520892 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -1,6 +1,7 @@
// emit.cpp
#include "emit.h"
+#include "../core/slang-writer.h"
#include "ir-insts.h"
#include "ir-restructure.h"
#include "ir-restructure-scoping.h"
@@ -2226,17 +2227,9 @@ struct EmitVisitor
// If the instruction has a mangled name, then emit using that.
- if (auto globalValue = as<IRGlobalValue>(inst))
+ if(auto linkageDecoration = inst->findDecoration<IRLinkageDecoration>())
{
- auto mangledName = globalValue->mangledName;
- if (mangledName)
- {
- auto mangledNameText = getText(mangledName);
- if (mangledNameText.Length() != 0)
- {
- return getText(mangledName);
- }
- }
+ return linkageDecoration->getMangledName();
}
// Otherwise fall back to a construct temporary name
@@ -3411,7 +3404,7 @@ struct EmitVisitor
// (which is `func` above), so we need to walk
// upwards to find it.
//
- IRGlobalValue* valueForName = func;
+ IRInst* valueForName = func;
for(;;)
{
auto parentBlock = as<IRBlock>(valueForName->parent);
@@ -3425,9 +3418,17 @@ struct EmitVisitor
valueForName = parentGeneric;
}
+ // If we reach this point, we are assuming that the value
+ // has some kind of linkage, and thus a mangled name.
+ //
+ auto linkageDecoration = valueForName->findDecoration<IRLinkageDecoration>();
+ SLANG_ASSERT(linkageDecoration);
+ auto mangledName = String(linkageDecoration->getMangledName());
+
+
// We will use the `UnmangleContext` utility to
// help us split the original name into its pieces.
- UnmangleContext um(getText(valueForName->mangledName));
+ UnmangleContext um(mangledName);
um.startUnmangling();
// We'll read through the qualified name of the
@@ -5969,13 +5970,16 @@ struct EmitVisitor
// appropriate decoration to these variables to indicate their
// purpose.
//
- if(getText(varDecl->mangledName).StartsWith("gl_"))
+ if(auto linkageDecoration = varDecl->findDecoration<IRLinkageDecoration>())
{
- // The variable represents an OpenGL system value,
- // so we will assume that it doesn't need to be declared.
- //
- // TODO: handle case where we *should* declare the variable.
- return;
+ if(linkageDecoration->getMangledName().startsWith("gl_"))
+ {
+ // The variable represents an OpenGL system value,
+ // so we will assume that it doesn't need to be declared.
+ //
+ // TODO: handle case where we *should* declare the variable.
+ return;
+ }
}
}
@@ -6363,6 +6367,31 @@ void legalizeTypes(
TypeLegalizationContext* context,
IRModule* module);
+static void dumpIRIfEnabled(
+ CompileRequest* compileRequest,
+ IRModule* irModule,
+ char const* label = nullptr)
+{
+ if(compileRequest->shouldDumpIR)
+ {
+ WriterHelper writer(compileRequest->getWriter(WriterChannel::StdError));
+
+ if(label)
+ {
+ writer.put("### ");
+ writer.put(label);
+ writer.put(":\n");
+ }
+
+ dumpIR(irModule, writer.getWriter());
+
+ if( label )
+ {
+ writer.put("###\n");
+ }
+ }
+}
+
String emitEntryPoint(
EntryPointRequest* entryPoint,
ProgramLayout* programLayout,
@@ -6422,9 +6451,7 @@ String emitEntryPoint(
&sharedContext.extensionUsageTracker);
#if 0
- fprintf(stderr, "### CLONED:\n");
- dumpIR(irModule);
- fprintf(stderr, "###\n");
+ dumpIRIfEnabled(compileRequest, irModule, "CLONED");
#endif
validateIRModuleIfEnabled(compileRequest, irModule);
@@ -6432,12 +6459,7 @@ String emitEntryPoint(
// If the user specified the flag that they want us to dump
// IR, then do it here, for the target-specific, but
// un-specialized IR.
- if (translationUnit->compileRequest->shouldDumpIR)
- {
- ISlangWriter* writer = translationUnit->compileRequest->getWriter(WriterChannel::StdError);
-
- dumpIR(irModule, writer);
- }
+ dumpIRIfEnabled(compileRequest, irModule);
// Next, we need to ensure that the code we emit for
// the target doesn't contain any operations that would
@@ -6449,9 +6471,7 @@ String emitEntryPoint(
// Debugging code for IR transformations...
#if 0
- fprintf(stderr, "### SPECIALIZED:\n");
- dumpIR(irModule);
- fprintf(stderr, "###\n");
+ dumpIRIfEnabled(compileRequest, irModule, "SPECIALIZED");
#endif
validateIRModuleIfEnabled(compileRequest, irModule);
@@ -6466,9 +6486,7 @@ String emitEntryPoint(
// Debugging output of legalization
#if 0
- fprintf(stderr, "### LEGALIZED:\n");
- dumpIR(irModule);
- fprintf(stderr, "###\n");
+ dumpIRIfEnabled(compileRequest, irModule, "LEGALIZED");
#endif
validateIRModuleIfEnabled(compileRequest, irModule);
@@ -6480,9 +6498,7 @@ String emitEntryPoint(
constructSSA(irModule);
#if 0
- fprintf(stderr, "### AFTER SSA:\n");
- dumpIR(irModule);
- fprintf(stderr, "###\n");
+ dumpIRIfEnabled(compileRequest, irModule, "AFTER SSA");
#endif
validateIRModuleIfEnabled(compileRequest, irModule);
diff --git a/source/slang/ir-constexpr.cpp b/source/slang/ir-constexpr.cpp
index 1f80bc010..684958ffe 100644
--- a/source/slang/ir-constexpr.cpp
+++ b/source/slang/ir-constexpr.cpp
@@ -16,8 +16,8 @@ struct PropagateConstExprContext
SharedIRBuilder sharedBuilder;
IRBuilder builder;
- List<IRGlobalValue*> workList;
- HashSet<IRGlobalValue*> onWorkList;
+ List<IRInst*> workList;
+ HashSet<IRInst*> onWorkList;
IRBuilder* getBuilder() { return &builder; }
@@ -158,7 +158,7 @@ bool propagateConstExprForward(
void maybeAddToWorkList(
PropagateConstExprContext* context,
- IRGlobalValue* gv)
+ IRInst* gv)
{
if( !context->onWorkList.Contains(gv) )
{
@@ -484,10 +484,7 @@ void propagateConstExpr(
for( auto ii : module->getGlobalInsts() )
{
- auto gv = as<IRGlobalValue>(ii);
- if (!gv)
- continue;
- maybeAddToWorkList(&context, gv);
+ maybeAddToWorkList(&context, ii);
}
// We will iterate applying propagation to one global value at a time
diff --git a/source/slang/ir-inst-defs.h b/source/slang/ir-inst-defs.h
index 202e80bcf..35a73c2f1 100644
--- a/source/slang/ir-inst-defs.h
+++ b/source/slang/ir-inst-defs.h
@@ -153,23 +153,19 @@ INST(StructType, struct, 0, PARENT)
INST_RANGE(Type, VoidType, StructType)
-/*IRGlobalValue*/
+/*IRGlobalValueWithCode*/
+ /* IRGlobalValueWIthParams*/
+ INST(Func, func, 0, PARENT)
+ INST(Generic, generic, 0, PARENT)
+ INST_RANGE(GlobalValueWithParams, Func, Generic)
- /*IRGlobalValueWithCode*/
- /* IRGlobalValueWIthParams*/
- INST(Func, func, 0, PARENT)
- INST(Generic, generic, 0, PARENT)
- INST_RANGE(GlobalValueWithParams, Func, Generic)
+ INST(GlobalVar, global_var, 0, 0)
+ INST(GlobalConstant, global_constant, 0, 0)
+INST_RANGE(GlobalValueWithCode, Func, GlobalConstant)
- INST(GlobalVar, global_var, 0, 0)
- INST(GlobalConstant, global_constant, 0, 0)
- INST_RANGE(GlobalValueWithCode, Func, GlobalConstant)
-
- INST(StructKey, key, 0, 0)
- INST(GlobalGenericParam, global_generic_param, 0, 0)
- INST(WitnessTable, witness_table, 0, 0)
-
-INST_RANGE(GlobalValue, StructType, WitnessTable)
+INST(StructKey, key, 0, 0)
+INST(GlobalGenericParam, global_generic_param, 0, 0)
+INST(WitnessTable, witness_table, 0, 0)
INST(Module, module, 0, PARENT)
@@ -384,7 +380,12 @@ INST(HighLevelDeclDecoration, highLevelDecl, 1, 0)
INST(GloballyCoherentDecoration, globallyCoherent, 0, 0)
INST(PatchConstantFuncDecoration, patchConstantFunc, 1, 0)
-INST_RANGE(Decoration, HighLevelDeclDecoration, PatchConstantFuncDecoration)
+ /* LinkageDecoration */
+ INST(ImportDecoration, import, 1, 0)
+ INST(ExportDecoration, export, 1, 0)
+ INST_RANGE(LinkageDecoration, ImportDecoration, ExportDecoration)
+
+INST_RANGE(Decoration, HighLevelDeclDecoration, ExportDecoration)
//
diff --git a/source/slang/ir-insts.h b/source/slang/ir-insts.h
index c3d21a4bd..1dfd52d8a 100644
--- a/source/slang/ir-insts.h
+++ b/source/slang/ir-insts.h
@@ -227,6 +227,37 @@ IR_SIMPLE_DECORATION(ReadNoneDecoration)
IR_SIMPLE_DECORATION(EarlyDepthStencilDecoration)
IR_SIMPLE_DECORATION(GloballyCoherentDecoration)
+ /// A decoration that marks a value as having linkage.
+ ///
+ /// A value with linkage is either exported from its module,
+ /// or will have a definition imported from another module.
+ /// In either case, it requires a mangled name to use when
+ /// matching imports and exports.
+ ///
+struct IRLinkageDecoration : IRDecoration
+{
+ IR_PARENT_ISA(LinkageDecoration)
+
+ IRStringLit* getMangledNameOperand() { return cast<IRStringLit>(getOperand(0)); }
+
+ UnownedStringSlice getMangledName()
+ {
+ return getMangledNameOperand()->getStringSlice();
+ }
+};
+
+struct IRImportDecoration : IRLinkageDecoration
+{
+ enum { kOp = kIROp_ImportDecoration };
+ IR_LEAF_ISA(ImportDecoration)
+};
+
+struct IRExportDecoration : IRLinkageDecoration
+{
+ enum { kOp = kIROp_ExportDecoration };
+ IR_LEAF_ISA(ExportDecoration)
+};
+
// An instruction that specializes another IR value
// (representing a generic) to a particular set of generic arguments
// (instructions representing types, witness tables, etc.)
@@ -544,7 +575,7 @@ struct IRWitnessTableEntry : IRInst
// interface. It basically takes the form of a
// map from the required members of the interface
// to the IR values that satisfy those requirements.
-struct IRWitnessTable : IRGlobalValue
+struct IRWitnessTable : IRInst
{
IRInstList<IRWitnessTableEntry> getEntries()
{
@@ -565,7 +596,7 @@ struct IRUndefined : IRInst
// A global-scope generic parameter (a type parameter, a
// constraint parameter, etc.)
-struct IRGlobalGenericParam : IRGlobalValue
+struct IRGlobalGenericParam : IRInst
{
IR_LEAF_ISA(GlobalGenericParam)
};
@@ -797,10 +828,6 @@ struct IRBuilder
IRType* getType(
IROp op);
-
- IRWitnessTable* lookupWitnessTable(Name* mangledName);
- void registerWitnessTable(IRWitnessTable* table);
-
/// Create an empty basic block.
///
/// The created block will not be inserted into the current
@@ -1043,6 +1070,15 @@ struct IRBuilder
addDecoration(value, kIROp_PatchConstantFuncDecoration, patchConstantFunc);
}
+ void addImportDecoration(IRInst* value, UnownedStringSlice const& mangledName)
+ {
+ addDecoration(value, kIROp_ImportDecoration, getStringValue(mangledName));
+ }
+
+ void addExportDecoration(IRInst* value, UnownedStringSlice const& mangledName)
+ {
+ addDecoration(value, kIROp_ExportDecoration, getStringValue(mangledName));
+ }
};
// Helper to establish the source location that will be used
@@ -1091,10 +1127,6 @@ IRSpecializationState* createIRSpecializationState(
void destroyIRSpecializationState(IRSpecializationState* state);
IRModule* getIRModule(IRSpecializationState* state);
-IRGlobalValue* getSpecializedGlobalValueForDeclRef(
- IRSpecializationState* state,
- DeclRef<Decl> const& declRef);
-
struct ExtensionUsageTracker;
// Clone the IR values reachable from the given entry point
diff --git a/source/slang/ir-legalize-types.cpp b/source/slang/ir-legalize-types.cpp
index 46ba59bcd..901d8705b 100644
--- a/source/slang/ir-legalize-types.cpp
+++ b/source/slang/ir-legalize-types.cpp
@@ -109,7 +109,7 @@ static void registerLegalizedValue(
struct IRGlobalNameInfo
{
- IRGlobalValue* globalVar;
+ IRInst* globalVar;
UInt counter;
};
@@ -1156,6 +1156,8 @@ static LegalVal declareSimpleVar(
UnownedStringSlice nameHint,
IRGlobalNameInfo* globalNameInfo)
{
+ SLANG_UNUSED(globalNameInfo);
+
RefPtr<VarLayout> varLayout = createVarLayout(varChain, typeLayout);
DeclRef<VarDeclBase> varDeclRef;
@@ -1177,25 +1179,6 @@ static LegalVal declareSimpleVar(
globalVar->removeFromParent();
globalVar->insertBefore(context->insertBeforeGlobal);
- // The legalization of a global variable with linkage (one that has
- // a mangled name), must also have an exported name, so that code
- // can link against it.
- //
- // For now we do something *really* simplistic, and just append
- // a counter to each leaf variable generated from the original
- if (globalNameInfo)
- {
- String mangledNameStr = getText(globalNameInfo->globalVar->mangledName);
- if (mangledNameStr.Length() != 0)
- {
- mangledNameStr.append("L");
- mangledNameStr.append(Int32(globalNameInfo->counter++));
- globalVar->mangledName = context->session->getNameObj(mangledNameStr);
- }
- }
-
-
-
irVar = globalVar;
legalVarVal = LegalVal::simple(irVar);
}
@@ -1301,7 +1284,13 @@ static LegalVal declareVars(
for (auto ee : tupleType->elements)
{
- auto fieldLayout = getFieldLayout(typeLayout, getText(ee.key->mangledName));
+ // Fields are currently required to have linkage, since we use
+ // their mangled name to look up field layout information.
+ //
+ auto fieldLinkage = ee.key->findDecoration<IRLinkageDecoration>();
+ SLANG_ASSERT(fieldLinkage);
+
+ auto fieldLayout = getFieldLayout(typeLayout, fieldLinkage->getMangledName());
RefPtr<TypeLayout> fieldTypeLayout = fieldLayout ? fieldLayout->typeLayout : nullptr;
// If we are processing layout information, then
diff --git a/source/slang/ir-serialize.cpp b/source/slang/ir-serialize.cpp
index 0fc8a0806..f3ccbd6c1 100644
--- a/source/slang/ir-serialize.cpp
+++ b/source/slang/ir-serialize.cpp
@@ -20,7 +20,6 @@ variables, but only a few types include extra data, and these do not have any op
* IRConstant - Needs special-case handling
* IRModuleInst - Presumably we can just set to the module pointer on reconstruction
-* IRGlobalValue - There are types derived from this type, but they don't add a parameter
Note! That on an IRInst there is an IRType* variable (accessed as getFullType()). As it stands it may NOT actually point
to an IRType derived type. Its 'ok' as long as it's an instruction that can be used in the place of the type. So this code does not
@@ -41,12 +40,6 @@ bother to check if it's correct, and just casts it.
{ 0, 0 } // Int64,
};
-static bool isGlobalValueDerived(IROp opIn)
-{
- const int op = (kIROpMeta_PseudoOpMask & opIn);
- return op >= kIROp_FirstGlobalValue && op <= kIROp_LastGlobalValue;
-}
-
static bool isTextureTypeBase(IROp opIn)
{
const int op = (kIROpMeta_PseudoOpMask & opIn);
@@ -501,13 +494,6 @@ Result IRSerialWriter::write(IRModule* module, SourceManager* sourceManager, Opt
}
continue;
}
- IRGlobalValue* globValue = as<IRGlobalValue>(srcInst);
- if (globValue)
- {
- dstInst.m_payloadType = PayloadType::String_1;
- dstInst.m_payload.m_stringIndices[0] = getStringIndex(globValue->mangledName);
- continue;
- }
IRTextureTypeBase* textureBase = as<IRTextureTypeBase>(srcInst);
if (textureBase)
@@ -1340,104 +1326,90 @@ int64_t _calcChunkTotalSize(const IRSerialBinary::Chunk& chunk)
const IROp op((IROp)srcInst.m_op);
- if (isGlobalValueDerived(op))
+ if (isConstant(op))
{
- // Cannot have operands
- SLANG_ASSERT(srcInst.getNumOperands() == 0);
-
- IRGlobalValue* globalValueInst = static_cast<IRGlobalValue*>(createEmptyInstWithSize(module, op, sizeof(IRGlobalValue)));
- insts[i] = globalValueInst;
- // Set the global value
- SLANG_ASSERT(srcInst.m_payloadType == PayloadType::String_1);
- globalValueInst->mangledName = m_stringRepresentationCache.getName(StringHandle(srcInst.m_payload.m_stringIndices[0]));
- }
- else
- {
- if (isConstant(op))
- {
- // Handling of constants
+ // Handling of constants
- // Calculate the minimum object size (ie not including the payload of value)
- const size_t prefixSize = SLANG_OFFSET_OF(IRConstant, value);
+ // Calculate the minimum object size (ie not including the payload of value)
+ const size_t prefixSize = SLANG_OFFSET_OF(IRConstant, value);
- IRConstant* irConst = nullptr;
- switch (op)
- {
- case kIROp_BoolLit:
- {
- SLANG_ASSERT(srcInst.m_payloadType == PayloadType::UInt32);
- irConst = static_cast<IRConstant*>(createEmptyInstWithSize(module, op, prefixSize + sizeof(IRIntegerValue)));
- irConst->value.intVal = srcInst.m_payload.m_uint32 != 0;
- break;
- }
- case kIROp_IntLit:
- {
- SLANG_ASSERT(srcInst.m_payloadType == PayloadType::Int64);
- irConst = static_cast<IRConstant*>(createEmptyInstWithSize(module, op, prefixSize + sizeof(IRIntegerValue)));
- irConst->value.intVal = srcInst.m_payload.m_int64;
- break;
- }
- case kIROp_PtrLit:
- {
- SLANG_ASSERT(srcInst.m_payloadType == PayloadType::Int64);
- irConst = static_cast<IRConstant*>(createEmptyInstWithSize(module, op, prefixSize + sizeof(void*)));
- irConst->value.ptrVal = (void*) (intptr_t) srcInst.m_payload.m_int64;
- break;
- }
- case kIROp_FloatLit:
- {
- SLANG_ASSERT(srcInst.m_payloadType == PayloadType::Float64);
- irConst = static_cast<IRConstant*>(createEmptyInstWithSize(module, op, prefixSize + sizeof(IRFloatingPointValue)));
- irConst->value.floatVal = srcInst.m_payload.m_float64;
- break;
- }
- case kIROp_StringLit:
- {
- SLANG_ASSERT(srcInst.m_payloadType == PayloadType::String_1);
+ IRConstant* irConst = nullptr;
+ switch (op)
+ {
+ case kIROp_BoolLit:
+ {
+ SLANG_ASSERT(srcInst.m_payloadType == PayloadType::UInt32);
+ irConst = static_cast<IRConstant*>(createEmptyInstWithSize(module, op, prefixSize + sizeof(IRIntegerValue)));
+ irConst->value.intVal = srcInst.m_payload.m_uint32 != 0;
+ break;
+ }
+ case kIROp_IntLit:
+ {
+ SLANG_ASSERT(srcInst.m_payloadType == PayloadType::Int64);
+ irConst = static_cast<IRConstant*>(createEmptyInstWithSize(module, op, prefixSize + sizeof(IRIntegerValue)));
+ irConst->value.intVal = srcInst.m_payload.m_int64;
+ break;
+ }
+ case kIROp_PtrLit:
+ {
+ SLANG_ASSERT(srcInst.m_payloadType == PayloadType::Int64);
+ irConst = static_cast<IRConstant*>(createEmptyInstWithSize(module, op, prefixSize + sizeof(void*)));
+ irConst->value.ptrVal = (void*) (intptr_t) srcInst.m_payload.m_int64;
+ break;
+ }
+ case kIROp_FloatLit:
+ {
+ SLANG_ASSERT(srcInst.m_payloadType == PayloadType::Float64);
+ irConst = static_cast<IRConstant*>(createEmptyInstWithSize(module, op, prefixSize + sizeof(IRFloatingPointValue)));
+ irConst->value.floatVal = srcInst.m_payload.m_float64;
+ break;
+ }
+ case kIROp_StringLit:
+ {
+ SLANG_ASSERT(srcInst.m_payloadType == PayloadType::String_1);
- const UnownedStringSlice slice = m_stringRepresentationCache.getStringSlice(StringHandle(srcInst.m_payload.m_stringIndices[0]));
+ const UnownedStringSlice slice = m_stringRepresentationCache.getStringSlice(StringHandle(srcInst.m_payload.m_stringIndices[0]));
- const size_t sliceSize = slice.size();
- const size_t instSize = prefixSize + SLANG_OFFSET_OF(IRConstant::StringValue, chars) + sliceSize;
+ const size_t sliceSize = slice.size();
+ const size_t instSize = prefixSize + SLANG_OFFSET_OF(IRConstant::StringValue, chars) + sliceSize;
- irConst = static_cast<IRConstant*>(createEmptyInstWithSize(module, op, instSize));
+ irConst = static_cast<IRConstant*>(createEmptyInstWithSize(module, op, instSize));
- IRConstant::StringValue& dstString = irConst->value.stringVal;
+ IRConstant::StringValue& dstString = irConst->value.stringVal;
- dstString.numChars = uint32_t(sliceSize);
- // Turn into pointer to avoid warning of array overrun
- char* dstChars = dstString.chars;
- // Copy the chars
- memcpy(dstChars, slice.begin(), sliceSize);
- break;
- }
- default:
- {
- SLANG_ASSERT(!"Unknown constant type");
- return SLANG_FAIL;
- }
+ dstString.numChars = uint32_t(sliceSize);
+ // Turn into pointer to avoid warning of array overrun
+ char* dstChars = dstString.chars;
+ // Copy the chars
+ memcpy(dstChars, slice.begin(), sliceSize);
+ break;
+ }
+ default:
+ {
+ SLANG_ASSERT(!"Unknown constant type");
+ return SLANG_FAIL;
}
-
- insts[i] = irConst;
}
- else if (isTextureTypeBase(op))
- {
- IRTextureTypeBase* inst = static_cast<IRTextureTypeBase*>(createEmptyInst(module, op, 1));
- SLANG_ASSERT(srcInst.m_payloadType == PayloadType::OperandAndUInt32);
- // Reintroduce the texture type bits into the the
- const uint32_t other = srcInst.m_payload.m_operandAndUInt32.m_uint32;
- inst->op = IROp(uint32_t(inst->op) | (other << kIROpMeta_OtherShift));
+ insts[i] = irConst;
+ }
+ else if (isTextureTypeBase(op))
+ {
+ IRTextureTypeBase* inst = static_cast<IRTextureTypeBase*>(createEmptyInst(module, op, 1));
+ SLANG_ASSERT(srcInst.m_payloadType == PayloadType::OperandAndUInt32);
- insts[i] = inst;
- }
- else
- {
- int numOperands = srcInst.getNumOperands();
- insts[i] = createEmptyInst(module, op, numOperands);
- }
- }
- }
+ // Reintroduce the texture type bits into the the
+ const uint32_t other = srcInst.m_payload.m_operandAndUInt32.m_uint32;
+ inst->op = IROp(uint32_t(inst->op) | (other << kIROpMeta_OtherShift));
+
+ insts[i] = inst;
+ }
+ else
+ {
+ int numOperands = srcInst.getNumOperands();
+ insts[i] = createEmptyInst(module, op, numOperands);
+ }
+ }
// Patch up the operands
for (int i = 1; i < numInsts; ++i)
diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp
index 784c5034d..b8892cc02 100644
--- a/source/slang/ir.cpp
+++ b/source/slang/ir.cpp
@@ -11,10 +11,10 @@ namespace Slang
{
struct IRSpecContext;
- IRGlobalValue* cloneGlobalValueWithMangledName(
- IRSpecContext* context,
- Name* mangledName,
- IRGlobalValue* originalVal);
+ IRInst* cloneGlobalValueWithLinkage(
+ IRSpecContext* context,
+ IRInst* originalVal,
+ IRLinkageDecoration* originalLinkage);
struct IROpMapEntry
{
@@ -1876,8 +1876,8 @@ namespace Slang
}
void addGlobalValue(
- IRBuilder* builder,
- IRGlobalValue* value)
+ IRBuilder* builder,
+ IRInst* value)
{
// Try to find a suitable parent for the
// global value we are emitting.
@@ -2057,21 +2057,6 @@ namespace Slang
return irGeneric;
}
-
- IRWitnessTable * IRBuilder::lookupWitnessTable(Name* mangledName)
- {
- IRWitnessTable * result;
- if (sharedBuilder->witnessTableMap.TryGetValue(mangledName, result))
- return result;
- return nullptr;
- }
-
-
- void IRBuilder::registerWitnessTable(IRWitnessTable * table)
- {
- sharedBuilder->witnessTableMap[table->mangledName] = table;
- }
-
IRBlock* IRBuilder::createBlock()
{
return createInst<IRBlock>(
@@ -2628,11 +2613,13 @@ namespace Slang
struct IRDumpContext
{
- StringBuilder* builder;
- int indent = 0;
+ StringBuilder* builder = nullptr;
+ int indent = 0;
+ IRDumpMode mode = IRDumpMode::Simplified;
- UInt idCounter = 1;
- Dictionary<IRInst*, UInt> mapValueToID;
+ Dictionary<IRInst*, String> mapValueToName;
+ Dictionary<String, UInt> uniqueNameCounters;
+ UInt uniqueIDCounter = 1;
};
static void dump(
@@ -2644,19 +2631,25 @@ namespace Slang
static void dump(
IRDumpContext* context,
+ String const& text)
+ {
+ context->builder->append(text);
+ }
+
+ /*
+ static void dump(
+ IRDumpContext* context,
UInt val)
{
context->builder->append(UnambigousUInt(val));
-// fprintf(context->file, "%llu", (unsigned long long)val);
}
+ */
static void dump(
IRDumpContext* context,
IntegerLiteralValue val)
{
context->builder->append(val);
-
-// fprintf(context->file, "%llu", (unsigned long long)val);
}
static void dump(
@@ -2664,8 +2657,6 @@ namespace Slang
FloatingPointLiteralValue val)
{
context->builder->append(val);
-
-// fprintf(context->file, "%llu", (unsigned long long)val);
}
static void dumpIndent(
@@ -2697,21 +2688,115 @@ namespace Slang
return inst->firstUse != nullptr;
}
- static UInt getID(
+ static void scrubName(
+ String const& name,
+ StringBuilder& sb)
+ {
+ // Note: this function duplicates a lot of the logic
+ // in `EmitVisitor::scrubName`, so we should consider
+ // whether they can share code at some point.
+ //
+ // There is no requirement that assembly dumps and output
+ // code follow the same model, though, so this is just
+ // a nice-to-have rather than a maintenance problem
+ // waiting to happen.
+
+ // Allow an empty nam
+ // Special case a name that is the empty string, just in case.
+ if(name.Length() == 0)
+ {
+ sb.append('_');
+ }
+
+ int prevChar = -1;
+ for(auto c : name)
+ {
+ if(c == '.')
+ {
+ c = '_';
+ }
+
+ if(((c >= 'a') && (c <= 'z'))
+ || ((c >= 'A') && (c <= 'Z')))
+ {
+ // Ordinary ASCII alphabetic characters are assumed
+ // to always be okay.
+ }
+ else if((c >= '0') && (c <= '9'))
+ {
+ // We don't want to allow a digit as the first
+ // byte in a name.
+ if(prevChar == -1)
+ {
+ sb.append('_');
+ }
+ }
+ else
+ {
+ // If we run into a character that wouldn't normally
+ // be allowed in an identifier, we need to translate
+ // it into something that *is* valid.
+ //
+ // Our solution for now will be very clumsy: we will
+ // emit `x` and then the hexadecimal version of
+ // the byte we were given.
+ sb.append("x");
+ sb.append(uint32_t((unsigned char) c), 16);
+
+ // We don't want to apply the default handling below,
+ // so skip to the top of the loop now.
+ prevChar = c;
+ continue;
+ }
+
+ sb.append(c);
+ prevChar = c;
+ }
+
+ // If the whole thing ended with a digit, then add
+ // a final `_` just to make sure that we can append
+ // a unique ID suffix without risk of collisions.
+ if(('0' <= prevChar) && (prevChar <= '9'))
+ {
+ sb.append('_');
+ }
+ }
+
+
+ static String getName(
IRDumpContext* context,
IRInst* value)
{
- UInt id = 0;
- if (context->mapValueToID.TryGetValue(value, id))
- return id;
+ String name = 0;
+ if (context->mapValueToName.TryGetValue(value, name))
+ return name;
- if (opHasResult(value) || instHasUses(value))
+ if(auto nameHintDecoration = value->findDecoration<IRNameHintDecoration>())
{
- id = context->idCounter++;
- }
+ String nameHint = nameHintDecoration->getName();
+
+ StringBuilder sb;
+ scrubName(nameHint, sb);
+
+ String key = sb.ProduceString();
+ UInt count = 0;
+ context->uniqueNameCounters.TryGetValue(key, count);
- context->mapValueToID.Add(value, id);
- return id;
+ context->uniqueNameCounters[key] = count+1;
+
+ if(count)
+ {
+ sb.append(count);
+ }
+ return sb.ProduceString();
+ }
+ else
+ {
+ StringBuilder sb;
+ auto id = context->uniqueIDCounter++;
+ sb.append(id);
+ return sb.ProduceString();
+ }
}
static void dumpID(
@@ -2724,26 +2809,10 @@ namespace Slang
return;
}
- if (auto globalValue = as<IRGlobalValue>(inst))
- {
- auto mangledName = globalValue->mangledName;
- if(mangledName)
- {
- auto mangledNameText = getText(mangledName);
- if (mangledNameText.Length() > 0)
- {
- dump(context, "@");
- dump(context, mangledNameText.Buffer());
- return;
- }
- }
- }
-
- UInt id = getID(context, inst);
- if (id)
+ if( opHasResult(inst) || instHasUses(inst) )
{
dump(context, "%");
- dump(context, id);
+ dump(context, getName(context, inst));
}
else
{
@@ -2859,6 +2928,38 @@ namespace Slang
IRDumpContext* context,
IRType* type);
+ static bool shouldFoldInstIntoUses(
+ IRDumpContext* context,
+ IRInst* inst)
+ {
+ // Never fold an instruction into its use site
+ // in the "detailed" mode, so that we always
+ // accurately reflect the structure of the IR.
+ //
+ if(context->mode == IRDumpMode::Detailed)
+ return false;
+
+ if(as<IRConstant>(inst))
+ return true;
+
+ if(as<IRType>(inst))
+ return true;
+
+ return false;
+ }
+
+ static void dumpInst(
+ IRDumpContext* context,
+ IRInst* inst);
+
+ static void dumpInstBody(
+ IRDumpContext* context,
+ IRInst* inst);
+
+ static void dumpInstExpr(
+ IRDumpContext* context,
+ IRInst* inst);
+
static void dumpOperand(
IRDumpContext* context,
IRInst* inst)
@@ -2870,25 +2971,10 @@ namespace Slang
return;
}
- switch (inst->op)
+ if(shouldFoldInstIntoUses(context, inst))
{
- case kIROp_IntLit:
- dump(context, ((IRConstant*)inst)->value.intVal);
- return;
-
- case kIROp_FloatLit:
- dump(context, ((IRConstant*)inst)->value.floatVal);
+ dumpInstExpr(context, inst);
return;
-
- case kIROp_BoolLit:
- dump(context, ((IRConstant*)inst)->value.intVal ? "true" : "false");
- return;
- case kIROp_StringLit:
- dumpEncodeString(context, static_cast<IRConstant*>(inst)->getStringSlice());
- return;
-
- default:
- break;
}
dumpID(context, inst);
@@ -2919,9 +3005,39 @@ namespace Slang
}
- static void dumpInst(
+ void dumpIRDecorations(
IRDumpContext* context,
- IRInst* inst);
+ IRInst* inst)
+ {
+ for(auto dd : inst->getDecorations())
+ {
+ // Certain decorations aren't helpful to appear
+ // in output dumps, so we will only include them
+ // in the "detailed" dumping mode.
+ //
+ // For all other modes, we will check the opcode
+ // and skip selected decorations.
+ //
+ if(context->mode != IRDumpMode::Detailed)
+ {
+ switch(dd->op)
+ {
+ default:
+ break;
+
+ case kIROp_HighLevelDeclDecoration:
+ case kIROp_LayoutDecoration:
+ continue;
+ }
+ }
+
+ dump(context, "[");
+ dumpInstBody(context, dd);
+ dump(context, "]\n");
+
+ dumpIndent(context);
+ }
+ }
static void dumpBlock(
IRDumpContext* context,
@@ -2952,6 +3068,7 @@ namespace Slang
inst = inst->getNextInst();
dumpIndent(context);
+ dumpIRDecorations(context, param);
dump(context, "param ");
dumpID(context, param);
dumpInstTypeClause(context, param->getFullType());
@@ -2965,25 +3082,6 @@ namespace Slang
for(; inst; inst = inst->getNextInst())
{
dumpInst(context, inst);
- dump(context, "\n");
- }
- }
-
- static void dumpInstBody(
- IRDumpContext* context,
- IRInst* inst);
-
- void dumpIRDecorations(
- IRDumpContext* context,
- IRInst* inst)
- {
- for(auto dd : inst->getDecorations())
- {
- dump(context, "[");
- dumpInstBody(context, dd);
- dump(context, "]\n");
-
- dumpIndent(context);
}
}
@@ -3021,20 +3119,10 @@ namespace Slang
}
context->indent--;
- dump(context, "}\n");
+ dump(context, "}");
}
- String dumpIRFunc(IRFunc* func)
- {
- IRDumpContext dumpContext;
- StringBuilder sbDump;
- dumpContext.builder = &sbDump;
- dumpIRGlobalValueWithCode(&dumpContext, func);
- auto strFunc = sbDump.ToString();
- return strFunc;
- }
-
void dumpIRWitnessTableEntry(
IRDumpContext* context,
IRWitnessTableEntry* entry)
@@ -3075,7 +3163,6 @@ namespace Slang
for(auto child : inst->getChildren())
{
dumpInst(context, child);
- dump(context, "\n");
}
context->indent--;
@@ -3096,13 +3183,91 @@ namespace Slang
for (auto ii : witnessTable->getChildren())
{
dumpInst(context, ii);
- dump(context, "\n");
}
context->indent--;
dump(context, "}\n");
}
+ static void dumpInstExpr(
+ IRDumpContext* context,
+ IRInst* inst)
+ {
+ if (!inst)
+ {
+ dump(context, "<null>");
+ return;
+ }
+
+ auto op = inst->op;
+ auto opInfo = getIROpInfo(op);
+
+ // Special-case the literal instructions.
+ if(auto irConst = as<IRConstant>(inst))
+ {
+ switch (op)
+ {
+ case kIROp_IntLit:
+ dump(context, irConst->value.intVal);
+ return;
+
+ case kIROp_FloatLit:
+ dump(context, irConst->value.floatVal);
+ return;
+
+ case kIROp_BoolLit:
+ dump(context, irConst->value.intVal ? "true" : "false");
+ return;
+
+ case kIROp_StringLit:
+ dumpEncodeString(context, irConst->getStringSlice());
+ return;
+
+ case kIROp_PtrLit:
+ dump(context, "<ptr>");
+ return;
+
+ default:
+ break;
+ }
+ }
+
+ dump(context, opInfo.name);
+
+ UInt argCount = inst->getOperandCount();
+
+ if(argCount == 0)
+ return;
+
+ UInt ii = 0;
+
+ // Special case: make printing of `call` a bit
+ // nicer to look at
+ if (inst->op == kIROp_Call && argCount > 0)
+ {
+ dump(context, " ");
+ auto argVal = inst->getOperand(ii++);
+ dumpOperand(context, argVal);
+ }
+
+ bool first = true;
+ dump(context, "(");
+ for (; ii < argCount; ++ii)
+ {
+ if (!first)
+ dump(context, ", ");
+
+ auto argVal = inst->getOperand(ii);
+
+ dumpOperand(context, argVal);
+
+ first = false;
+ }
+
+ dump(context, ")");
+
+ }
+
static void dumpInstBody(
IRDumpContext* context,
IRInst* inst)
@@ -3143,7 +3308,6 @@ namespace Slang
}
// Okay, we have a seemingly "ordinary" op now
- auto opInfo = getIROpInfo(op);
auto dataType = inst->getDataType();
auto rate = inst->getRate();
@@ -3166,57 +3330,19 @@ namespace Slang
// No result, okay...
}
- dump(context, opInfo.name);
-
- UInt argCount = inst->getOperandCount();
- UInt ii = 0;
-
- // Special case: make printing of `call` a bit
- // nicer to look at
- if (inst->op == kIROp_Call && argCount > 0)
- {
- dump(context, " ");
- auto argVal = inst->getOperand(ii++);
- dumpOperand(context, argVal);
- }
-
- bool first = true;
- dump(context, "(");
- for (; ii < argCount; ++ii)
- {
- if (!first)
- dump(context, ", ");
-
- auto argVal = inst->getOperand(ii);
-
- dumpOperand(context, argVal);
-
- first = false;
- }
-
- // Special cases: literals and other instructions with no real operands
- switch (inst->op)
- {
- case kIROp_IntLit:
- case kIROp_FloatLit:
- case kIROp_BoolLit:
- case kIROp_StringLit:
- dumpOperand(context, inst);
- break;
-
- default:
- break;
- }
-
- dump(context, ")");
+ dumpInstExpr(context, inst);
}
static void dumpInst(
IRDumpContext* context,
IRInst* inst)
{
+ if(shouldFoldInstIntoUses(context, inst))
+ return;
+
dumpIndent(context);
dumpInstBody(context, inst);
+ dump(context, "\n");
}
void dumpIRModule(
@@ -3226,51 +3352,45 @@ namespace Slang
for(auto ii : module->getGlobalInsts())
{
dumpInst(context, ii);
- dump(context, "\n");
}
}
- void printSlangIRAssembly(StringBuilder& builder, IRModule* module)
+ void printSlangIRAssembly(StringBuilder& builder, IRModule* module, IRDumpMode mode)
{
IRDumpContext context;
context.builder = &builder;
context.indent = 0;
+ context.mode = mode;
dumpIRModule(&context, module);
}
- void dumpIR(IRGlobalValue* globalVal, ISlangWriter* writer)
+ void dumpIR(IRInst* globalVal, ISlangWriter* writer, IRDumpMode mode)
{
StringBuilder sb;
IRDumpContext context;
context.builder = &sb;
context.indent = 0;
+ context.mode = mode;
dumpInst(&context, globalVal);
writer->write(sb.Buffer(), sb.Length());
- char cr[] = "\n";
- writer->write(cr, 1);
-
writer->flush();
}
- String getSlangIRAssembly(IRModule* module)
+ String getSlangIRAssembly(IRModule* module, IRDumpMode mode)
{
StringBuilder sb;
- printSlangIRAssembly(sb, module);
+ printSlangIRAssembly(sb, module, mode);
return sb;
}
- void dumpIR(IRModule* module, ISlangWriter* writer)
+ void dumpIR(IRModule* module, ISlangWriter* writer, IRDumpMode mode)
{
- String ir = getSlangIRAssembly(module);
-
+ String ir = getSlangIRAssembly(module, mode);
writer->write(ir.Buffer(), ir.Length());
- char cr[] = "\n";
- writer->write(cr, 1);
-
writer->flush();
}
@@ -3566,9 +3686,6 @@ namespace Slang
if(as<IRType>(this))
return false;
- if(as<IRGlobalValue>(this))
- return false;
-
if(as<IRConstant>(this))
return false;
@@ -3606,6 +3723,19 @@ namespace Slang
}
return true;
+ // All of the cases for "global values" are side-effect-free.
+ case kIROp_StructType:
+ case kIROp_StructField:
+ case kIROp_Func:
+ case kIROp_Generic:
+ case kIROp_GlobalVar:
+ case kIROp_GlobalConstant:
+ case kIROp_StructKey:
+ case kIROp_GlobalGenericParam:
+ case kIROp_WitnessTable:
+ case kIROp_WitnessTableEntry:
+ return false;
+
case kIROp_Nop:
case kIROp_Specialize:
case kIROp_lookup_interface_method:
@@ -3686,8 +3816,8 @@ namespace Slang
}
void moveValueBefore(
- IRGlobalValue* valueToMove,
- IRGlobalValue* placeBefore)
+ IRInst* valueToMove,
+ IRInst* placeBefore)
{
valueToMove->removeFromParent();
valueToMove->insertBefore(placeBefore);
@@ -4158,7 +4288,7 @@ namespace Slang
if( systemValueInfo )
{
- globalVariable->mangledName = builder->getSession()->getNameObj(systemValueInfo->name);
+ builder->addImportDecoration(globalVariable, UnownedTerminatedStringSlice(systemValueInfo->name));
if( auto fromType = systemValueInfo->requiredType )
{
@@ -5214,7 +5344,7 @@ namespace Slang
struct IRSpecSymbol : RefObject
{
- IRGlobalValue* irGlobalValue;
+ IRInst* irGlobalValue;
RefPtr<IRSpecSymbol> nextWithSameName;
};
@@ -5241,7 +5371,7 @@ namespace Slang
// A map from mangled symbol names to zero or
// more global IR values that have that name,
// in the *original* module.
- typedef Dictionary<Name*, RefPtr<IRSpecSymbol>> SymbolDictionary;
+ typedef Dictionary<String, RefPtr<IRSpecSymbol>> SymbolDictionary;
SymbolDictionary symbols;
SharedIRBuilder sharedBuilderStorage;
@@ -5251,6 +5381,47 @@ namespace Slang
IRSpecEnv globalEnv;
};
+ struct IRGenericSpecKey
+ {
+ // Note: Slang::Dictionary requires key types to have default constructors
+ IRGenericSpecKey()
+ {}
+
+ IRGenericSpecKey(IRSpecialize* specializeInst)
+ {
+ m_values.Add(specializeInst->getBase());
+ auto argCount = specializeInst->getArgCount();
+ for(UInt aa = 0; aa < argCount; ++aa)
+ {
+ m_values.Add(specializeInst->getArg(aa));
+ }
+ }
+
+ List<IRInst*> m_values;
+
+ bool operator==(IRGenericSpecKey const& other) const
+ {
+ auto valueCount = m_values.Count();
+ if(valueCount != other.m_values.Count()) return false;
+ for(UInt ii = 0; ii < valueCount; ++ii)
+ {
+ if(m_values[ii] != other.m_values[ii]) return false;
+ }
+ return true;
+ }
+
+ UInt GetHashCode() const
+ {
+ auto hash = 0;
+ auto valueCount = m_values.Count();
+ for(UInt ii = 0; ii < valueCount; ++ii)
+ {
+ hash = combineHash(hash, Slang::GetHashCode(m_values[ii]));
+ }
+ return hash;
+ }
+ };
+
struct IRSharedGenericSpecContext : IRSharedSpecContext
{
// Instructions to be processed (for generic specialization context)
@@ -5276,13 +5447,15 @@ namespace Slang
}
return nullptr;
}
+
+ Dictionary<IRGenericSpecKey, IRInst*> specializations;
};
struct IRSpecContextBase
{
// A map from the mangled name of a global variable
// to the layout to use for it.
- Dictionary<Name*, VarLayout*> globalVarLayouts;
+ Dictionary<String, VarLayout*> globalVarLayouts;
IRSharedSpecContext* shared;
@@ -5405,6 +5578,26 @@ namespace Slang
clonedValue->sourceLoc = originalValue->sourceLoc;
}
+ /// Clone any decorations and children from `originalValue` onto `clonedValue`
+ void cloneDecorationsAndChildren(
+ IRSpecContextBase* context,
+ IRInst* clonedValue,
+ IRInst* originalValue)
+ {
+ IRBuilder builderStorage = *context->builder;
+ IRBuilder* builder = &builderStorage;
+ builder->setInsertInto(clonedValue);
+
+ SLANG_UNUSED(context);
+ for(auto originalItem : originalValue->getDecorationsAndChildren())
+ {
+ cloneInst(context, builder, originalItem);
+ }
+
+ // We will also clone the location here, just because this is a convenient bottleneck
+ clonedValue->sourceLoc = originalValue->sourceLoc;
+ }
+
// We use an `IRSpecContext` for the case where we are cloning
// code from one or more input modules to create a "linked" output
// module. Along the way, we will resolve profile-specific functions
@@ -5417,7 +5610,7 @@ namespace Slang
};
- IRGlobalValue* cloneGlobalValue(IRSpecContext* context, IRGlobalValue* originalVal);
+ IRInst* cloneGlobalValue(IRSpecContext* context, IRInst* originalVal);
IRInst* cloneValue(
IRSpecContextBase* context,
@@ -5429,13 +5622,18 @@ namespace Slang
IRInst* IRSpecContext::maybeCloneValue(IRInst* originalValue)
{
- if (auto globalValue = as<IRGlobalValue>(originalValue))
- {
- return cloneGlobalValue(this, globalValue);
- }
-
switch (originalValue->op)
{
+ case kIROp_StructType:
+ case kIROp_Func:
+ case kIROp_Generic:
+ case kIROp_GlobalVar:
+ case kIROp_GlobalConstant:
+ case kIROp_StructKey:
+ case kIROp_GlobalGenericParam:
+ case kIROp_WitnessTable:
+ return cloneGlobalValue(this, originalValue);
+
case kIROp_BoolLit:
{
IRConstant* c = (IRConstant*)originalValue;
@@ -5491,7 +5689,7 @@ namespace Slang
IRInst* clonedArg = cloneValue(this, originalArg);
clonedValue->getOperands()[aa].init(clonedValue, clonedArg);
}
- cloneDecorations(this, clonedValue, originalValue);
+ cloneDecorationsAndChildren(this, clonedValue, originalValue);
addHoistableInst(builder, clonedValue);
@@ -5542,22 +5740,6 @@ namespace Slang
return (IRType*)cloneValue(context, originalType);
}
- IRInst* maybeCloneValueWithMangledName(
- IRSpecContextBase* context,
- IRGlobalValue* originalValue)
- {
- for(auto ii : context->shared->module->getGlobalInsts())
- {
- auto gv = as<IRGlobalValue>(ii);
- if (!gv)
- continue;
-
- if (gv->mangledName == originalValue->mangledName)
- return gv;
- }
- return cloneValue(context, originalValue);
- }
-
void cloneGlobalValueWithCodeCommon(
IRSpecContextBase* context,
IRGlobalValueWithCode* clonedValue,
@@ -5597,13 +5779,19 @@ namespace Slang
registerClonedValue(context, clonedVar, originalValues);
+#if 0
auto mangledName = originalVar->mangledName;
clonedVar->mangledName = mangledName;
+#endif
- VarLayout* layout = nullptr;
- if (context->globalVarLayouts.TryGetValue(mangledName, layout))
+ if(auto linkage = originalVar->findDecoration<IRLinkageDecoration>())
{
- builder->addLayoutDecoration(clonedVar, layout);
+ auto mangledName = String(linkage->getMangledName());
+ VarLayout* layout = nullptr;
+ if (context->globalVarLayouts.TryGetValue(mangledName, layout))
+ {
+ builder->addLayoutDecoration(clonedVar, layout);
+ }
}
// Clone any code in the body of the variable, since this
@@ -5626,9 +5814,6 @@ namespace Slang
cloneType(context, originalVal->getFullType()));
registerClonedValue(context, clonedVal, originalValues);
- auto mangledName = originalVal->mangledName;
- clonedVal->mangledName = mangledName;
-
// Clone any code in the body of the constant, since this
// represents the initializer.
cloneGlobalValueWithCodeCommon(
@@ -5648,9 +5833,6 @@ namespace Slang
auto clonedVal = builder->emitGeneric();
registerClonedValue(context, clonedVal, originalValues);
- auto mangledName = originalVal->mangledName;
- clonedVal->mangledName = mangledName;
-
// Clone any code in the body of the generic, since this
// computes its result value.
cloneGlobalValueWithCodeCommon(
@@ -5663,17 +5845,14 @@ namespace Slang
void cloneSimpleGlobalValueImpl(
IRSpecContextBase* context,
- IRGlobalValue* originalInst,
+ IRInst* originalInst,
IROriginalValuesForClone const& originalValues,
- IRGlobalValue* clonedInst,
+ IRInst* clonedInst,
bool registerValue = true)
{
if (registerValue)
registerClonedValue(context, clonedInst, originalValues);
- auto mangledName = originalInst->mangledName;
- clonedInst->mangledName = mangledName;
-
// Set up an IR builder for inserting into the inst
IRBuilder builderStorage = *context->builder;
IRBuilder* builder = &builderStorage;
@@ -5805,7 +5984,7 @@ namespace Slang
}
- void checkIRDuplicate(IRInst* inst, IRInst* moduleInst, Name* mangledName)
+ void checkIRDuplicate(IRInst* inst, IRInst* moduleInst, UnownedStringSlice const& mangledName)
{
#ifdef _DEBUG
for (auto child : moduleInst->getDecorationsAndChildren())
@@ -5813,13 +5992,12 @@ namespace Slang
if (child == inst)
continue;
- if (child->op == kIROp_Func)
+ if(auto childLinkage = child->findDecoration<IRLinkageDecoration>())
{
- auto extName = ((IRGlobalValue*)child)->mangledName;
- if (extName == mangledName ||
- (extName && mangledName &&
- extName->text == mangledName->text))
- SLANG_UNEXPECTED("duplicate global var");
+ if(mangledName == childLinkage->getMangledName())
+ {
+ SLANG_UNEXPECTED("duplicate global instruction");
+ }
}
}
#else
@@ -5836,7 +6014,6 @@ namespace Slang
bool checkDuplicate = true)
{
// First clone all the simple properties.
- clonedFunc->mangledName = originalFunc->mangledName;
clonedFunc->setFullType(cloneType(context, originalFunc->getFullType()));
cloneGlobalValueWithCodeCommon(
@@ -5849,8 +6026,14 @@ namespace Slang
//
// TODO: This isn't really a good requirement to place on the IR...
clonedFunc->moveToEnd();
- if (checkDuplicate)
- checkIRDuplicate(clonedFunc, context->getModule()->getModuleInst(), clonedFunc->mangledName);
+
+ if( checkDuplicate )
+ {
+ if( auto linkage = clonedFunc->findDecoration<IRLinkageDecoration>() )
+ {
+ checkIRDuplicate(clonedFunc, context->getModule()->getModuleInst(), linkage->getMangledName());
+ }
+ }
}
IRFunc* specializeIRForEntryPoint(
@@ -5859,7 +6042,7 @@ namespace Slang
EntryPointLayout* entryPointLayout)
{
// Look up the IR symbol by name
- auto mangledName = context->getModule()->session->getNameObj(getMangledName(entryPointRequest->decl));
+ auto mangledName = getMangledName(entryPointRequest->decl);
RefPtr<IRSpecSymbol> sym;
if (!context->getSymbols().TryGetValue(mangledName, sym))
{
@@ -5970,7 +6153,7 @@ namespace Slang
};
TargetSpecializationLevel getTargetSpecialiationLevel(
- IRGlobalValue* inVal,
+ IRInst* inVal,
String const& targetName)
{
// HACK: Currently the front-end is placing modifiers related
@@ -6039,7 +6222,7 @@ namespace Slang
}
bool isDefinition(
- IRGlobalValue* inVal)
+ IRInst* inVal)
{
IRInst* val = inVal;
// unwrap any generic declarations to see
@@ -6057,6 +6240,10 @@ namespace Slang
val = returnVal;
}
+ // TODO: the logic here should probably
+ // be that anything with an `IRImportDecoration`
+ // is considered to be a declaration rather than definition.
+
switch (val->op)
{
case kIROp_WitnessTable:
@@ -6081,8 +6268,8 @@ namespace Slang
// to check if things are even available in the first place...
bool isBetterForTarget(
IRSpecContext* context,
- IRGlobalValue* newVal,
- IRGlobalValue* oldVal)
+ IRInst* newVal,
+ IRInst* oldVal)
{
String targetName = getTargetName(context);
@@ -6207,24 +6394,26 @@ namespace Slang
return clonedInst;
}
- IRGlobalValue* cloneGlobalValueImpl(
+ IRInst* cloneGlobalValueImpl(
IRSpecContext* context,
- IRGlobalValue* originalInst,
+ IRInst* originalInst,
IROriginalValuesForClone const& originalValues)
{
auto clonedValue = cloneInst(context, &context->shared->builderStorage, originalInst, originalValues);
clonedValue->moveToEnd();
- return cast<IRGlobalValue>(clonedValue);
+ return clonedValue;
}
- // Clone a global value, which has the given `mangledName`.
- // The `originalVal` is a known global IR value with that name, if one is available.
- // (It is okay for this parameter to be null).
- IRGlobalValue* cloneGlobalValueWithMangledName(
- IRSpecContext* context,
- Name* mangledName,
- IRGlobalValue* originalVal)
+ /// Clone a global value, which has the given `originalLinkage`.
+ ///
+ /// The `originalVal` is a known global IR value with that linkage, if one is available.
+ /// (It is okay for this parameter to be null).
+ ///
+ IRInst* cloneGlobalValueWithLinkage(
+ IRSpecContext* context,
+ IRInst* originalVal,
+ IRLinkageDecoration* originalLinkage)
{
// If the global value being cloned is already in target module, don't clone
// Why checking this?
@@ -6241,11 +6430,11 @@ namespace Slang
{
if (IRInst* clonedVal = findClonedValue(context, originalVal))
{
- return cast<IRGlobalValue>(clonedVal);
+ return clonedVal;
}
}
- if(getText(mangledName).Length() == 0)
+ if(!originalLinkage)
{
// If there is no mangled name, then we assume this is a local symbol,
// and it can't possibly have multiple declarations.
@@ -6257,6 +6446,7 @@ namespace Slang
// with the same mangled name as `originalVal` and try
// to pick the "best" one for our target.
+ auto mangledName = String(originalLinkage->getMangledName());
RefPtr<IRSpecSymbol> sym;
if( !context->getSymbols().TryGetValue(mangledName, sym) )
{
@@ -6274,10 +6464,10 @@ namespace Slang
// more specialized for the chosen target. Otherwise, we simply favor
// definitions over declarations.
//
- IRGlobalValue* bestVal = sym->irGlobalValue;
+ IRInst* bestVal = sym->irGlobalValue;
for( auto ss = sym->nextWithSameName; ss; ss = ss->nextWithSameName )
{
- IRGlobalValue* newVal = ss->irGlobalValue;
+ IRInst* newVal = ss->irGlobalValue;
if(isBetterForTarget(context, newVal, bestVal))
bestVal = newVal;
}
@@ -6289,30 +6479,25 @@ namespace Slang
{
if (IRInst* clonedVal = findClonedValue(context, bestVal))
{
- return cast<IRGlobalValue>(clonedVal);
+ return clonedVal;
}
}
return cloneGlobalValueImpl(context, bestVal, IROriginalValuesForClone(sym));
}
- IRGlobalValue* cloneGlobalValueWithMangledName(IRSpecContext* context, Name* mangledName)
- {
- return cloneGlobalValueWithMangledName(context, mangledName, nullptr);
- }
-
// Clone a global value, where `originalVal` is one declaration/definition, but we might
// have to consider others, in order to find the "best" version of the symbol.
- IRGlobalValue* cloneGlobalValue(IRSpecContext* context, IRGlobalValue* originalVal)
+ IRInst* cloneGlobalValue(IRSpecContext* context, IRInst* originalVal)
{
// We are being asked to clone a particular global value, but in
// the IR that comes out of the front-end there could still
// be multiple, target-specific, declarations of any given
// global value, all of which share the same mangled name.
- return cloneGlobalValueWithMangledName(
+ return cloneGlobalValueWithLinkage(
context,
- originalVal->mangledName,
- originalVal);
+ originalVal,
+ originalVal->findDecoration<IRLinkageDecoration>());
}
StructTypeLayout* getGlobalStructLayout(
@@ -6320,16 +6505,18 @@ namespace Slang
void insertGlobalValueSymbol(
IRSharedSpecContext* sharedContext,
- IRGlobalValue* gv)
+ IRInst* gv)
{
- auto mangledName = gv->mangledName;
+ auto linkage = gv->findDecoration<IRLinkageDecoration>();
// Don't try to register a symbol for global values
- // with no mangled name, since these represent symbols
- // that shouldn't get "linkage"
- if (!getText(mangledName).Length())
+ // that don't have linkage.
+ //
+ if (!linkage)
return;
+ auto mangledName = String(linkage->getMangledName());
+
RefPtr<IRSpecSymbol> sym = new IRSpecSymbol();
sym->irGlobalValue = gv;
@@ -6354,10 +6541,7 @@ namespace Slang
for(auto ii : originalModule->getGlobalInsts())
{
- auto gv = as<IRGlobalValue>(ii);
- if (!gv)
- continue;
- insertGlobalValueSymbol(sharedContext, gv);
+ insertGlobalValueSymbol(sharedContext, ii);
}
}
@@ -6489,7 +6673,7 @@ namespace Slang
auto globalStructLayout = getGlobalStructLayout(newProgramLayout);
for (auto globalVarLayout : globalStructLayout->fields)
{
- auto mangledName = compileRequest->mSession->getNameObj(getMangledName(globalVarLayout->varDecl));
+ auto mangledName = getMangledName(globalVarLayout->varDecl);
context->globalVarLayouts.AddIfNotExists(mangledName, globalVarLayout);
}
@@ -6512,32 +6696,6 @@ namespace Slang
return state->irModule;
}
- IRGlobalValue* getSpecializedGlobalValueForDeclRef(
- IRSpecializationState* state,
- DeclRef<Decl> const& declRef)
- {
- // We will start be ensuring that we have code for
- // the declaration itself.
- auto decl = declRef.getDecl();
- auto mangledDeclName = getMangledName(decl);
-
- IRGlobalValue* irDeclVal = cloneGlobalValueWithMangledName(
- state->getContext(),
- state->getContext()->getModule()->session->getNameObj(mangledDeclName));
- if(!irDeclVal)
- return nullptr;
-
- // Now we need to deal with specializing the given
- // IR value based on the substitutions applied to
- // our declaration reference.
-
- if(!declRef.substitutions)
- return irDeclVal;
-
- SLANG_UNEXPECTED("unhandled");
- UNREACHABLE_RETURN(nullptr);
- }
-
void specializeIRForEntryPoint(
IRSpecializationState* state,
EntryPointRequest* entryPointRequest,
@@ -6662,31 +6820,14 @@ namespace Slang
IRSpecialize* specializeInst)
{
// First, we want to see if an existing specialization
- // has already been made. To do that we will need to
- // compute the mangled name of the specialized value,
- // so that we can look for existing declarations.
- String specMangledName = mangleSpecializedFuncName(getText(genericVal->mangledName), specializeInst);
- auto specMangledNameObj = sharedContext->module->session->getNameObj(specMangledName);
-
- // Now look up an existing symbol with a matching name
- RefPtr<IRSpecSymbol> symb;
- if (sharedContext->symbols.TryGetValue(specMangledNameObj, symb))
- {
- return symb->irGlobalValue;
- }
-
- // TODO: This is a terrible linear search, and we should
- // avoid it by building a dictionary ahead of time,
- // as is being done for the `IRSpecContext` used above.
- // We can probalby use the same basic context, actually.
- for(auto ii : sharedContext->module->getGlobalInsts())
+ // has already been made. To do that we will construct a key
+ // for lookup in the generic specialization context.
+ //
+ IRGenericSpecKey specializationKey(specializeInst);
{
- auto gv = as<IRGlobalValue>(ii);
- if (!gv)
- continue;
-
- if (gv->mangledName == specMangledNameObj)
- return gv;
+ IRInst* specializedValue = nullptr;
+ if(sharedContext->specializations.TryGetValue(specializationKey, specializedValue))
+ return specializedValue;
}
// If we get to this point, then we need to construct a
@@ -6752,12 +6893,8 @@ namespace Slang
if (auto returnValInst = as<IRReturnVal>(ii))
{
auto clonedResult = cloneValue(&context, returnValInst->getVal());
- if (auto clonedGlobalValue = as<IRGlobalValue>(clonedResult))
- {
- clonedGlobalValue->mangledName = specMangledNameObj;
- // TODO: create a symbol for it and add it to the map.
- }
+ sharedContext->specializations.Add(specializationKey, clonedResult);
return clonedResult;
}
@@ -6823,20 +6960,10 @@ namespace Slang
// We've found the leaf value that will be produced after
// all of the specialization is done. Now we want to know
// if that is a value suitable for actually specializing
-
- if (auto globalValue = as<IRGlobalValue>(val))
- {
- if (isDefinition(globalValue))
- return true;
- return false;
- }
- else
- {
- // There might be other cases with a declaration-vs-definition
- // thing that we need to handle.
-
+ //
+ if (isDefinition(val))
return true;
- }
+ return false;
}
}
diff --git a/source/slang/ir.h b/source/slang/ir.h
index 6fb0ff728..d68b3b8f3 100644
--- a/source/slang/ir.h
+++ b/source/slang/ir.h
@@ -257,10 +257,7 @@ struct IRInst
// Look up a decoration in the list of decorations
IRDecoration* findDecorationImpl(IROp op);
template<typename T>
- T* findDecoration()
- {
- return (T*) findDecorationImpl(IROp(T::kOp));
- }
+ T* findDecoration();
// The first use of this value (start of a linked list)
IRUse* firstUse = nullptr;
@@ -424,8 +421,18 @@ T* cast(IRInst* inst, T* /* */ = nullptr)
return (T*)inst;
}
-// Now that `IRInst` is defined we can back-fill the `IRInstList<T>` members
-// that need to access it.
+// Now that `IRInst` is defined we can back-fill the definitions that need to access it.
+
+template<typename T>
+T* IRInst::findDecoration()
+{
+ for( auto decoration : getDecorations() )
+ {
+ if(auto match = as<T>(decoration))
+ return match;
+ }
+ return nullptr;
+}
template<typename T>
typename IRInstList<T>::Iterator IRInstList<T>::end()
@@ -913,36 +920,8 @@ struct IRFuncType : IRType
IR_LEAF_ISA(FuncType)
};
-// A "global value" is an instruction that might have
-// linkage, so that it can be declared in one module
-// and then resolved to a definition in another module.
-struct IRGlobalValue : IRInst
-{
- // The mangled name, for a symbol that should have linkage,
- // or which might have multiple declarations.
- Name* mangledName = nullptr;
-
-#if 0
- // TODO: these all belong on `IRInst`
- void insertBefore(IRGlobalValue* other);
- void insertBefore(IRGlobalValue* other, IRModule* module);
- void insertAtStart(IRModule* module);
-
- void insertAfter(IRGlobalValue* other);
- void insertAfter(IRGlobalValue* other, IRModule* module);
- void insertAtEnd(IRModule* module);
-
- void removeFromParent();
-
- void moveToEnd();
-#endif
-
- IR_PARENT_ISA(GlobalValue)
-};
-
bool isDefinition(
- IRGlobalValue* inVal);
-
+ IRInst* inVal);
// A structure type is represented as a parent instruction,
// where the child instructions represent the fields of the
@@ -953,7 +932,7 @@ bool isDefinition(
// (that is, they have mangled names that can be used
// for linkage).
//
-struct IRStructKey : IRGlobalValue
+struct IRStructKey : IRInst
{
IR_LEAF_ISA(StructKey)
};
@@ -978,7 +957,7 @@ struct IRStructField : IRInst
// *not* contain the keys, because code needs to be able to
// reference the keys from scopes outside of the struct.
//
-struct IRStructType : IRGlobalValue
+struct IRStructType : IRInst
{
IRInstList<IRStructField> getFields() { return IRInstList<IRStructField>(getChildren()); }
@@ -988,7 +967,7 @@ struct IRStructType : IRGlobalValue
/// @brief A global value that potentially holds executable code.
///
-struct IRGlobalValueWithCode : IRGlobalValue
+struct IRGlobalValueWithCode : IRInst
{
// The children of a value with code will be the basic
// blocks of its definition.
@@ -1102,13 +1081,36 @@ struct IRModule : RefObject
ObjectScopeManager m_objectScopeManager;
};
-void printSlangIRAssembly(StringBuilder& builder, IRModule* module);
-String getSlangIRAssembly(IRModule* module);
+ /// How much detail to include in dumped IR.
+ ///
+ /// Used with the `dumpIR` functions to determine
+ /// whether a completely faithful, but verbose, IR
+ /// dump is produced, or something simplified for ease
+ /// or reading.
+ ///
+enum class IRDumpMode
+{
+ /// Produce a simplified IR dump.
+ ///
+ /// Simplified IR dumping will skip certain instructions
+ /// and print them at their use sites instead, so that
+ /// the overall dump is shorter and easier to read.
+ Simplified,
+
+ /// Produce a detailed/accurate IR dump.
+ ///
+ /// A detailed IR dump will make sure to emit exactly
+ /// the instructions that were present with no attempt
+ /// to selectively skip them or give special formatting.
+ ///
+ Detailed,
+};
-void dumpIR(IRModule* module, ISlangWriter* writer);
-void dumpIR(IRGlobalValue* globalVal, ISlangWriter* writer);
+void printSlangIRAssembly(StringBuilder& builder, IRModule* module, IRDumpMode mode = IRDumpMode::Simplified);
+String getSlangIRAssembly(IRModule* module, IRDumpMode mode = IRDumpMode::Simplified);
-String dumpIRFunc(IRFunc* func);
+void dumpIR(IRModule* module, ISlangWriter* writer, IRDumpMode mode = IRDumpMode::Simplified);
+void dumpIR(IRInst* globalVal, ISlangWriter* writer, IRDumpMode mode = IRDumpMode::Simplified);
IRInst* createEmptyInst(
IRModule* module,
diff --git a/source/slang/legalize-types.cpp b/source/slang/legalize-types.cpp
index 15d7a4621..858dbd95c 100644
--- a/source/slang/legalize-types.cpp
+++ b/source/slang/legalize-types.cpp
@@ -351,7 +351,6 @@ struct TupleTypeBuilder
IRBuilder* builder = context->getBuilder();
IRStructType* ordinaryStructType = builder->createStructType();
ordinaryStructType->sourceLoc = originalStructType->sourceLoc;
- ordinaryStructType->mangledName = originalStructType->mangledName;
if(auto nameHintDecoration = originalStructType->findDecoration<IRNameHintDecoration>())
{
diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp
index 2804854b7..bf5aeff24 100644
--- a/source/slang/lower-to-ir.cpp
+++ b/source/slang/lower-to-ir.cpp
@@ -384,6 +384,48 @@ void setValue(IRGenContext* context, Decl* decl, LoweredValInfo value)
context->env->mapDeclToValue[decl] = value;
}
+ModuleDecl* findModuleDecl(Decl* decl)
+{
+ for (auto dd = decl; dd; dd = dd->ParentDecl)
+ {
+ if (auto moduleDecl = dynamic_cast<ModuleDecl*>(dd))
+ return moduleDecl;
+ }
+ return nullptr;
+}
+
+bool isFromStdLib(Decl* decl)
+{
+ for (auto dd = decl; dd; dd = dd->ParentDecl)
+ {
+ if (dd->HasModifier<FromStdLibModifier>())
+ return true;
+ }
+ return false;
+}
+
+bool isImportedDecl(IRGenContext* context, Decl* decl)
+{
+ ModuleDecl* moduleDecl = findModuleDecl(decl);
+ if (!moduleDecl)
+ return false;
+
+ // HACK: don't treat standard library code as
+ // being imported for right now, just because
+ // we don't load its IR in the same way as
+ // for other imports.
+ //
+ // TODO: Fix this the right way, by having standard
+ // library declarations have IR modules that we link
+ // in via the normal means.
+ if (isFromStdLib(decl))
+ return false;
+
+ if (moduleDecl != context->shared->mainModuleDecl)
+ return true;
+
+ return false;
+}
/// Should the given `decl` nested in `parentDecl` be treated as a static rather than instance declaration?
bool isEffectivelyStatic(
@@ -954,6 +996,51 @@ IRType* getIntType(
return context->irBuilder->getBasicType(BaseType::Int);
}
+static IRGeneric* getOuterGeneric(IRInst* gv)
+{
+ auto parentBlock = as<IRBlock>(gv->getParent());
+ if (!parentBlock) return nullptr;
+
+ auto parentGeneric = as<IRGeneric>(parentBlock->getParent());
+ return parentGeneric;
+}
+
+static void addLinkageDecoration(
+ IRGenContext* context,
+ IRInst* inInst,
+ Decl* decl,
+ UnownedStringSlice const& mangledName)
+{
+ // If the instruction is nested inside one or more generics,
+ // then the mangled name should really apply to the outer-most
+ // generic, and not the declaration nested inside.
+
+ auto builder = context->irBuilder;
+
+ IRInst* inst = inInst;
+ while (auto outerGeneric = getOuterGeneric(inst))
+ {
+ inst = outerGeneric;
+ }
+
+ if(isImportedDecl(context, decl))
+ {
+ builder->addImportDecoration(inst, mangledName);
+ }
+ else
+ {
+ builder->addExportDecoration(inst, mangledName);
+ }
+}
+
+static void addLinkageDecoration(
+ IRGenContext* context,
+ IRInst* inst,
+ Decl* decl)
+{
+ addLinkageDecoration(context, inst, decl, getMangledName(decl).getUnownedSlice());
+}
+
IRStructKey* getInterfaceRequirementKey(
IRGenContext* context,
Decl* requirementDecl)
@@ -973,8 +1060,8 @@ IRStructKey* getInterfaceRequirementKey(
// this requirement in the IR, and to allow lookup
// into the declaration.
requirementKey = builder->createStructKey();
- requirementKey->mangledName = context->getSession()->getNameObj(
- getMangledName(requirementDecl));
+
+ addLinkageDecoration(context, requirementKey, requirementDecl);
context->shared->interfaceRequirementKeys.Add(requirementDecl, requirementKey);
@@ -3461,7 +3548,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
// alias is somehow generic.
if(outerGeneric)
{
- setMangledName(outerGeneric, getMangledName(decl));
+ addLinkageDecoration(context, outerGeneric, decl);
}
auto type = lowerType(subContext, decl->type.type);
@@ -3499,7 +3586,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
// and so it should lower as a parameter of its own.
auto inst = getBuilder()->emitGlobalGenericParam();
- setMangledName(inst, getMangledName(decl));
+ addLinkageDecoration(context, inst, decl);
return LoweredValInfo::simple(inst);
}
@@ -3515,7 +3602,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
LoweredValInfo visitGlobalGenericParamDecl(GlobalGenericParamDecl* decl)
{
auto inst = getBuilder()->emitGlobalGenericParam();
- setMangledName(inst, getMangledName(decl));
+ addLinkageDecoration(context, inst, decl);
return LoweredValInfo::simple(inst);
}
@@ -3643,8 +3730,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
// on the type that is conforming, and the type that it conforms to.
//
// TODO: This approach doesn't really make sense for generic `extension` conformances.
- auto mangledName = context->getSession()->getNameObj(
- getMangledNameForConformanceWitness(subType, superType));
+ auto mangledName = getMangledNameForConformanceWitness(subType, superType);
// A witness table may need to be generic, if the outer
// declaration (either a type declaration or an `extension`)
@@ -3666,7 +3752,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
// Create the IR-level witness table
auto irWitnessTable = subBuilder->createWitnessTable();
- setMangledName(irWitnessTable, mangledName);
+ addLinkageDecoration(context, irWitnessTable, inheritanceDecl, mangledName.getUnownedSlice());
// Register the value now, rather than later, to avoid any possible infinite recursion.
setGlobalValue(context, inheritanceDecl, LoweredValInfo::simple(irWitnessTable));
@@ -3762,7 +3848,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
irGlobal = builder->createGlobalVar(varType);
globalVal = LoweredValInfo::ptr(irGlobal);
}
- irGlobal->mangledName = context->getSession()->getNameObj(getMangledName(decl));
+ addLinkageDecoration(context, irGlobal, decl);
addNameHint(context, irGlobal, decl);
maybeSetRate(context, irGlobal, decl);
@@ -4137,35 +4223,6 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
return LoweredValInfo();
}
- IRGeneric* getOuterGeneric(IRGlobalValue* gv)
- {
- auto parentBlock = as<IRBlock>(gv->getParent());
- if (!parentBlock) return nullptr;
-
- auto parentGeneric = as<IRGeneric>(parentBlock->getParent());
- return parentGeneric;
- }
-
- void setMangledName(IRGlobalValue* inst, Name* name)
- {
- // If the instruction is nested inside one or more generics,
- // then the mangled name should really apply to the outer-most
- // generic, and not the declaration nested inside.
-
- IRGlobalValue* gv = inst;
- while (auto outerGeneric = getOuterGeneric(gv))
- {
- gv = outerGeneric;
- }
-
- gv->mangledName = name;
- }
-
- void setMangledName(IRGlobalValue* inst, String const& name)
- {
- setMangledName(inst, context->getSession()->getNameObj(name));
- }
-
LoweredValInfo visitEnumCaseDecl(EnumCaseDecl* decl)
{
// A case within an `enum` decl will lower to a value
@@ -4241,7 +4298,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
IRStructType* irStruct = subBuilder->createStructType();
addNameHint(context, irStruct, decl);
- setMangledName(irStruct, getMangledName(decl));
+ addLinkageDecoration(context, irStruct, decl);
subBuilder->setInsertInto(irStruct);
@@ -4306,8 +4363,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
addVarDecorations(context, irFieldKey, fieldDecl);
- irFieldKey->mangledName = context->getSession()->getNameObj(
- getMangledName(fieldDecl));
+ addLinkageDecoration(context, irFieldKey, fieldDecl);
if (auto semanticModifier = fieldDecl->FindModifier<HLSLSimpleSemantic>())
{
@@ -4582,47 +4638,9 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
}
}
- ModuleDecl* findModuleDecl(Decl* decl)
- {
- for (auto dd = decl; dd; dd = dd->ParentDecl)
- {
- if (auto moduleDecl = dynamic_cast<ModuleDecl*>(dd))
- return moduleDecl;
- }
- return nullptr;
- }
-
- bool isFromStdLib(Decl* decl)
- {
- for (auto dd = decl; dd; dd = dd->ParentDecl)
- {
- if (dd->HasModifier<FromStdLibModifier>())
- return true;
- }
- return false;
- }
-
bool isImportedDecl(Decl* decl)
{
- ModuleDecl* moduleDecl = findModuleDecl(decl);
- if (!moduleDecl)
- return false;
-
- // HACK: don't treat standard library code as
- // being imported for right now, just because
- // we don't load its IR in the same way as
- // for other imports.
- //
- // TODO: Fix this the right way, by having standard
- // library declarations have IR modules that we link
- // in via the normal means.
- if (isFromStdLib(decl))
- return false;
-
- if (moduleDecl != this->context->shared->mainModuleDecl)
- return true;
-
- return false;
+ return Slang::isImportedDecl(context, decl);
}
bool isConstExprVar(Decl* decl)
@@ -4659,21 +4677,13 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
auto subBuilder = subContext->irBuilder;
// Of course, a generic might itself be nested inside of other generics...
- auto nextOuterGeneric = emitOuterGenerics(subContext, genericDecl, leafDecl);
+ emitOuterGenerics(subContext, genericDecl, leafDecl);
// We need to create an IR generic
auto irGeneric = subBuilder->emitGeneric();
subBuilder->setInsertInto(irGeneric);
- if (!nextOuterGeneric)
- {
- // If this is the outer-most generic, then it will be the
- // global symbol that gets the mangled name from the inner
- // declaration actually being lowered.
- irGeneric->mangledName = context->getSession()->getNameObj(getMangledName(leafDecl));
- }
-
auto irBlock = subBuilder->emitBlock();
subBuilder->setInsertInto(irBlock);
@@ -4848,8 +4858,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
IRFunc* irFunc = subBuilder->createFunc();
addNameHint(context, irFunc, decl);
-
- setMangledName(irFunc, getMangledName(decl));
+ addLinkageDecoration(context, irFunc, decl);
List<IRType*> paramTypes;
diff --git a/source/slang/mangle.cpp b/source/slang/mangle.cpp
index c2645929f..d78f3321a 100644
--- a/source/slang/mangle.cpp
+++ b/source/slang/mangle.cpp
@@ -1,7 +1,6 @@
#include "mangle.h"
#include "name.h"
-#include "ir-insts.h"
#include "syntax.h"
#include "../core/slang-cpu-defines.h"
@@ -200,82 +199,6 @@ namespace Slang
}
}
- void emitIRVal(
- ManglingContext* context,
- IRInst* inst);
-
- void emitIRSimpleIntVal(
- ManglingContext* context,
- IRInst* inst)
- {
- if (auto intLit = as<IRIntLit>(inst))
- {
- auto cVal = intLit->getValue();
- if(cVal >= 0 && cVal <= 9 )
- {
- emit(context, (UInt)cVal);
- return;
- }
- }
-
- // Fallback:
- emitIRVal(context, inst);
- }
-
- void emitIRVal(
- ManglingContext* context,
- IRInst* inst)
- {
- if(auto basicType = as<IRBasicType>(inst) )
- {
- emitBaseType(context, basicType->getBaseType());
- return;
- }
-
- if (auto globalVal = as<IRGlobalValue>(inst))
- {
- // If it is a global value, it has its own mangled name.
- emit(context, getText(globalVal->mangledName));
- }
- // TODO: need to handle various type cases here
- else if (auto intLit = as<IRIntLit>(inst))
- {
- // TODO: need to figure out what prefix/suffix is needed
- // to allow demangling later.
- emitRaw(context, "k");
- emit(context, (UInt) intLit->getValue());
- }
- // Note: the cases here handling types really should match
- // the cases above that handle AST-level `Type`s. This
- // seems to be a weakness in the way we mangle names, because
- // we may mangle in both IR-level and AST-level types.
- else if (auto vecType = as<IRVectorType>(inst))
- {
- emitRaw(context, "v");
- emitIRSimpleIntVal(context, vecType->getElementCount());
- emitIRVal(context, vecType->getElementType());
-
- }
- else if( auto matType = as<IRMatrixType>(inst) )
- {
- emitRaw(context, "m");
- emitIRSimpleIntVal(context, matType->getRowCount());
- emitRaw(context, "x");
- emitIRSimpleIntVal(context, matType->getColumnCount());
- emitIRVal(context, matType->getElementType());
- }
- else if (auto arrType = as<IRArrayType>(inst))
- {
- emitRaw(context, "a");
- emitIRSimpleIntVal(context, arrType->getElementCount());
- emitIRVal(context, arrType->getElementCount());
- }
- else
- {
- SLANG_UNEXPECTED("unimplemented case in mangling");
- }
- }
-
void emitQualifiedName(
ManglingContext* context,
DeclRef<Decl> declRef)
@@ -487,21 +410,6 @@ namespace Slang
DeclRef<Decl>(declRef.decl, declRef.substitutions));
}
- String mangleSpecializedFuncName(String baseName, IRSpecialize* specializeInst)
- {
- ManglingContext context;
- emitRaw(&context, baseName.Buffer());
- emitRaw(&context, "_G");
-
- UInt argCount = specializeInst->getArgCount();
- for (UInt aa = 0; aa < argCount; ++aa)
- {
- emitIRVal(&context, specializeInst->getArg(aa));
- }
-
- return context.sb.ProduceString();
- }
-
String getMangledName(Decl* decl)
{
return getMangledName(makeDeclRef(decl));
diff --git a/source/slang/mangle.h b/source/slang/mangle.h
index b6f7587ad..7fc8d0d93 100644
--- a/source/slang/mangle.h
+++ b/source/slang/mangle.h
@@ -14,8 +14,6 @@ namespace Slang
String getMangledName(DeclRef<Decl> const & declRef);
String getMangledName(DeclRefBase const & declRef);
- String mangleSpecializedFuncName(String baseName, IRSpecialize* specializeInst);
-
String getMangledNameForConformanceWitness(
Type* sub,
Type* sup);
diff --git a/source/slang/slang.natvis b/source/slang/slang.natvis
index 0045b8f84..6565f5a7a 100644
--- a/source/slang/slang.natvis
+++ b/source/slang/slang.natvis
@@ -93,10 +93,10 @@
</Expand>
</Synthetic>
<Item Name="[parent]">parent</Item>
- <Synthetic Name="[children]">
+ <Synthetic Name="[decorations/children]">
<Expand>
<LinkedListItems>
- <HeadPointer>children.first</HeadPointer>
+ <HeadPointer>m_decorationsAndChildren.first</HeadPointer>
<NextPointer>next</NextPointer>
<ValueNode>this</ValueNode>
</LinkedListItems>
@@ -113,33 +113,6 @@
</Synthetic>
</Expand>
</Type>
- <Type Name="Slang::IRGlobalValue">
- <DisplayString>{{{op} "{mangledName}"}}</DisplayString>
- <Expand>
- <Item Name="[op]">op</Item>
- <Item Name="[type]">type</Item>
- <Synthetic Name="[children]">
- <Expand>
- <LinkedListItems>
- <HeadPointer>children.first</HeadPointer>
- <NextPointer>next</NextPointer>
- <ValueNode>this</ValueNode>
- </LinkedListItems>
- </Expand>
- </Synthetic>
- <Item Name="[parent]">parent</Item>
- <Synthetic Name="[uses]">
- <Expand>
- <LinkedListItems>
- <HeadPointer>firstUse</HeadPointer>
- <NextPointer>nextUse</NextPointer>
- <ValueNode>user</ValueNode>
- </LinkedListItems>
- </Expand>
- </Synthetic>
- </Expand>
- </Type>
-
<Type Name="Slang::IRDeclRef">
<DisplayString>{{IRDeclRef {declRef}}}</DisplayString>
<Expand>