summaryrefslogtreecommitdiffstats
path: root/source/slang
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang')
-rw-r--r--source/slang/ir.cpp29
-rw-r--r--source/slang/ir.h131
-rw-r--r--source/slang/lower-to-ir.cpp319
-rw-r--r--source/slang/lower-to-ir.h27
-rw-r--r--source/slang/slang.vcxproj4
-rw-r--r--source/slang/slang.vcxproj.filters4
-rw-r--r--source/slang/visitor.h12
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 \