summaryrefslogtreecommitdiffstats
path: root/source/slang/ir.cpp
diff options
context:
space:
mode:
authorTim Foley <tfoley@nvidia.com>2017-08-31 12:47:39 -0700
committerTim Foley <tfoley@nvidia.com>2017-09-06 13:52:04 -0700
commit5900f32fff9970b4221ce7fb7e94133e387ff9de (patch)
treefd83b7e861dbc6a0d442d5a913a1bcd9df547408 /source/slang/ir.cpp
parente59a1b39317c10815baaed3b70c4a6580dbe1e63 (diff)
Continue work on IR-based codegen
This gets us far enough that we can convert a single test case to use the IR, under the new `-use-ir` flag. Getting this merged into mainline will at least ensure that we keep the IR path working in a minimal fashion, even when we have to add functionality the existing AST-based path There is definitely some clutter here from keeping both IR-based and AST-based translation around, but I don't want to have a long-lived branch for the IR that gets further and further away from the `master` branch that is actually getting used and tested. Summary of changes: - Add pointer types and basic `load` operation to be able to handle variable declarations - Add basic `call` instruction type - Add simple address math for field reference in l-value - Always add IR for referenced decls to global scope - Add notion of "intrinsic" type modifier, which maps a type declaration directly to an IR opcode (plus optional literal operands to handle things like texture/sampler flavor) - Improve printing of IR instructions, types, operands - Add constant-buffer type to IR - Allow any instruction to be detected as "should be folded into use sites" and use this to tag things of constant-buffer type - Also add logic for implicit base on member expressions, to handle references to `cbuffer` members - Add connection back to original decl to IR variables (including global shader parameters...) - Use reflection name instead of true name when emitting HLSL from IR (so that we can match HLSL output) - Make IR include decorations for type layout - Re-use existing emit logic for HLSL semantics to output `register` semantics for IR-based code - Make IR-based codegen be an option we can enable from the command line - It still isn't on by default (it can barely manage a trivial shader), but it seems better to enable it always instead of putting it under an `#ifdef` - Fix up how we check for intrinsic operations suring AST-based cross compilation so that adding new intrinsic ops for the IR won't break codegen.
Diffstat (limited to 'source/slang/ir.cpp')
-rw-r--r--source/slang/ir.cpp143
1 files changed, 138 insertions, 5 deletions
diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp
index 8e4f789ef..3f07a685f 100644
--- a/source/slang/ir.cpp
+++ b/source/slang/ir.cpp
@@ -365,8 +365,10 @@ namespace Slang
UInt size,
IROp op,
IRType* type,
- UInt argCount,
- IRValue* const* args)
+ UInt fixedArgCount,
+ IRValue* const* fixedArgs,
+ UInt varArgCount = 0,
+ IRValue* const* varArgs = nullptr)
{
// First, we need to pick a good insertion point
// for the instruction, which we do by looking
@@ -378,9 +380,14 @@ namespace Slang
{
parent = joinParentInstsForInsertion(parent, type->parent);
}
- for( UInt aa = 0; aa < argCount; ++aa )
+ for( UInt aa = 0; aa < fixedArgCount; ++aa )
{
- auto arg = args[aa];
+ auto arg = fixedArgs[aa];
+ parent = joinParentInstsForInsertion(parent, arg->parent);
+ }
+ for( UInt aa = 0; aa < varArgCount; ++aa )
+ {
+ auto arg = varArgs[aa];
parent = joinParentInstsForInsertion(parent, arg->parent);
}
@@ -405,7 +412,7 @@ namespace Slang
// way: we will construct a temporary instruction and
// then use it to look up in a cache of instructions.
- IRInst* keyInst = createInstImpl(builder, size, op, type, argCount ,args);
+ IRInst* keyInst = createInstImpl(builder, size, op, type, fixedArgCount, fixedArgs, varArgCount, varArgs);
keyInst->parent = parent;
IRInstKey key;
@@ -452,6 +459,27 @@ namespace Slang
static T* findOrEmitInst(
IRBuilder* builder,
IROp op,
+ IRType* type,
+ UInt fixedArgCount,
+ IRValue* const* fixedArgs,
+ UInt varArgCount,
+ IRValue* const* varArgs)
+ {
+ return (T*) findOrEmitInstImpl(
+ builder,
+ sizeof(T) + varArgCount * sizeof(IRUse),
+ op,
+ type,
+ fixedArgCount,
+ fixedArgs,
+ varArgCount,
+ varArgs);
+ }
+
+ template<typename T>
+ static T* findOrEmitInst(
+ IRBuilder* builder,
+ IROp op,
IRType* type)
{
return (T*) findOrEmitInstImpl(
@@ -630,6 +658,22 @@ namespace Slang
getTypeType());
}
+ IRType* IRBuilder::getIntrinsicType(
+ IROp op,
+ UInt argCount,
+ IRValue* const* args)
+ {
+ return findOrEmitInst<IRType>(
+ this,
+ op,
+ getTypeType(),
+ 0,
+ nullptr,
+ argCount,
+ args);
+ }
+
+
IRStructDecl* IRBuilder::createStructType()
{
return createInst<IRStructDecl>(
@@ -652,6 +696,7 @@ namespace Slang
IRType* const* paramTypes,
IRType* resultType)
{
+ // TODO: need to unique things here!
auto inst = createInstWithTrailingArgs<IRFuncType>(
this,
kIROp_FuncType,
@@ -664,6 +709,19 @@ namespace Slang
return inst;
}
+ IRType* IRBuilder::getPtrType(
+ IRType* valueType)
+ {
+ auto inst = findOrEmitInst<IRPtrType>(
+ this,
+ kIROp_PtrType,
+ getTypeType(),
+ 1,
+ (IRValue* const*) &valueType);
+ return inst;
+ }
+
+
IRValue* IRBuilder::getBoolValue(bool value)
{
SLANG_UNIMPLEMENTED_X("IR");
@@ -689,6 +747,24 @@ namespace Slang
&value);
}
+ IRInst* IRBuilder::emitCallInst(
+ IRType* type,
+ IRValue* func,
+ UInt argCount,
+ IRValue* const* args)
+ {
+ auto inst = createInstWithTrailingArgs<IRCall>(
+ this,
+ kIROp_Call,
+ type,
+ 1,
+ &func,
+ argCount,
+ args);
+ addInst(inst);
+ return inst;
+ }
+
IRInst* IRBuilder::emitIntrinsicInst(
IRType* type,
IntrinsicOp intrinsicOp,
@@ -763,6 +839,40 @@ namespace Slang
return inst;
}
+ IRVar* IRBuilder::emitVar(
+ IRType* type)
+ {
+ auto allocatedType = getPtrType(type);
+ auto inst = createInst<IRVar>(
+ this,
+ kIROp_Var,
+ allocatedType);
+ addInst(inst);
+ return inst;
+ }
+
+ IRInst* IRBuilder::emitLoad(
+ IRValue* ptr)
+ {
+ auto ptrType = ptr->getType();
+ if( ptrType->op != kIROp_PtrType )
+ {
+ // Bad!
+ return nullptr;
+ }
+
+ auto valueType = ((IRPtrType*) ptrType)->getValueType();
+
+ auto inst = createInst<IRLoad>(
+ this,
+ kIROp_Load,
+ valueType,
+ ptr);
+
+ addInst(inst);
+ return inst;
+ }
+
IRInst* IRBuilder::emitFieldExtract(
IRType* type,
IRValue* base,
@@ -779,6 +889,22 @@ namespace Slang
return inst;
}
+ IRInst* IRBuilder::emitFieldAddress(
+ IRType* type,
+ IRValue* base,
+ IRStructField* field)
+ {
+ auto inst = createInst<IRFieldAddress>(
+ this,
+ kIROp_FieldAddress,
+ type,
+ base,
+ field);
+
+ addInst(inst);
+ return inst;
+ }
+
IRInst* IRBuilder::emitReturn(
IRValue* val)
{
@@ -824,6 +950,13 @@ namespace Slang
return decoration;
}
+ IRLayoutDecoration* IRBuilder::addLayoutDecoration(IRInst* inst, Layout* layout)
+ {
+ auto decoration = addDecoration<IRLayoutDecoration>(inst);
+ decoration->layout = layout;
+ return decoration;
+ }
+
//