From 5900f32fff9970b4221ce7fb7e94133e387ff9de Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Thu, 31 Aug 2017 12:47:39 -0700 Subject: 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. --- source/slang/ir.cpp | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 138 insertions(+), 5 deletions(-) (limited to 'source/slang/ir.cpp') 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; @@ -448,6 +455,27 @@ namespace Slang args); } + template + 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 static T* findOrEmitInst( IRBuilder* builder, @@ -630,6 +658,22 @@ namespace Slang getTypeType()); } + IRType* IRBuilder::getIntrinsicType( + IROp op, + UInt argCount, + IRValue* const* args) + { + return findOrEmitInst( + this, + op, + getTypeType(), + 0, + nullptr, + argCount, + args); + } + + IRStructDecl* IRBuilder::createStructType() { return createInst( @@ -652,6 +696,7 @@ namespace Slang IRType* const* paramTypes, IRType* resultType) { + // TODO: need to unique things here! auto inst = createInstWithTrailingArgs( this, kIROp_FuncType, @@ -664,6 +709,19 @@ namespace Slang return inst; } + IRType* IRBuilder::getPtrType( + IRType* valueType) + { + auto inst = findOrEmitInst( + 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( + 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( + 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( + 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( + 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(inst); + decoration->layout = layout; + return decoration; + } + // -- cgit v1.2.3