diff options
| author | Tim Foley <tfoley@nvidia.com> | 2017-08-31 12:47:39 -0700 |
|---|---|---|
| committer | Tim Foley <tfoley@nvidia.com> | 2017-09-06 13:52:04 -0700 |
| commit | 5900f32fff9970b4221ce7fb7e94133e387ff9de (patch) | |
| tree | fd83b7e861dbc6a0d442d5a913a1bcd9df547408 /source/slang/ir.cpp | |
| parent | e59a1b39317c10815baaed3b70c4a6580dbe1e63 (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.cpp | 143 |
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; + } + // |
