summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2018-05-03 16:34:49 -0700
committerGitHub <noreply@github.com>2018-05-03 16:34:49 -0700
commit00afea1e59e8929324df882009618534d3065138 (patch)
tree384eb8724b51e345d3dbd2d4026cab8fe6bd58d4 /source
parentf8472940229e8582ec9f941069fc9576bd09b94c (diff)
Pass through original names for most declarations (#547)
The basic idea here is that when lowering to the IR, the front-end will attach a "name hint" to the IR instruction(s) that represent a given declaration, and then the passes that work on the IR will try to preserve and propagate those names, and then finally the emit logic will use them in place of mangled or unique names when available. This change does *not* try to deal with the issues that arise when we try to use those variable names in the output without any modification (e.g., handling cases where they might clash with keywords or builtins in the target language). Instead, it tries to establish baseline behavior for propagating through names, so that a later change can concentrate on the issue of using those names exactly when it is legal to do so. In order to avoid issues around the name "hints" causing problems we take two main steps: 1. We "scrub" each name to reduce it down to the allowed set of identifier characters in C-like languages, and then ensure that it doesn't do things that would be illegal in some downstream languages (e.g., consecutive underscores are not allowed in GLSL) or could clash with Slang's mangled names. This process isn't guaranteed to give distinct results for distinct inputs (it isn't a mangling scheme, after all). 2. We generate a unique ID for each occurence of a given name and always use that as a suffix. This means that even if a name happens to overlap with a keyword (if you somehow have a variable named `do`), we will still add a suffix that makes it not a problem (we'd output `do_0` which is fine). The logic for generating these names is mostly straightforward. For simple variables, we use their given name directly, while for other declarations we try to form a name that includes their parent declaration (e.g. `SomeType.someMethod`). Various IR passes need to propagate or preserve this information. The most interesting is type legalization, when we take a variable with an aggregate type and split some of the fields out into their own variables. In that case we generate "dotted" names like `someVar.someTexture` and rely on the emit logic to turn that into `someVar_someTexture`. During SSA generation, if we are promoting a variable to SSA temporaries, we will try to propagate the name of the variable over to the temporaries (unless they already have a name from some other place). The same applies to block parameters ("phi nodes"). Many of the test changes need their expected output to be updated for this change. Luckily in most cases the output has gotten easier to understand.
Diffstat (limited to 'source')
-rw-r--r--source/slang/emit.cpp198
-rw-r--r--source/slang/ir-insts.h11
-rw-r--r--source/slang/ir-legalize-types.cpp67
-rw-r--r--source/slang/ir-ssa.cpp21
-rw-r--r--source/slang/ir.cpp8
-rw-r--r--source/slang/ir.h1
-rw-r--r--source/slang/legalize-types.cpp5
-rw-r--r--source/slang/lower-to-ir.cpp111
8 files changed, 411 insertions, 11 deletions
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index 9f9a089c8..4ed7dd5a7 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -136,6 +136,14 @@ struct SharedEmitContext
// How far are we indented?
Int indentLevel = 0;
+
+ // Map a string name to the number of times we have seen this
+ // name used so far during code emission.
+ Dictionary<String, UInt> uniqueNameCounters;
+
+ // Map an IR instruction to the name that we've decided
+ // to use for it when emitting code.
+ Dictionary<IRInst*, String> mapInstToName;
};
struct EmitContext
@@ -1895,8 +1903,128 @@ struct EmitVisitor
return id;
}
- String getIRName(
- IRInst* inst)
+ /// "Scrub" a name so that it complies with restrictions of the target language.
+ String scrubName(
+ String const& name)
+ {
+ // We will use a plain `U` as a dummy character to insert
+ // whenever we need to insert things to make a string into
+ // valid name.
+ //
+ char const* dummyChar = "U";
+
+ // Special case a name that is the empty string, just in case.
+ if(name.Length() == 0)
+ return dummyChar;
+
+ // Otherwise, we are going to walk over the name byte by byte
+ // and write some legal characters to the output as we go.
+ StringBuilder sb;
+
+ if(getTarget(context) == CodeGenTarget::GLSL)
+ {
+ // GLSL reserverse all names that start with `gl_`,
+ // so if we are in danger of collision, then make
+ // our name start with a dummy character instead.
+ if(name.StartsWith("gl_"))
+ {
+ sb.append(dummyChar);
+ }
+ }
+
+ // We will also detect user-defined names that
+ // might overlap with our convention for mangled names,
+ // to avoid an possible collision.
+ if(name.StartsWith("_S"))
+ {
+ sb.Append(dummyChar);
+ }
+
+ // TODO: This is where we might want to consult
+ // a dictionary of reserved words for the chosen target
+ //
+ // if(isReservedWord(name)) { sb.Append(dummyChar); }
+ //
+
+ // We need to track the previous byte in
+ // order to detect consecutive underscores for GLSL.
+ int prevChar = -1;
+
+ for(auto c : name)
+ {
+ // We will treat a dot character just like an underscore
+ // for the purposes of producing a scrubbed name, so
+ // that we translate `SomeType.someMethod` into
+ // `SomeType_someMethod`.
+ //
+ // By handling this case at the top of this loop, we
+ // ensure that a `.`-turned-`_` is handled just like
+ // a `_` in the original name, and will be properly
+ // scrubbed for GLSL output.
+ //
+ 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, since the result wouldn't
+ // be a valid identifier in many target languages.
+ if(prevChar == -1)
+ {
+ sb.append(dummyChar);
+ }
+ }
+ else if(c == '_')
+ {
+ // We will collapse any consecutive sequence of `_`
+ // characters into a single one (this means that
+ // some names that were unique in the original
+ // code might not resolve to unique names after
+ // scrubbing, but that was true in general).
+
+ if(prevChar == '_')
+ {
+ // Skip this underscore, so we don't output
+ // more than one in a row.
+ continue;
+ }
+ }
+ 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;
+ }
+
+ return sb.ProduceString();
+ }
+
+ String generateIRName(
+ IRInst* inst)
{
// If the instruction names something
// that should be emitted as a target intrinsic,
@@ -1906,6 +2034,58 @@ struct EmitVisitor
return intrinsicDecoration->definition;
}
+ // If we have a name hint on the instruction, then we will try to use that
+ // to provide the actual name in the output code.
+ //
+ // We need to be careful that the name follows the rules of the target language,
+ // so there is a "scrubbing" step that needs to be applied here.
+ //
+ // We also need to make sure that the name won't collide with other declarations
+ // that might have the same name hint applied, so we will still unique
+ // them by appending the numeric ID of the instruction.
+ //
+ // TODO: Find cases where we can drop the suffix safely.
+ //
+ // TODO: When we start having to handle symbols with external linkage for
+ // things like DXIL libraries, we will need to *not* use the friendly
+ // names for stuff that should be link-able.
+ //
+ if(auto nameHintDecoration = inst->findDecoration<IRNameHintDecoration>())
+ {
+ // The name we output will basically be:
+ //
+ // <nameHint>_<uniqueID>
+ //
+ // Except that we will "scrub" the name hint first,
+ // and we will omit the underscore if the (scrubbed)
+ // name hint already ends with one.
+ //
+
+ String nameHint = nameHintDecoration->name->text;
+ nameHint = scrubName(nameHint);
+
+ StringBuilder sb;
+ sb.append(nameHint);
+
+ // Avoid introducing a double underscore
+ if(!nameHint.EndsWith("_"))
+ {
+ sb.append("_");
+ }
+
+ String key = sb.ProduceString();
+ UInt count = 0;
+ context->shared->uniqueNameCounters.TryGetValue(key, count);
+
+ context->shared->uniqueNameCounters[key] = count+1;
+
+ sb.append(count);
+ return sb.ProduceString();
+ }
+
+
+
+
// If the instruction has a mangled name, then emit using that.
if (auto globalValue = as<IRGlobalValue>(inst))
{
@@ -1925,9 +2105,23 @@ struct EmitVisitor
StringBuilder sb;
sb << "_S";
sb << getID(inst);
+
+
return sb.ProduceString();
}
+ String getIRName(
+ IRInst* inst)
+ {
+ String name;
+ if(!context->shared->mapInstToName.TryGetValue(inst, name))
+ {
+ name = generateIRName(inst);
+ context->shared->mapInstToName.Add(inst, name);
+ }
+ return name;
+ }
+
struct IRDeclaratorInfo
{
enum class Flavor
diff --git a/source/slang/ir-insts.h b/source/slang/ir-insts.h
index 22685f316..804c393c2 100644
--- a/source/slang/ir-insts.h
+++ b/source/slang/ir-insts.h
@@ -121,6 +121,17 @@ struct IRInterpolationModeDecoration : IRDecoration
IRInterpolationMode mode;
};
+/// A decoration that provides a desired name to be used
+/// in conjunction with the given instruction. Back-end
+/// code generation may use this to help derive symbol
+/// names, emit debug information, etc.
+struct IRNameHintDecoration : IRDecoration
+{
+ enum { kDecorationOp = kIRDecorationOp_NameHint };
+
+ Name* name;
+};
+
//
// An IR node to represent a reference to an AST-level
diff --git a/source/slang/ir-legalize-types.cpp b/source/slang/ir-legalize-types.cpp
index 25bd498b8..3465662f3 100644
--- a/source/slang/ir-legalize-types.cpp
+++ b/source/slang/ir-legalize-types.cpp
@@ -117,6 +117,7 @@ static LegalVal declareVars(
LegalType type,
TypeLayout* typeLayout,
LegalVarChain* varChain,
+ String const* nameHint,
IRGlobalNameInfo* globalNameInfo);
static LegalType legalizeType(
@@ -708,6 +709,15 @@ RefPtr<VarLayout> findVarLayout(IRInst* value)
return nullptr;
}
+static String const* findNameHint(IRInst* inst)
+{
+ if( auto nameHintDecoration = inst->findDecoration<IRNameHintDecoration>() )
+ {
+ return &nameHintDecoration->name->text;
+ }
+ return nullptr;
+}
+
static LegalVal legalizeLocalVar(
IRTypeLegalizationContext* context,
IRVar* irLocalVar)
@@ -763,7 +773,8 @@ static LegalVal legalizeLocalVar(
varChain = &varChainStorage;
}
- LegalVal newVal = declareVars(context, kIROp_Var, legalValueType, typeLayout, varChain, nullptr);
+ String const* nameHint = findNameHint(irLocalVar);
+ LegalVal newVal = declareVars(context, kIROp_Var, legalValueType, typeLayout, varChain, nameHint, nullptr);
// Remove the old local var.
irLocalVar->removeFromParent();
@@ -794,7 +805,8 @@ static LegalVal legalizeParam(
context->insertBeforeParam = originalParam;
- auto newVal = declareVars(context, kIROp_Param, legalParamType, nullptr, nullptr, nullptr);
+ String const* nameHint = findNameHint(originalParam);
+ auto newVal = declareVars(context, kIROp_Param, legalParamType, nullptr, nullptr, nameHint, nullptr);
originalParam->removeFromParent();
context->replacedInstructions.Add(originalParam);
@@ -996,12 +1008,25 @@ static LegalVal legalizeFunc(
return LegalVal::simple(irFunc);
}
+static void addNameHint(
+ IRTypeLegalizationContext* context,
+ IRInst* inst,
+ String const& text)
+{
+ if(text.Length() == 0)
+ return;
+
+ auto name = context->session->getNameObj(text);
+ context->builder->addDecoration<IRNameHintDecoration>(inst)->name = name;
+}
+
static LegalVal declareSimpleVar(
IRTypeLegalizationContext* context,
IROp op,
IRType* type,
TypeLayout* typeLayout,
LegalVarChain* varChain,
+ String const* nameHint,
IRGlobalNameInfo* globalNameInfo)
{
RefPtr<VarLayout> varLayout = createVarLayout(varChain, typeLayout);
@@ -1087,17 +1112,23 @@ static LegalVal declareSimpleVar(
{
builder->addHighLevelDeclDecoration(irVar, varDeclRef.getDecl());
}
+
+ if( nameHint )
+ {
+ addNameHint(context, irVar, *nameHint);
+ }
}
return legalVarVal;
}
static LegalVal declareVars(
- IRTypeLegalizationContext* context,
+ IRTypeLegalizationContext* context,
IROp op,
LegalType type,
TypeLayout* typeLayout,
LegalVarChain* varChain,
+ String const* nameHint,
IRGlobalNameInfo* globalNameInfo)
{
switch (type.flavor)
@@ -1106,7 +1137,7 @@ static LegalVal declareVars(
return LegalVal();
case LegalType::Flavor::simple:
- return declareSimpleVar(context, op, type.getSimple(), typeLayout, varChain, globalNameInfo);
+ return declareSimpleVar(context, op, type.getSimple(), typeLayout, varChain, nameHint, globalNameInfo);
break;
case LegalType::Flavor::implicitDeref:
@@ -1120,6 +1151,7 @@ static LegalVal declareVars(
type.getImplicitDeref()->valueType,
getDerefTypeLayout(typeLayout),
varChain,
+ nameHint,
globalNameInfo);
return LegalVal::implicitDeref(val);
}
@@ -1128,8 +1160,8 @@ static LegalVal declareVars(
case LegalType::Flavor::pair:
{
auto pairType = type.getPair();
- auto ordinaryVal = declareVars(context, op, pairType->ordinaryType, typeLayout, varChain, globalNameInfo);
- auto specialVal = declareVars(context, op, pairType->specialType, typeLayout, varChain, globalNameInfo);
+ auto ordinaryVal = declareVars(context, op, pairType->ordinaryType, typeLayout, varChain, nameHint, globalNameInfo);
+ auto specialVal = declareVars(context, op, pairType->specialType, typeLayout, varChain, nameHint, globalNameInfo);
return LegalVal::pair(ordinaryVal, specialVal, pairType->pairInfo);
}
@@ -1158,12 +1190,28 @@ static LegalVal declareVars(
newVarChain = &newVarChainStorage;
}
+ String* fieldNameHint = nullptr;
+ String joinedNameHintStorage;
+ if( nameHint )
+ {
+ if( auto fieldNameHintDecoration = ee.key->findDecoration<IRNameHintDecoration>() )
+ {
+ joinedNameHintStorage.append(*nameHint);
+ joinedNameHintStorage.append(".");
+ joinedNameHintStorage.append(fieldNameHintDecoration->name->text);
+
+ fieldNameHint = &joinedNameHintStorage;
+ }
+
+ }
+
LegalVal fieldVal = declareVars(
context,
op,
ee.type,
fieldTypeLayout,
newVarChain,
+ fieldNameHint,
globalNameInfo);
TuplePseudoVal::Element element;
@@ -1222,7 +1270,8 @@ static LegalVal legalizeGlobalVar(
globalNameInfo.globalVar = irGlobalVar;
globalNameInfo.counter = 0;
- LegalVal newVal = declareVars(context, kIROp_GlobalVar, legalValueType, typeLayout, varChain, &globalNameInfo);
+ String const* nameHint = findNameHint(irGlobalVar);
+ LegalVal newVal = declareVars(context, kIROp_GlobalVar, legalValueType, typeLayout, varChain, nameHint, &globalNameInfo);
// Register the new value as the replacement for the old
registerLegalizedValue(context, irGlobalVar, newVal);
@@ -1263,7 +1312,9 @@ static LegalVal legalizeGlobalConstant(
globalNameInfo.counter = 0;
// TODO: need to handle initializer here!
- LegalVal newVal = declareVars(context, kIROp_GlobalConstant, legalValueType, nullptr, nullptr, &globalNameInfo);
+
+ String const* nameHint = findNameHint(irGlobalConstant);
+ LegalVal newVal = declareVars(context, kIROp_GlobalConstant, legalValueType, nullptr, nullptr, nameHint, &globalNameInfo);
// Register the new value as the replacement for the old
registerLegalizedValue(context, irGlobalConstant, newVal);
diff --git a/source/slang/ir-ssa.cpp b/source/slang/ir-ssa.cpp
index e97298969..6c4cfa8ff 100644
--- a/source/slang/ir-ssa.cpp
+++ b/source/slang/ir-ssa.cpp
@@ -350,6 +350,24 @@ IRInst* readVar(
SSABlockInfo* blockInfo,
IRVar* var);
+/// Try to take any name hint on `var` and apply it to `val`.
+///
+/// Doesn't do anything if `val` already has a name hint,
+/// or if `var` doesn't have one to transfer over.
+///
+void maybeApplyNameHint(
+ ConstructSSAContext* context,
+ IRVar* var,
+ IRInst* val)
+{
+ if( auto nameHint = var->findDecoration<IRNameHintDecoration>() )
+ {
+ if( !val->findDecoration<IRNameHintDecoration>() )
+ {
+ context->getBuilder()->addDecoration<IRNameHintDecoration>(val)->name = nameHint->name;
+ }
+ }
+}
// Add a phi node to represent the given variable
PhiInfo* addPhi(
@@ -365,6 +383,7 @@ PhiInfo* addPhi(
valueType = context->getBuilder()->getRateQualifiedType(rate, valueType);
}
IRParam* phi = builder->createParam(valueType);
+ maybeApplyNameHint(context, var, phi);
RefPtr<PhiInfo> phiInfo = new PhiInfo();
context->phiInfos.Add(phi, phiInfo);
@@ -755,6 +774,8 @@ void processBlock(
// block.
auto val = readVar(context, blockInfo, var);
+ maybeApplyNameHint(context, var, val);
+
val = applyAccessChain(context, &blockInfo->builder, ptrArg, val);
// We can just replace all uses of this
diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp
index 53050b6b9..f8ca54639 100644
--- a/source/slang/ir.cpp
+++ b/source/slang/ir.cpp
@@ -4713,6 +4713,14 @@ namespace Slang
}
break;
+ case kIRDecorationOp_NameHint:
+ {
+ auto originalDecoration = (IRNameHintDecoration*)dd;
+ auto newDecoration = context->builder->addDecoration<IRNameHintDecoration>(clonedValue);
+ newDecoration->name = originalDecoration->name;
+ }
+ break;
+
default:
// Don't clone any decorations we don't understand.
break;
diff --git a/source/slang/ir.h b/source/slang/ir.h
index 4a393cae0..5d9948b70 100644
--- a/source/slang/ir.h
+++ b/source/slang/ir.h
@@ -125,6 +125,7 @@ enum IRDecorationOp : uint16_t
kIRDecorationOp_GLSLOuterArray,
kIRDecorationOp_Semantic,
kIRDecorationOp_InterpolationMode,
+ kIRDecorationOp_NameHint,
};
// represents an object allocated in an IR memory pool
diff --git a/source/slang/legalize-types.cpp b/source/slang/legalize-types.cpp
index 6922a5174..bbfa6264d 100644
--- a/source/slang/legalize-types.cpp
+++ b/source/slang/legalize-types.cpp
@@ -341,6 +341,11 @@ struct TupleTypeBuilder
ordinaryStructType->sourceLoc = originalStructType->sourceLoc;
ordinaryStructType->mangledName = originalStructType->mangledName;
+ if(auto nameHintDecoration = originalStructType->findDecoration<IRNameHintDecoration>())
+ {
+ builder->addDecoration<IRNameHintDecoration>(ordinaryStructType)->name = nameHintDecoration->name;
+ }
+
// The new struct type will appear right after the original in the IR,
// so that we can be sure any instruction that could reference the
// original can also reference the new one.
diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp
index 2d5f169f3..ea82e4b70 100644
--- a/source/slang/lower-to-ir.cpp
+++ b/source/slang/lower-to-ir.cpp
@@ -1232,7 +1232,92 @@ void maybeSetRate(
}
}
+static Name* getNameForNameHint(
+ IRGenContext* context,
+ Decl* decl)
+{
+ // We will use a bit of an ad hoc convention here for now.
+
+ Name* leafName = decl->getName();
+
+ // Handle custom name for a global parameter group (e.g., a `cbuffer`)
+ if(auto reflectionNameModifier = decl->FindModifier<ParameterGroupReflectionName>())
+ {
+ leafName = reflectionNameModifier->nameAndLoc.name;
+ }
+
+ // There is no point in trying to provide a name hint for something with no name,
+ // or with an empty name
+ if(!leafName)
+ return nullptr;
+ if(leafName->text.Length() == 0)
+ return nullptr;
+
+
+ if(auto varDecl = dynamic_cast<VarDeclBase*>(decl))
+ {
+ // For an ordinary local variable, global variable,
+ // parameter, or field, we will just use the name
+ // as declared, and now work in anything from
+ // its parent declaration(s).
+ //
+ // TODO: consider whether global/static variables should
+ // follow different rules.
+ //
+ return leafName;
+ }
+
+ // For other cases of declaration, we want to consider
+ // merging its name with the name of its parent declaration.
+ auto parentDecl = decl->ParentDecl;
+
+ // Skip past a generic parent, if we are a declaration nested in a generic.
+ if(auto genericParentDecl = dynamic_cast<GenericDecl*>(parentDecl))
+ parentDecl = genericParentDecl->ParentDecl;
+
+ auto parentName = getNameForNameHint(context, parentDecl);
+ if(!parentName)
+ {
+ return leafName;
+ }
+
+ // TODO: at some point we will start giving `ModuleDecl`s names,
+ // and in that case we need to think carefully about whether to
+ // include their names here or not.
+ // We will now construct a new `Name` to use as the hint,
+ // combining the name of the parent and the leaf declaration.
+
+ StringBuilder sb;
+ sb.append(parentName->text);
+ sb.append(".");
+ sb.append(leafName->text);
+
+ return context->getSession()->getNameObj(sb.ProduceString());
+}
+
+/// Try to add an appropriate name hint to the instruction,
+/// that can be used for back-end code emission or debug info.
+static void addNameHint(
+ IRGenContext* context,
+ IRInst* inst,
+ Decl* decl)
+{
+ Name* name = getNameForNameHint(context, decl);
+ if(!name)
+ return;
+ context->irBuilder->addDecoration<IRNameHintDecoration>(inst)->name = name;
+}
+
+/// Add a name hint based on a fixed string.
+static void addNameHint(
+ IRGenContext* context,
+ IRInst* inst,
+ char const* text)
+{
+ Name* name = context->getSession()->getNameObj(text);
+ context->irBuilder->addDecoration<IRNameHintDecoration>(inst)->name = name;
+}
LoweredValInfo createVar(
IRGenContext* context,
@@ -1249,6 +1334,8 @@ LoweredValInfo createVar(
addVarDecorations(context, irAlloc, decl);
builder->addHighLevelDeclDecoration(irAlloc, decl);
+
+ addNameHint(context, irAlloc, decl);
}
return LoweredValInfo::ptr(irAlloc);
@@ -3406,6 +3493,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
globalVal = LoweredValInfo::ptr(irGlobal);
}
irGlobal->mangledName = context->getSession()->getNameObj(getMangledName(decl));
+ addNameHint(context, irGlobal, decl);
maybeSetRate(context, irGlobal, decl);
@@ -3605,6 +3693,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
subContext->irBuilder = subBuilder;
IRStructType* irStruct = subBuilder->createStructType();
+ addNameHint(context, irStruct, decl);
setMangledName(irStruct, getMangledName(decl));
@@ -3664,6 +3753,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
auto builder = getBuilder();
auto irFieldKey = builder->createStructKey();
+ addNameHint(context, irFieldKey, fieldDecl);
addVarDecorations(context, irFieldKey, fieldDecl);
@@ -4074,12 +4164,14 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
// TODO: use a `TypeKind` to represent the
// classifier of the parameter.
auto param = subBuilder->emitParam(nullptr);
+ addNameHint(context, param, typeParamDecl);
setValue(subContext, typeParamDecl, LoweredValInfo::simple(param));
}
else if (auto valDecl = member.As<GenericValueParamDecl>())
{
auto paramType = lowerType(subContext, valDecl->getType());
auto param = subBuilder->emitParam(paramType);
+ addNameHint(context, param, valDecl);
setValue(subContext, valDecl, LoweredValInfo::simple(param));
}
}
@@ -4092,6 +4184,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
// TODO: use a `WitnessTableKind` to represent the
// classifier of the parameter.
auto param = subBuilder->emitParam(nullptr);
+ addNameHint(context, param, constraintDecl);
setValue(subContext, constraintDecl, LoweredValInfo::simple(param));
}
}
@@ -4172,6 +4265,18 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
}
}
+ void addParamNameHint(IRInst* inst, ParameterInfo info)
+ {
+ if(auto decl = info.decl)
+ {
+ addNameHint(context, inst, decl);
+ }
+ else if( info.isThisParam )
+ {
+ addNameHint(context, inst, "this");
+ }
+ }
+
LoweredValInfo lowerFuncDecl(FunctionDeclBase* decl)
{
// We are going to use a nested builder, because we will
@@ -4221,6 +4326,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
// need to create an IR function here
IRFunc* irFunc = subBuilder->createFunc();
+ addNameHint(context, irFunc, decl);
setMangledName(irFunc, getMangledName(decl));
@@ -4335,6 +4441,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
{
subBuilder->addHighLevelDeclDecoration(irParamPtr, paramDecl);
}
+ addParamNameHint(irParamPtr, paramInfo);
paramVal = LoweredValInfo::ptr(irParamPtr);
@@ -4361,6 +4468,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
{
subBuilder->addHighLevelDeclDecoration(irParam, paramDecl);
}
+ addParamNameHint(irParam, paramInfo);
paramVal = LoweredValInfo::simple(irParam);
//
// HLSL allows a function parameter to be used as a local
@@ -4416,7 +4524,8 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
{
// Add the IR parameter for the new value
IRType* irParamType = irResultType;
- subBuilder->emitParam(irParamType);
+ auto irParam = subBuilder->emitParam(irParamType);
+ addNameHint(context, irParam, "newValue");
// TODO: we need some way to wire this up to the `newValue`
// or whatever name we give for that parameter inside