summaryrefslogtreecommitdiff
path: root/source/slang/ir.h
diff options
context:
space:
mode:
authorTim Foley <tim.foley.is@gmail.com>2017-08-16 16:25:32 -0700
committerGitHub <noreply@github.com>2017-08-16 16:25:32 -0700
commit3dd88c2eb5cd2e405cd5aa184a2cd45db6fb027a (patch)
tree040d49332f125fb7a5450128c98cb9abf21ec035 /source/slang/ir.h
parent74e04b8746f7254d5e95520ff31fb09d4bc327b1 (diff)
parente30ba2f6b7ad346fa5f2d435a9edc9ba1c56efab (diff)
Merge pull request #167 from tfoleyNV/ir
More work on IR
Diffstat (limited to 'source/slang/ir.h')
-rw-r--r--source/slang/ir.h253
1 files changed, 188 insertions, 65 deletions
diff --git a/source/slang/ir.h b/source/slang/ir.h
index db46235b3..95dec6007 100644
--- a/source/slang/ir.h
+++ b/source/slang/ir.h
@@ -7,125 +7,248 @@
// similar in spirit to LLVM (but much simpler).
//
+// We need the definition of `BaseType` which currently belongs to the AST
+#include "syntax.h"
+
namespace Slang {
-struct IRBlock;
struct IRFunc;
+struct IRInst;
struct IRModule;
+struct IRParentInst;
struct IRType;
-// A value that can be referenced in the program.
-struct IRValue
+typedef unsigned int IROpFlags;
+enum : IROpFlags
+{
+ kIROpFlags_None = 0,
+
+ // This op is a parent op
+ kIROpFlag_Parent = 1 << 0,
+};
+
+// A logical operation/opcode in the IR
+struct IROpInfo
+{
+ // What is the name/mnemonic for this operation
+ char const* name;
+
+ // How many required arguments are there
+ // (not including the mandatory type argument)
+ unsigned int fixedArgCount;
+
+ // Flags to control how we emit additional info
+ IROpFlags flags;
+};
+
+// A use of another value/inst within an IR operation
+struct IRUse
+{
+ // The value that is doing the using.
+ IRInst* user;
+
+ // The value that is being used
+ IRInst* usedValue;
+
+ // The next use of the same value
+ IRUse* nextUse;
+
+ // A "link" back to where this use is referenced,
+ // so that we can simplify updates.
+ IRUse** prevLink;
+
+ void init(IRInst* user, IRInst* usedValue);
+};
+
+// In the IR, almost *everything* is an instruction,
+// in order to make the representation as uniform as possible.
+struct IRInst
+{
+ // The operation that this value represents
+ IROpInfo const* op;
+
+ // A unique ID to represent the op when printing
+ // (or zero to indicate that the value of this
+ // op isn't special).
+ UInt id;
+
+ // The parent of this instruction.
+ // This will often be a basic block, but we
+ // allow instructions to nest in more general ways.
+ IRParentInst* parent;
+
+ // The next and previous instructions in the same parent block
+ IRInst* nextInst;
+ IRInst* prevInst;
+
+ // The first use of this value (start of a linked list)
+ IRUse* firstUse;
+
+ // The type of this value
+ IRUse type;
+
+ IRUse* getArgs();
+};
+
+typedef IRInst IRValue;
+
+typedef long long IRIntegerValue;
+typedef double IRFloatingPointValue;
+
+struct IRIntLit : IRInst
+{
+ IRIntegerValue value;
+};
+
+struct IRFloatLit : IRInst
{
- // Type type of this value
- IRType* type;
+ IRFloatingPointValue value;
};
// Representation of a type at the IR level.
// Such a type may not correspond to the high-level-language notion
// of a type as used by the front end.
//
-// Note that types are values in the IR, so that operations
+// Note that types are instructions in the IR, so that operations
// may take type operands as easily as values.
-struct IRType : IRValue
+struct IRType : IRInst
{
};
-// An instruction in the program.
-struct IRInst : IRValue
+struct IRVectorType : IRType
{
- // The basic block that contains this instruction,
- // or NULL if the instruction currently has no parent.
- IRBlock* parentBlock;
+ IRUse elementType;
+ IRUse elementCount;
+};
- // The next and previous instructions in the same parent block
- IRInst* nextInst;
- IRInst* prevInst;
+struct IRStructType : IRType
+{};
+
+struct IRFieldExtract : IRInst
+{
+ IRUse base;
+ UInt fieldIndex;
};
// A instruction that ends a basic block (usually because of control flow)
struct IRTerminatorInst : IRInst
{};
-// A basic block, consisting of a sequence of instructions that can only
-// be entered at the top, and can only be exited at the last instruction.
-//
-// Note that a block is itself a value, so that it can be a direct operand
-// of an instruction (e.g., an instruction that branches to the block)
-struct IRBlock : IRValue
+struct IRReturn : IRTerminatorInst
+{};
+
+struct IRReturnVal : IRReturn
{
- // The function that contains this block
- IRFunc* parentFunc;
+ IRUse val;
+};
- // The first and last instruction in the block (or NULL in
- // the case that the block is empty).
+struct IRReturnVoid : IRReturn
+{};
+
+// A parent instruction contains a sequence of other instructions
+//
+struct IRParentInst : IRInst
+{
+ // The first and last instruction in the container (or NULL in
+ // the case that the container is empty).
//
+ IRInst* firstChild;
+ IRInst* lastChild;
+};
+
+// A basic block is a parent instruction that adds the constraint
+// that all the children need to be "ordinary" instructions (so
+// no function declarations, or nested blocks). We also expect
+// that the previous/next instruction are always a basic block.
+//
+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* first;
- IRInst* last;
-
- // Next and previous block in the same function
- IRBlock* nextBlock;
- IRBlock* prevBlock;
+ IRInst* firstChild;
+ IRInst* lastChild;
};
-// A function parameter.
-struct IRParam : IRValue
+// A function parameter is represented by an instruction
+// in the entry block of a function.
+struct IRParam : IRInst
{
- // The function that declared this parameter
- IRFunc* parentFunc;
-
- // The next and previous parameter of the function
- IRParam* nextParam;
- IRParam* prevParam;
-
};
-// A function, which consists of zero or more blocks of instructions.
+// A function is a parent to zero or more blocks of instructions.
//
// A function is itself a value, so that it can be a direct operand of
// an instruction (e.g., a call).
-struct IRFunc : IRValue
+struct IRFunc : IRParentInst
{
- // The IR module that defines this function
- IRModule* parentModule;
-
- // The unique entry block for the function is always the
- // first block in the list of blocks.
- IRBlock* firstBlock;
-
- // The last block in the function.
- IRBlock* lastBlock;
-
- // The parameters of the function
- IRParam* firstParam;
- IRParam* lastParam;
-
- // The next/previous function in the same IR module
- IRFunc* nextFunc;
- IRFunc* prevFunc;
};
-// A module defining global values
-struct IRModule
+// A module is a parent to functions, global variables, types, etc.
+struct IRModule : IRParentInst
{
-};
-
-typedef long long IRIntegerValue;
-typedef double IRFloatingPointValue;
+ // The designated entry-point function, if any
+ IRFunc* entryPoint;
+ // A special counter used to assign logical ids to instructions in this module.
+ UInt idCounter;
+};
struct IRBuilder
{
+ // The module that will own all of the IR
+ IRModule* module;
+
+ // The parent instruction to add children to.
+ IRParentInst* parentInst;
+
+ IRType* getBaseType(BaseType flavor);
IRType* getBoolType();
+ IRType* getVectorType(IRType* elementType, IRValue* elementCount);
+ IRType* getTypeType();
+ IRType* getVoidType();
+ IRType* getBlockType();
+ IRType* getStructType(
+ UInt fieldCount,
+ IRType* const* fieldTypes);
IRValue* getBoolValue(bool value);
IRValue* getIntValue(IRType* type, IRIntegerValue value);
IRValue* getFloatValue(IRType* type, IRFloatingPointValue value);
+
+ IRInst* emitIntrinsicInst(
+ IRType* type,
+ IntrinsicOp intrinsicOp,
+ UInt argCount,
+ IRValue* const* args);
+
+ IRInst* emitConstructorInst(
+ IRType* type,
+ UInt argCount,
+ IRValue* const* args);
+
+ IRModule* createModule();
+
+ IRFunc* createFunc();
+
+ IRBlock* createBlock();
+
+ IRParam* createParam(
+ IRType* type);
+
+ IRInst* createFieldExtract(
+ IRType* type,
+ IRValue* base,
+ UInt fieldIndex);
+
+ IRInst* createReturn(
+ IRValue* val);
+
+ IRInst* createReturn();
};
+void dumpIR(IRModule* module);
+
}
#endif