summaryrefslogtreecommitdiffstats
path: root/source/slang/ir.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/ir.cpp')
-rw-r--r--source/slang/ir.cpp144
1 files changed, 97 insertions, 47 deletions
diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp
index 40c7e20d5..50b0b83e9 100644
--- a/source/slang/ir.cpp
+++ b/source/slang/ir.cpp
@@ -59,41 +59,81 @@ namespace Slang
//
+ void IRUse::debugValidate()
+ {
+#ifdef _DEBUG
+ auto uv = this->usedValue;
+ if(!uv)
+ {
+ assert(!user);
+ assert(!nextUse);
+ assert(!prevLink);
+ return;
+ }
+
+ auto pp = &uv->firstUse;
+ for(auto u = uv->firstUse; u;)
+ {
+ assert(u->prevLink == pp);
+
+ pp = &u->nextUse;
+ u = u->nextUse;
+ }
+#endif
+ }
+
void IRUse::init(IRUser* u, IRValue* v)
{
+ clear();
+
user = u;
usedValue = v;
-
if(v)
{
nextUse = v->firstUse;
prevLink = &v->firstUse;
+ if(nextUse)
+ {
+ nextUse->prevLink = &this->nextUse;
+ }
+
v->firstUse = this;
}
+
+ debugValidate();
}
- void IRUse::set(IRValue* usedVal)
+ void IRUse::set(IRValue* uv)
{
- // clear out the old value
- if (usedVal)
- {
- if (prevLink)
- *prevLink = nextUse;
- }
-
- init(user, usedVal);
+ init(user, uv);
}
void IRUse::clear()
{
+ // This `IRUse` is part of the linked list
+ // of uses for `usedValue`.
+
+ debugValidate();
+
if (usedValue)
{
+ auto uv = usedValue;
+
*prevLink = nextUse;
- }
+ if(nextUse)
+ {
+ nextUse->prevLink = prevLink;
+ }
+
+ user = nullptr;
+ usedValue = nullptr;
+ nextUse = nullptr;
+ prevLink = nullptr;
- user = nullptr;
- usedValue = nullptr;
+ if(uv->firstUse)
+ uv->firstUse->debugValidate();
+ }
}
//
@@ -250,7 +290,7 @@ namespace Slang
// We will re-use the logic for getting the successor
// list from such an instruction.
- auto successorList = getSuccessors((IRInst*) use->user);
+ auto successorList = getSuccessors((IRInst*) use->getUser());
if(use >= successorList.begin_
&& use < successorList.end_)
@@ -315,7 +355,7 @@ namespace Slang
IRBlock* IRBlock::PredecessorList::Iterator::operator*()
{
if (!use) return nullptr;
- return (IRBlock*)use->user->parent;
+ return (IRBlock*)use->getUser()->parent;
}
IRBlock::SuccessorList IRBlock::getSuccessors()
@@ -351,7 +391,7 @@ namespace Slang
IRBlock* IRBlock::SuccessorList::Iterator::operator*()
{
- return (IRBlock*)use->usedValue;
+ return (IRBlock*)use->get();
}
// IRFunc
@@ -714,7 +754,7 @@ namespace Slang
auto rightArgs = right.inst->getArgs();
for( UInt aa = 0; aa < argCount; ++aa )
{
- if(leftArgs[aa].usedValue != rightArgs[aa].usedValue)
+ if(leftArgs[aa].get() != rightArgs[aa].get())
return false;
}
@@ -731,7 +771,7 @@ namespace Slang
auto args = inst->getArgs();
for( UInt aa = 0; aa < argCount; ++aa )
{
- code = combineHash(code, Slang::GetHashCode(args[aa].usedValue));
+ code = combineHash(code, Slang::GetHashCode(args[aa].get()));
}
return code;
}
@@ -1894,7 +1934,7 @@ namespace Slang
}
else if (auto proxyVal = dynamic_cast<IRProxyVal*>(val))
{
- dumpOperand(context, proxyVal->inst.usedValue);
+ dumpOperand(context, proxyVal->inst.get());
}
else
{
@@ -2283,7 +2323,7 @@ namespace Slang
if (ii != 0)
dump(context, ", ");
- auto argVal = inst->getArgs()[ii].usedValue;
+ auto argVal = inst->getArgs()[ii].get();
dumpOperand(context, argVal);
}
@@ -2449,9 +2489,9 @@ namespace Slang
IRWitnessTableEntry* entry)
{
dump(context, "witness_table_entry(");
- dumpOperand(context, entry->requirementKey.usedValue);
+ dumpOperand(context, entry->requirementKey.get());
dump(context, ",");
- dumpOperand(context, entry->satisfyingVal.usedValue);
+ dumpOperand(context, entry->satisfyingVal.get());
dump(context, ")\n");
}
@@ -2522,6 +2562,20 @@ namespace Slang
dumpIRModule(&context, module);
}
+ void dumpIR(IRGlobalValue* globalVal)
+ {
+ StringBuilder sb;
+
+ IRDumpContext context;
+ context.builder = &sb;
+ context.indent = 0;
+
+ dumpIRGlobalValue(&context, globalVal);
+
+ fprintf(stderr, "%s\n", sb.Buffer());
+ fflush(stderr);
+ }
+
String getSlangIRAssembly(IRModule* module)
{
StringBuilder sb;
@@ -2551,12 +2605,14 @@ namespace Slang
if(!ff)
return;
+ ff->debugValidate();
+
IRUse* uu = ff;
for(;;)
{
// The uses had better all be uses of this
// instruction, or invariants are broken.
- assert(uu->usedValue == this);
+ assert(uu->get() == this);
// Swap this use over to use the other value.
uu->usedValue = other;
@@ -2597,6 +2653,8 @@ namespace Slang
// And `this` will have no uses any more.
this->firstUse = nullptr;
+
+ ff->debugValidate();
}
void IRValue::deallocate()
@@ -2684,15 +2742,7 @@ namespace Slang
for( UInt aa = 0; aa < argCount; ++aa )
{
IRUse& use = getArgs()[aa];
-
- if(!use.usedValue)
- continue;
-
- // Need to unlink this use from the appropriate linked list.
- use.usedValue = nullptr;
- *use.prevLink = use.nextUse;
- use.prevLink = nullptr;
- use.nextUse = nullptr;
+ use.clear();
}
}
@@ -3616,7 +3666,7 @@ namespace Slang
{
auto proxyVal = witness.Value.As<IRProxyVal>();
SLANG_ASSERT(proxyVal);
- return proxyVal->inst.usedValue;
+ return proxyVal->inst.get();
}
}
}
@@ -3651,7 +3701,7 @@ namespace Slang
{
if (auto proxyVal = dynamic_cast<IRProxyVal*>(val))
{
- auto newIRVal = cloneValue(context, proxyVal->inst.usedValue);
+ auto newIRVal = cloneValue(context, proxyVal->inst.get());
RefPtr<IRProxyVal> newProxyVal = new IRProxyVal();
newProxyVal->inst.init(nullptr, newIRVal);
@@ -3879,10 +3929,10 @@ namespace Slang
// Clone the entries in the witness table as well
for( auto originalEntry : originalTable->entries )
{
- auto clonedKey = cloneValue(context, originalEntry->requirementKey.usedValue);
+ auto clonedKey = cloneValue(context, originalEntry->requirementKey.get());
// if a global val with the mangled name already exists, don't clone again
- auto clonedVal = maybeCloneValueWithMangledName(context, (IRGlobalValue*)(originalEntry->satisfyingVal.usedValue));
+ auto clonedVal = maybeCloneValueWithMangledName(context, (IRGlobalValue*)(originalEntry->satisfyingVal.get()));
/*auto clonedEntry = */context->builder->createWitnessTableEntry(
clonedTable,
@@ -4643,7 +4693,7 @@ namespace Slang
// the pointed-to value and not the proxy type-level `Val`
// instead.
- return context->maybeCloneValue(proxyVal->inst.usedValue);
+ return context->maybeCloneValue(proxyVal->inst.get());
}
else
{
@@ -4905,9 +4955,9 @@ namespace Slang
// of involved functions.
for (auto entry : specTable->entries)
{
- if (entry->satisfyingVal.usedValue->op == kIROp_Func)
+ if (entry->satisfyingVal.get()->op == kIROp_Func)
{
- IRFunc* func = (IRFunc*)entry->satisfyingVal.usedValue;
+ IRFunc* func = (IRFunc*)entry->satisfyingVal.get();
auto specFunc = getSpecializedFunc(sharedContext, func, specDeclRef);
entry->satisfyingVal.set(specFunc);
insertGlobalValueSymbol(sharedContext, specFunc);
@@ -5016,7 +5066,7 @@ namespace Slang
{
// We expect the key on the entry to be a decl-ref,
// but lets go ahead and check, just to be sure.
- auto requirementKey = entry->requirementKey.usedValue;
+ auto requirementKey = entry->requirementKey.get();
if(requirementKey->op != kIROp_decl_ref)
continue;
auto keyDeclRef = ((IRDeclRef*) requirementKey)->declRef;
@@ -5039,7 +5089,7 @@ namespace Slang
// If the keys matched, then we use the value from
// this entry.
- auto satisfyingVal = entry->satisfyingVal.usedValue;
+ auto satisfyingVal = entry->satisfyingVal.get();
return satisfyingVal;
}
@@ -5147,11 +5197,11 @@ namespace Slang
// Now we extract the specialized decl-ref that will
// tell us how to specialize things.
- auto specDeclRefVal = (IRDeclRef*)specInst->specDeclRefVal.usedValue;
+ auto specDeclRefVal = (IRDeclRef*)specInst->specDeclRefVal.get();
auto specDeclRef = specDeclRefVal->declRef;
// We need to specialize functions and witness tables
- auto genericVal = specInst->genericVal.usedValue;
+ auto genericVal = specInst->genericVal.get();
if (genericVal->op == kIROp_Func)
{
auto genericFunc = (IRFunc*)genericVal;
@@ -5187,8 +5237,8 @@ namespace Slang
// try find concrete witness table from global scope
IRLookupWitnessTable* lookupInst = (IRLookupWitnessTable*)ii;
IRWitnessTable* witnessTable = nullptr;
- auto srcDeclRef = ((IRDeclRef*)lookupInst->sourceType.usedValue)->declRef;
- auto interfaceDeclRef = ((IRDeclRef*)lookupInst->interfaceType.usedValue)->declRef;
+ auto srcDeclRef = ((IRDeclRef*)lookupInst->sourceType.get())->declRef;
+ auto interfaceDeclRef = ((IRDeclRef*)lookupInst->interfaceType.get())->declRef;
auto mangledName = getMangledNameForConformanceWitness(srcDeclRef, interfaceDeclRef);
witnessTables.TryGetValue(mangledName, witnessTable);
@@ -5221,14 +5271,14 @@ namespace Slang
// We only want to deal with the case where the witness-table
// argument points to a concrete global table.
- auto witnessTableArg = lookupInst->witnessTable.usedValue;
+ auto witnessTableArg = lookupInst->witnessTable.get();
if(witnessTableArg->op != kIROp_witness_table)
continue;
IRWitnessTable* witnessTable = (IRWitnessTable*)witnessTableArg;
// We also need to be sure that the requirement we
// are trying to look up is identified via a decl-ref:
- auto requirementArg = lookupInst->requirementDeclRef.usedValue;
+ auto requirementArg = lookupInst->requirementDeclRef.get();
if(requirementArg->op != kIROp_decl_ref)
continue;
auto requirementDeclRef = ((IRDeclRef*) requirementArg)->declRef;