diff options
| author | Tim Foley <tfoley@nvidia.com> | 2017-08-17 13:40:50 -0700 |
|---|---|---|
| committer | Tim Foley <tfoley@nvidia.com> | 2017-08-17 13:44:02 -0700 |
| commit | ad19484792dcc5a1fb90720614830c66c4b9712d (patch) | |
| tree | 45e5c5152b4d5deca3125d9fb8159d114bc09d14 /source/slang/ir.h | |
| parent | 1965c3f3f265c43c8d1d96bb49d0850ce5d53cc3 (diff) | |
Add some dummy logic to print IR to HLSL
- Change IR instructions to just hold an integer opcode instead of a pointer to the "info" structure
- Externalize definition of IR instructions to a header file, and use the "X macro" approach to allow generating different definitions
- Add notion of function types to the IR, so that we can easily query the result type of a function
- Add some convenience accesors to allow walking the IR in a strongly-typed manner (e.g., iterate over the parameters of a function)
- TODO: these should really be changed to assert the type of things, as least in debug builds
- Add very basic logic to `emit.cpp` so that it can walk the generated IR and start printing it back as HLSL
- This isn't meant to be usable as-is, but it is a step toward where we need to go
Diffstat (limited to 'source/slang/ir.h')
| -rw-r--r-- | source/slang/ir.h | 73 |
1 files changed, 69 insertions, 4 deletions
diff --git a/source/slang/ir.h b/source/slang/ir.h index 0a0c8d612..e583997fd 100644 --- a/source/slang/ir.h +++ b/source/slang/ir.h @@ -27,6 +27,15 @@ enum : IROpFlags kIROpFlag_Parent = 1 << 0, }; +enum IROp : uint16_t +{ + +#define INST(ID, MNEMONIC, ARG_COUNT, FLAGS) \ + kIROp_##ID, + +#include "ir-inst-defs.h" +}; + // A logical operation/opcode in the IR struct IROpInfo { @@ -67,7 +76,7 @@ typedef uint32_t IRInstID; struct IRInst { // The operation that this value represents - IROpInfo const* op; + IROp op; // A unique ID to represent the op when printing // (or zero to indicate that the value of this @@ -93,7 +102,19 @@ struct IRInst // The type of this value IRUse type; + IRType* getType() { return (IRType*) type.usedValue; } + + UInt getArgCount() + { + return argCount; + } + IRUse* getArgs(); + + IRInst* getArg(UInt index) + { + return getArgs()[index].usedValue; + } }; typedef IRInst IRValue; @@ -127,15 +148,40 @@ struct IRVectorType : IRType { IRUse elementType; IRUse elementCount; + + IRType* getElementType() { return (IRType*) elementType.usedValue; } + IRInst* getElementCount() { return elementCount.usedValue; } }; struct IRStructType : IRType -{}; +{ + + UInt getFieldCount() { return getArgCount() - 1; } + IRType* getFieldType(UInt index) { return (IRType*) getArg(index + 1); } +}; + +struct IRFuncType : IRType +{ + IRUse resultType; + // parameter tyeps are varargs... + + IRType* getResultType() { return (IRType*) resultType.usedValue; } + UInt getParamCount() + { + return getArgCount() - 2; + } + IRType* getParamType(UInt index) + { + return (IRType*) getArg(2 + index); + } +}; struct IRFieldExtract : IRInst { IRUse base; UInt fieldIndex; + + IRInst* getBase() { return base.usedValue; } }; // A instruction that ends a basic block (usually because of control flow) @@ -148,6 +194,8 @@ struct IRReturn : IRTerminatorInst struct IRReturnVal : IRReturn { IRUse val; + + IRInst* getVal() { return val.usedValue; } }; struct IRReturnVoid : IRReturn @@ -174,14 +222,16 @@ struct IRBlock : IRParentInst // Note that in a valid program, every block must end with // a "terminator" instruction, so these should be non-NULL, // and `last` should actually be an `IRTerminatorInst`. - IRInst* firstChild; - IRInst* lastChild; + + IRBlock* getPrevBlock() { return (IRBlock*) prevInst; } + IRBlock* getNextBlock() { return (IRBlock*) nextInst; } }; // A function parameter is represented by an instruction // in the entry block of a function. struct IRParam : IRInst { + IRParam* getNextParam(); }; // A function is a parent to zero or more blocks of instructions. @@ -190,6 +240,16 @@ struct IRParam : IRInst // an instruction (e.g., a call). struct IRFunc : IRParentInst { + IRFuncType* getType() { return (IRFuncType*) type.usedValue; } + + IRType* getResultType() { return getType()->getResultType(); } + UInt getParamCount() { return getType()->getParamCount(); } + IRType* getParamType(UInt index) { return getType()->getParamType(index); } + + IRBlock* getFirstBlock() { return (IRBlock*) firstChild; } + IRBlock* getLastBlock() { return (IRBlock*) lastChild; } + + IRParam* getFirstParam(); }; // A module is a parent to functions, global variables, types, etc. @@ -252,6 +312,11 @@ struct IRBuilder UInt fieldCount, IRType* const* fieldTypes); + IRType* getFuncType( + UInt paramCount, + IRType* const* paramTypes, + IRType* resultType); + IRValue* getBoolValue(bool value); IRValue* getIntValue(IRType* type, IRIntegerValue value); IRValue* getFloatValue(IRType* type, IRFloatingPointValue value); |
