summaryrefslogtreecommitdiffstats
path: root/source/slang/bytecode.h
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2017-10-04 13:54:25 -0700
committerGitHub <noreply@github.com>2017-10-04 13:54:25 -0700
commit54f016e7ef36b7505bf47d188cf4b7e1fdc443a4 (patch)
treef8a385c8a3bbac807c2c0d08a9b1e4cd208db95c /source/slang/bytecode.h
parent8a0ebb9fa25fd44def17b03b3f8aa1a33ad77940 (diff)
IR: overhaul IR design/implementation (#195)
* IR: overhaul IR design/implementation Closes #192 Closes #188 This is a major overhaul of how the IR is implemented, with the primary goal of just using the AST-level type representation as the IR's type representation, rather than inventing an entire shadow set of types (as captured in issue #192). One consequence of this choice is that types in the IR are no longer explicit "instructions" and are not represented as ordinary operands (so a bunch of `+ 1` cases end up going away when enumerating ordinary operands). Along the way I also got rid of the embedded IDs in the IR (issue #188) because this wasn't too hard to deal with at the same time. Another related change was to split the `IRValue` and `IRInst` cases, so that there are values that are not also instructions. Non-instruction values are now used to represent literals, references to declarations, and would eventually be used for an `undef` value if we need one. IR functions, global variables, and basic blocks are all values (because they can appear as operands), but not instructions. The main benefit of this approach is that the top-level structure of a bytecode (BC) module is much simpler to understand and walk, and BC-level types are represented much more directly (such that we could conceivably use them for reflection soon). * fixup: 64-bit build fix * fixup: try to silence clang's pedantic dependent-type errors * fixup: bug in VM loading of constants
Diffstat (limited to 'source/slang/bytecode.h')
-rw-r--r--source/slang/bytecode.h102
1 files changed, 76 insertions, 26 deletions
diff --git a/source/slang/bytecode.h b/source/slang/bytecode.h
index e073763cf..1ea16406f 100644
--- a/source/slang/bytecode.h
+++ b/source/slang/bytecode.h
@@ -65,6 +65,7 @@ struct BCPtr
}
operator T*() const { return getPtr(); }
+ T* operator->() const { return getPtr(); }
T* getPtr() const
{
@@ -73,9 +74,52 @@ struct BCPtr
}
};
-struct BCType
+// Representation of a "type-level" value in
+// the bytecode fiel. This corresponds to
+// the AST-level notion of a `Val`
+struct BCVal
{
+ // The opcode used to define this value
uint32_t op;
+
+ // The ID of the type within its module
+ uint32_t id;
+};
+
+struct BCType : BCVal
+{
+ // TODO: avoid having to encode this?
+ uint32_t argCount;
+
+ // type-specific operands follow
+
+ //
+
+ BCPtr<BCVal>* getArgs() { return (BCPtr<BCVal>*) (this +1); }
+
+ BCVal* getArg(UInt index) { return getArgs()[index]; }
+};
+
+struct BCPtrType : BCType
+{
+ BCPtr<BCType> valueType;
+};
+
+struct BCFuncType : BCType
+{
+ BCPtr<BCType> resultType;
+ BCPtr<BCType> paramTypes[1];
+
+ BCType* getResultType() { return resultType; }
+
+ UInt getParamCount() { return argCount - 1; }
+ BCType* getParamType(UInt index) { return paramTypes[index]; }
+};
+
+struct BCConstant : BCVal
+{
+ uint32_t typeID;
+ BCPtr<uint8_t> ptr;
};
struct BCSymbol
@@ -84,15 +128,9 @@ struct BCSymbol
// this symbol; used to categorize things
uint32_t op;
- // The type of the symbol is represent
- // as an index into the global-scope symbol
- // list of the module.
- //
- // Note: This currently precludes having
- // a register with a type that is not
- // statically determined, but that is
- // probably okay.
- uint32_t typeGlobalID;
+ // The index (in the module's type table)
+ // of the type of the symbol:
+ uint32_t typeID;
// The name of this symbol (which might
// be a mangled name at some point,
@@ -111,17 +149,18 @@ struct BCReg : BCSymbol
uint32_t previousVarIndexPlusOne;
};
+enum BCConstFlavor
+{
+ kBCConstFlavor_GlobalSymbol,
+ kBCConstFlavor_Constant,
+};
+
struct BCConst
{
- // The ID of the symbol in the global
- // scope that we are trying to refer
- // to.
- //
- // TODO: eventually, if we have general
- // nesting, then this might be the
- // entry in the outer scope that
- // is being referenced.
- uint32_t globalID;
+ // The flavor of bytecode constant we
+ // are dealing with.
+ uint32_t flavor;
+ uint32_t id;
};
struct BCBlock
@@ -153,16 +192,27 @@ struct BCFunc : BCSymbol
// but this would make the encoding less dense.
uint32_t constCount;
BCPtr<BCConst> consts;
-
- // Data for "nested" symbols (e.g., a function
- // nested inside this function).
- uint32_t nestedSymbolCount;
- BCPtr<BCPtr<BCSymbol>> nestedSymbols;
};
-// A module is encoded more or less like a function.
-struct BCModule : BCFunc
+struct BCModule
{
+ // The symbols (functions, global variables, etc.)
+ // that have been declared in the module.
+ uint32_t symbolCount;
+ BCPtr<BCPtr<BCSymbol>> symbols;
+
+ // The types that are used by this module, stored
+ // in a single array so that they can be conveniently
+ // mapped to another representation in one go.
+ //
+ // Instructions in a bytecode instruction sequence
+ // might reference these types by index.
+ uint32_t typeCount;
+ BCPtr<BCPtr<BCType>> types;
+
+ // True compile-time constants go here:
+ uint32_t constantCount;
+ BCPtr<BCConstant> constants;
};
struct BCHeader