diff options
| author | Tim Foley <tfoleyNV@users.noreply.github.com> | 2017-08-15 12:51:14 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-08-15 12:51:14 -0700 |
| commit | 6de0a485e09c32cbd0bfead0fbdc5bb6f9aa7040 (patch) | |
| tree | b3f2bd89ffb324bbdc84e542ef42f8e9b3731c31 /source | |
| parent | e6abc6821a1bf13a9826e7db74362ce34ccaca2a (diff) | |
| parent | 831896f844453ba09c9e6cbfe7d29f6d44282632 (diff) | |
Merge pull request #165 from tfoleyNV/ir
Starting to add intermediate representation (IR)
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/ir.cpp | 29 | ||||
| -rw-r--r-- | source/slang/ir.h | 131 | ||||
| -rw-r--r-- | source/slang/lower-to-ir.cpp | 319 | ||||
| -rw-r--r-- | source/slang/lower-to-ir.h | 27 | ||||
| -rw-r--r-- | source/slang/slang.vcxproj | 4 | ||||
| -rw-r--r-- | source/slang/slang.vcxproj.filters | 4 | ||||
| -rw-r--r-- | source/slang/visitor.h | 12 |
7 files changed, 526 insertions, 0 deletions
diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp new file mode 100644 index 000000000..44eb7a727 --- /dev/null +++ b/source/slang/ir.cpp @@ -0,0 +1,29 @@ +// ir.cpp +#include "ir.h" + +#include "../core/basic.h" + +namespace Slang +{ + + IRType* IRBuilder::getBoolType() + { + SLANG_UNIMPLEMENTED_X("IR"); + } + + IRValue* IRBuilder::getBoolValue(bool value) + { + SLANG_UNIMPLEMENTED_X("IR"); + } + + IRValue* IRBuilder::getIntValue(IRType* type, IRIntegerValue value) + { + SLANG_UNIMPLEMENTED_X("IR"); + } + + IRValue* IRBuilder::getFloatValue(IRType* type, IRFloatingPointValue value) + { + SLANG_UNIMPLEMENTED_X("IR"); + } + +} diff --git a/source/slang/ir.h b/source/slang/ir.h new file mode 100644 index 000000000..db46235b3 --- /dev/null +++ b/source/slang/ir.h @@ -0,0 +1,131 @@ +// ir.h +#ifndef SLANG_IR_H_INCLUDED +#define SLANG_IR_H_INCLUDED + +// This file defines the intermediate representation (IR) used for Slang +// shader code. This is a typed static single assignment (SSA) IR, +// similar in spirit to LLVM (but much simpler). +// + +namespace Slang { + +struct IRBlock; +struct IRFunc; +struct IRModule; +struct IRType; + +// A value that can be referenced in the program. +struct IRValue +{ + // Type type of this value + IRType* type; +}; + +// 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 +// may take type operands as easily as values. +struct IRType : IRValue +{ +}; + +// An instruction in the program. +struct IRInst : IRValue +{ + // The basic block that contains this instruction, + // or NULL if the instruction currently has no parent. + IRBlock* parentBlock; + + // The next and previous instructions in the same parent block + IRInst* nextInst; + IRInst* prevInst; +}; + +// 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 +{ + // The function that contains this block + IRFunc* parentFunc; + + // The first and last instruction in the block (or NULL in + // the case that the block is empty). + // + // 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; +}; + +// A function parameter. +struct IRParam : IRValue +{ + // 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 itself a value, so that it can be a direct operand of +// an instruction (e.g., a call). +struct IRFunc : IRValue +{ + // 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 +{ +}; + +typedef long long IRIntegerValue; +typedef double IRFloatingPointValue; + + +struct IRBuilder +{ + IRType* getBoolType(); + + IRValue* getBoolValue(bool value); + IRValue* getIntValue(IRType* type, IRIntegerValue value); + IRValue* getFloatValue(IRType* type, IRFloatingPointValue value); +}; + +} + +#endif diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp new file mode 100644 index 000000000..bee3edb16 --- /dev/null +++ b/source/slang/lower-to-ir.cpp @@ -0,0 +1,319 @@ +// lower.cpp +#include "lower-to-ir.h" + +#include "ir.h" +#include "type-layout.h" +#include "visitor.h" + +namespace Slang +{ + +struct SharedIRGenContext +{ + EntryPointRequest* entryPoint; + ProgramLayout* programLayout; + CodeGenTarget target; +}; + +struct LoweredExprInfo +{ + enum class Flavor + { + Value, + }; + + static LoweredExprInfo createValue(IRValue* value) + { + LoweredExprInfo result; + result.flavor = Flavor::Value; + result.value = value; + return result; + } + + Flavor flavor; + union + { + IRValue* value; + }; +}; + +struct IRGenContext +{ + Dictionary<Decl*, LoweredExprInfo> declValues; + + IRBuilder* irBuilder; +}; + +struct LoweredValInfo +{ +}; + +struct LoweredTypeInfo +{ + enum class Flavor + { + Type, + }; + + union + { + IRType* type; + }; + Flavor flavor; +}; + +LoweredTypeInfo lowerType( + IRGenContext* context, + Type* type); + +static LoweredTypeInfo lowerType( + IRGenContext* context, + QualType const& type) +{ + return lowerType(context, type.type); +} + +LoweredExprInfo lowerExpr( + IRGenContext* context, + Expr* expr); + +// + +struct ValLoweringVisitor : ValVisitor<ValLoweringVisitor, LoweredValInfo, LoweredTypeInfo> +{ + IRGenContext* context; + + LoweredValInfo visitVal(Val* val) + { + SLANG_UNIMPLEMENTED_X("value lowering"); + } + + LoweredTypeInfo visitType(Type* type) + { + SLANG_UNIMPLEMENTED_X("type lowering"); + } + +}; + +LoweredTypeInfo lowerType( + IRGenContext* context, + Type* type) +{ + ValLoweringVisitor visitor; + visitor.context = context; + return visitor.dispatchType(type); +} + +#if 0 +struct LoweringVisitor + : ExprVisitor<LoweringVisitor, LoweredExpr> + , StmtVisitor<LoweringVisitor, void> + , DeclVisitor<LoweringVisitor, LoweredDecl> + , ValVisitor<LoweringVisitor, RefPtr<Val>, RefPtr<Type>> +#endif + + +// + +struct ExprLoweringVisitor : ExprVisitor<ExprLoweringVisitor, LoweredExprInfo> +{ + IRGenContext* context; + + LoweredExprInfo visitVarExpr(VarExpr* expr) + { + LoweredExprInfo info; + if(context->declValues.TryGetValue(expr->declRef.getDecl(), info)) + return info; + + throw 99; + + return LoweredExprInfo(); + } + + LoweredExprInfo visitOverloadedExpr(OverloadedExpr* expr) + { + SLANG_UNEXPECTED("overloaded expressions should not occur in checked AST"); + } + + LoweredExprInfo visitInitializerListExpr(InitializerListExpr* expr) + { + SLANG_UNIMPLEMENTED_X("codegen for initializer list expression"); + } + + IRType* getIRType(LoweredTypeInfo const& typeInfo) + { + switch( typeInfo.flavor ) + { + case LoweredTypeInfo::Flavor::Type: + return typeInfo.type; + } + } + + LoweredExprInfo visitConstantExpr(ConstantExpr* expr) + { + auto type = getIRType(lowerType(context, expr->type)); + + switch( expr->ConstType ) + { + case ConstantExpr::ConstantType::Bool: + return LoweredExprInfo::createValue(context->irBuilder->getBoolValue(expr->integerValue != 0)); + case ConstantExpr::ConstantType::Int: + return LoweredExprInfo::createValue(context->irBuilder->getIntValue(type, expr->integerValue)); + case ConstantExpr::ConstantType::Float: + return LoweredExprInfo::createValue(context->irBuilder->getFloatValue(type, expr->floatingPointValue)); + case ConstantExpr::ConstantType::String: + break; + } + + SLANG_UNEXPECTED("unexpected constant type"); + } + + LoweredExprInfo visitAggTypeCtorExpr(AggTypeCtorExpr* expr) + { + SLANG_UNIMPLEMENTED_X("codegen for aggregate type constructor expression"); + } + + LoweredExprInfo visitInvokeExpr(InvokeExpr* expr) + { + SLANG_UNIMPLEMENTED_X("codegen for invoke expression"); + } + + LoweredExprInfo visitIndexExpr(IndexExpr* expr) + { + SLANG_UNIMPLEMENTED_X("codegen for subscript expression"); + } + + LoweredExprInfo visitMemberExpr(MemberExpr* expr) + { + SLANG_UNIMPLEMENTED_X("codegen for subscript expression"); + } + + LoweredExprInfo visitSwizzleExpr(SwizzleExpr* expr) + { + SLANG_UNIMPLEMENTED_X("codegen for swizzle expression"); + } + + LoweredExprInfo visitDerefExpr(DerefExpr* expr) + { + SLANG_UNIMPLEMENTED_X("codegen for deref expression"); + } + + LoweredExprInfo visitTypeCastExpr(TypeCastExpr* expr) + { + SLANG_UNIMPLEMENTED_X("codegen for type cast expression"); + } + + LoweredExprInfo visitSelectExpr(SelectExpr* expr) + { + SLANG_UNIMPLEMENTED_X("codegen for select expression"); + } + + LoweredExprInfo visitGenericAppExpr(GenericAppExpr* expr) + { + SLANG_UNIMPLEMENTED_X("generic application expression during code generation"); + } + + LoweredExprInfo visitSharedTypeExpr(SharedTypeExpr* expr) + { + SLANG_UNIMPLEMENTED_X("shared type expression during code generation"); + } + + LoweredExprInfo visitAssignExpr(AssignExpr* expr) + { + SLANG_UNIMPLEMENTED_X("shared type expression during code generation"); + } + + LoweredExprInfo visitParenExpr(ParenExpr* expr) + { + return lowerExpr(context, expr->base); + } +}; + +LoweredExprInfo lowerExpr( + IRGenContext* context, + Expr* expr) +{ + ExprLoweringVisitor visitor; + visitor.context = context; + return visitor.dispatch(expr); +} + +struct LoweredDeclInfo +{}; + +struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredDeclInfo> +{ + IRGenContext* context; + + LoweredDeclInfo visitDeclBase(DeclBase* decl) + { + SLANG_UNIMPLEMENTED_X("decl catch-all"); + } + + LoweredDeclInfo visitDecl(Decl* decl) + { + SLANG_UNIMPLEMENTED_X("decl catch-all"); + } +}; + +LoweredDeclInfo lowerDecl( + IRGenContext* context, + Decl* decl) +{ + DeclLoweringVisitor visitor; + visitor.context = context; + return visitor.dispatch(decl); +} + +EntryPointLayout* findEntryPointLayout( + SharedIRGenContext* shared, + EntryPointRequest* entryPointRequest) +{ + for( auto entryPointLayout : shared->programLayout->entryPoints ) + { + if(entryPointLayout->entryPoint->getName() != entryPointRequest->name) + continue; + + if(entryPointLayout->profile != entryPointRequest->profile) + continue; + + // TODO: can't easily filter on translation unit here... + // Ideally the `EntryPointRequest` should get filled in with a pointer + // the specific function declaration that represents the entry point. + + return entryPointLayout.Ptr(); + } + + return nullptr; +} + +static void lowerEntryPointToIR( + IRGenContext* context, + EntryPointRequest* entryPointRequest, + EntryPointLayout* entryPointLayout) +{ + auto entryPointFunc = entryPointLayout->entryPoint; + + // TODO: entry point lowering is probably *not* just like lowering a function... + + lowerDecl(context, entryPointFunc); +} + +void lowerEntryPointToIR( + EntryPointRequest* entryPoint, + ProgramLayout* programLayout, + CodeGenTarget target) +{ + SharedIRGenContext sharedContextStorage; + SharedIRGenContext* sharedContext = &sharedContextStorage; + + IRGenContext contextStorage; + IRGenContext* context = &contextStorage; + + auto entryPointLayout = findEntryPointLayout(sharedContext, entryPoint); + + lowerEntryPointToIR(context, entryPoint, entryPointLayout); + +} + +} diff --git a/source/slang/lower-to-ir.h b/source/slang/lower-to-ir.h new file mode 100644 index 000000000..b8e0f1a67 --- /dev/null +++ b/source/slang/lower-to-ir.h @@ -0,0 +1,27 @@ +// lower.h +#ifndef SLANG_LOWER_TO_IR_H_INCLUDED +#define SLANG_LOWER_TO_IR_H_INCLUDED + +// The lowering step translates from a (type-checked) AST into +// our intermediate representation, to facilitate further +// optimization and transformation. + +#include "../core/basic.h" + +#include "compiler.h" +#include "ir.h" + +namespace Slang +{ + class EntryPointRequest; + class ProgramLayout; + class TranslationUnitRequest; + + struct ExtensionUsageTracker; + + void lowerEntryPointToIR( + EntryPointRequest* entryPoint, + ProgramLayout* programLayout, + CodeGenTarget target); +} +#endif diff --git a/source/slang/slang.vcxproj b/source/slang/slang.vcxproj index a212d96ec..94a6004e0 100644 --- a/source/slang/slang.vcxproj +++ b/source/slang/slang.vcxproj @@ -172,8 +172,10 @@ <ClInclude Include="emit.h" /> <ClInclude Include="expr-defs.h" /> <ClInclude Include="intrinsic-defs.h" /> + <ClInclude Include="ir.h" /> <ClInclude Include="lexer.h" /> <ClInclude Include="lookup.h" /> + <ClInclude Include="lower-to-ir.h" /> <ClInclude Include="modifier-defs.h" /> <ClInclude Include="name.h" /> <ClInclude Include="object-meta-begin.h" /> @@ -203,8 +205,10 @@ <ClCompile Include="compiler.cpp" /> <ClCompile Include="diagnostics.cpp" /> <ClCompile Include="emit.cpp" /> + <ClCompile Include="ir.cpp" /> <ClCompile Include="lexer.cpp" /> <ClCompile Include="lookup.cpp" /> + <ClCompile Include="lower-to-ir.cpp" /> <ClCompile Include="lower.cpp" /> <ClCompile Include="name.cpp" /> <ClCompile Include="options.cpp" /> diff --git a/source/slang/slang.vcxproj.filters b/source/slang/slang.vcxproj.filters index 2efbc8e30..14358e42e 100644 --- a/source/slang/slang.vcxproj.filters +++ b/source/slang/slang.vcxproj.filters @@ -37,6 +37,8 @@ <ClInclude Include="visitor.h" /> <ClInclude Include="lower.h" /> <ClInclude Include="name.h" /> + <ClInclude Include="ir.h" /> + <ClInclude Include="lower-to-ir.h" /> </ItemGroup> <ItemGroup> <ClCompile Include="check.cpp" /> @@ -59,5 +61,7 @@ <ClCompile Include="lower.cpp" /> <ClCompile Include="source-loc.cpp" /> <ClCompile Include="name.cpp" /> + <ClCompile Include="ir.cpp" /> + <ClCompile Include="lower-to-ir.cpp" /> </ItemGroup> </Project>
\ No newline at end of file diff --git a/source/slang/visitor.h b/source/slang/visitor.h index 59c5772f2..8a0301782 100644 --- a/source/slang/visitor.h +++ b/source/slang/visitor.h @@ -34,6 +34,13 @@ struct TypeVisitor : Base return result; } + Result dispatchType(Type* type) + { + Result result; + type->accept(this, &result); + return result; + } + #define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */ #define SYNTAX_CLASS(NAME, BASE) \ virtual void dispatch_##NAME(NAME* obj, void* extra) override \ @@ -61,6 +68,11 @@ struct TypeVisitor<Derived,void,Base> : Base type->accept(this, 0); } + void dispatchType(Type* type) + { + type->accept(this, 0); + } + #define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */ #define SYNTAX_CLASS(NAME, BASE) \ virtual void dispatch_##NAME(NAME* obj, void*) override \ |
