From 87c50675941a3ac853a79f50ec0ce3465631fa8f Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Tue, 15 Aug 2017 15:12:29 -0700 Subject: More work on IR With this change, basic generation of IR works for a trivial shader, and there is some basic support for dumping the generated IR in an assembly-like format. As with the other IR change, the use of the IR is statically disabled for now, so that existing users won't be affected. --- source/slang/emit.cpp | 110 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 87 insertions(+), 23 deletions(-) (limited to 'source/slang/emit.cpp') diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index 71ee31e5e..3bec17456 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -2,6 +2,7 @@ #include "emit.h" #include "lower.h" +#include "lower-to-ir.h" #include "name.h" #include "syntax.h" #include "type-layout.h" @@ -519,7 +520,7 @@ struct EmitVisitor emitRawText("\n#line "); char buffer[16]; - sprintf(buffer, "%d", sourceLocation.line); + sprintf(buffer, "%llu", (unsigned long long)sourceLocation.line); emitRawText(buffer); emitRawText(" "); @@ -679,7 +680,7 @@ struct EmitVisitor // and how we do. if(sourceLocation.column > context->shared->loc.column) { - int delta = sourceLocation.column - context->shared->loc.column; + Slang::Int delta = sourceLocation.column - context->shared->loc.column; for( int ii = 0; ii < delta; ++ii ) { emitRawText(" "); @@ -3756,7 +3757,7 @@ struct EmitVisitor void EmitDecl(RefPtr decl) { - emitDeclImpl(decl, nullptr); +emitDeclImpl(decl, nullptr); } void EmitDeclUsingLayout(RefPtr decl, RefPtr layout) @@ -3770,9 +3771,9 @@ struct EmitVisitor { EmitDecl(decl); } - else if(auto declGroup = declBase.As()) + else if( auto declGroup = declBase.As() ) { - for(auto d : declGroup->decls) + for( auto d : declGroup->decls ) EmitDecl(d); } else @@ -3805,7 +3806,7 @@ String emitEntryPoint( { globalStructLayout = gs.Ptr(); } - else if(auto globalConstantBufferLayout = globalScopeLayout.As()) + else if( auto globalConstantBufferLayout = globalScopeLayout.As() ) { // TODO: the `cbuffer` case really needs to be emitted very // carefully, but that is beyond the scope of what a simple rewriter @@ -3837,32 +3838,95 @@ String emitEntryPoint( } sharedContext.globalStructLayout = globalStructLayout; + auto translationUnitSyntax = translationUnit->SyntaxNode.Ptr(); + EmitContext context; context.shared = &sharedContext; EmitVisitor visitor(&context); - auto translationUnitSyntax = translationUnit->SyntaxNode.Ptr(); - - // We perform lowering of the program before emitting *anything*, - // because the lowering process might change how we emit some - // boilerplate at the start of the ouput for GLSL (e.g., what - // version we require). - auto lowered = lowerEntryPoint(entryPoint, programLayout, target, &sharedContext.extensionUsageTracker); - sharedContext.program = lowered.program; - - // Note that we emit the main body code of the program *before* - // we emit any leading preprocessor directives for GLSL. - // This is to give the emit logic a change to make last-minute - // adjustments like changing the required GLSL version. + // Depending on how the compiler was invoked, we may need to perform + // some amount of preocessing on the code before we can emit it. + // + // For our purposes, there are basically three different "modes" we + // care about: + // + // 1. "Full rewriter" mode, where the user provides HLSL/GLSL, and + // doesn't make use of any Slang code via `import`. + // + // 2. "Partial rewriter" mode, where the user starts with HLSL/GLSL, + // but also imports some Slang code, and may need us to rewrite + // their HLSL/GLSL function bodies to make things work. + // + // 3. "Full" mode, where all of the input code is in Slang (and/or + // the subset of HLSL we can fully type-check). // - // TODO: All such adjustments would be better handled during - // lowering, but that requires having a semantic rather than - // textual format for the HLSL->GLSL mapping. - visitor.EmitDeclsInContainer(lowered.program.Ptr()); + // We'll try to detect the cases here: + // +#if 0 + if(!(translationUnit->compileFlags & SLANG_COMPILE_FLAG_NO_CHECKING )) + { + // This seems to be case (3), because the user is asking for full + // checking, and so we can assume we understand the code fully. + // + // In this case we want to translate to our intermediate representation + // and do optimizations/transformations there before we emit final code. + // + + auto lowered = lowerEntryPointToIR(entryPoint, programLayout, target); + + dumpIR(lowered); + + throw 99; + + } + else if(translationUnit->compileRequest->loadedModulesList.Count() != 0) +#else + if(!(translationUnit->compileFlags & SLANG_COMPILE_FLAG_NO_CHECKING ) + || translationUnit->compileRequest->loadedModulesList.Count() != 0) +#endif + { + // The user has `import`ed some Slang modules, and so we are in case (2) + // + // We need to apply a "rewriting" pass to the code the user wrote, + // and then emit the result. + + // We perform lowering of the program before emitting *anything*, + // because the lowering process might change how we emit some + // boilerplate at the start of the ouput for GLSL (e.g., what + // version we require). + auto lowered = lowerEntryPoint(entryPoint, programLayout, target, &sharedContext.extensionUsageTracker); + sharedContext.program = lowered.program; + + // Note that we emit the main body code of the program *before* + // we emit any leading preprocessor directives for GLSL. + // This is to give the emit logic a change to make last-minute + // adjustments like changing the required GLSL version. + // + // TODO: All such adjustments would be better handled during + // lowering, but that requires having a semantic rather than + // textual format for the HLSL->GLSL mapping. + visitor.EmitDeclsInContainer(lowered.program.Ptr()); + } + else + { + // We are in case (1). + // + // We should be able to just emit the AST we parsed right back out, + // along with whatever annotations we added along the way. + + sharedContext.program = translationUnitSyntax; + visitor.EmitDeclsInContainer(translationUnitSyntax); + } + String code = sharedContext.sb.ProduceString(); sharedContext.sb.Clear(); + // Now that we've emitted the code for all the declaratiosn in the file, + // it is time to stich together the final output. + + + // There may be global-scope modifiers that we should emit now visitor.emitGLSLPreprocessorDirectives(translationUnitSyntax); String prefix = sharedContext.sb.ProduceString(); -- cgit v1.2.3 From e30ba2f6b7ad346fa5f2d435a9edc9ba1c56efab Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Wed, 16 Aug 2017 16:04:09 -0700 Subject: Fixups for IR checkpoint - The changes introduced a new path where we don't even go through the current "lowering" (really an AST-to-AST legalization pass), but this exposed a few issues I didn't anticipate: - First, we needed to make sure to pass in the computed layout information when emitting the original program (since the layout info is no longer automatically attached to AST nodes) - Second, we needed to take the sample-rate input checks that were being done in lowering before, and move them to the emit logic (which is really ugly, but I don't see a way around it for GLSL). --- source/slang/emit.cpp | 75 +++++++++++++++++++++++++++++++++++++++++++++++++- source/slang/lower.cpp | 39 -------------------------- 2 files changed, 74 insertions(+), 40 deletions(-) (limited to 'source/slang/emit.cpp') diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index 3bec17456..c8f3f06cb 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -48,6 +48,9 @@ struct SharedEmitContext // The entry point we are being asked to compile EntryPointRequest* entryPoint; + // The layout for the entry point + EntryPointLayout* entryPointLayout; + // The target language we want to generate code for CodeGenTarget target; @@ -2283,8 +2286,32 @@ struct EmitVisitor emitName(expr->lookupResult2.getName()); } + void setSampleRateFlag() + { + context->shared->entryPointLayout->flags |= EntryPointLayout::Flag::usesAnySampleRateInput; + } + + void doSampleRateInputCheck(VarDeclBase* decl) + { + if (decl->HasModifier()) + { + setSampleRateFlag(); + } + } + + void doSampleRateInputCheck(Name* name) + { + auto text = getText(name); + if (text == "gl_SampleID") + { + setSampleRateFlag(); + } + } + void visitVarExpr(VarExpr* varExpr, ExprEmitArg const& arg) { + doSampleRateInputCheck(varExpr->name); + auto prec = kEOp_Atomic; auto outerPrec = arg.outerPrec; bool needClose = MaybeEmitParens(outerPrec, kEOp_Atomic); @@ -2485,6 +2512,11 @@ struct EmitVisitor Emit("{\n"); for( auto& token : stmt->tokens ) { + if (token.type == TokenType::Identifier) + { + doSampleRateInputCheck(token.getName()); + } + emitTokenWithLocation(token); } Emit("}\n"); @@ -3560,6 +3592,15 @@ struct EmitVisitor void visitVarDeclBase(RefPtr decl, DeclEmitArg const& arg) { + // Global variable? Check if it is a sample-rate input. + if (dynamic_cast(decl->ParentDecl)) + { + if (decl->HasModifier()) + { + doSampleRateInputCheck(decl); + } + } + // Skip fields that have been tuple-ified and don't contribute // any fields of "ordinary" type. if (auto tupleFieldMod = decl->FindModifier()) @@ -3783,6 +3824,29 @@ emitDeclImpl(decl, nullptr); } }; + +EntryPointLayout* findEntryPointLayout( + ProgramLayout* programLayout, + EntryPointRequest* entryPointRequest) +{ + for( auto entryPointLayout : 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; +} + String emitEntryPoint( EntryPointRequest* entryPoint, ProgramLayout* programLayout, @@ -3795,6 +3859,13 @@ String emitEntryPoint( sharedContext.finalTarget = entryPoint->compileRequest->Target; sharedContext.entryPoint = entryPoint; + if (entryPoint) + { + sharedContext.entryPointLayout = findEntryPointLayout( + programLayout, + entryPoint); + } + sharedContext.programLayout = programLayout; // Layout information for the global scope is either an ordinary @@ -3916,7 +3987,9 @@ String emitEntryPoint( // along with whatever annotations we added along the way. sharedContext.program = translationUnitSyntax; - visitor.EmitDeclsInContainer(translationUnitSyntax); + visitor.EmitDeclsInContainerUsingLayout( + translationUnitSyntax, + globalStructLayout); } String code = sharedContext.sb.ProduceString(); diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp index 2c62a69a8..7a12fc3b7 100644 --- a/source/slang/lower.cpp +++ b/source/slang/lower.cpp @@ -886,8 +886,6 @@ struct LoweringVisitor LoweredExpr visitVarExpr( VarExpr* expr) { - doSampleRateInputCheck(expr->name); - // If the expression didn't get resolved, we can leave it as-is if (!expr->declRef) return expr; @@ -2206,14 +2204,6 @@ struct LoweringVisitor RefPtr loweredStmt = new UnparsedStmt(); lowerStmtFields(loweredStmt, stmt); - for (auto token : stmt->tokens) - { - if (token.type == TokenType::Identifier) - { - doSampleRateInputCheck(token.getName()); - } - } - loweredStmt->tokens = stmt->tokens; addStmt(loweredStmt); @@ -3369,28 +3359,6 @@ struct LoweringVisitor return SourceLanguage::Unknown; } - void setSampleRateFlag() - { - shared->entryPointLayout->flags |= EntryPointLayout::Flag::usesAnySampleRateInput; - } - - void doSampleRateInputCheck(VarDeclBase* decl) - { - if (decl->HasModifier()) - { - setSampleRateFlag(); - } - } - - void doSampleRateInputCheck(Name* name) - { - auto text = getText(name); - if (text == "gl_SampleIndex") - { - setSampleRateFlag(); - } - } - AggTypeDecl* isStructType(RefPtr type) { if (type->As()) return nullptr; @@ -3440,14 +3408,8 @@ struct LoweringVisitor LoweredDecl visitVariable( Variable* decl) { - // Global variable? Check if it is a sample-rate input. if (dynamic_cast(decl->ParentDecl)) { - if (decl->HasModifier()) - { - doSampleRateInputCheck(decl); - } - auto varLayout = tryToFindLayout(decl); if (varLayout) { @@ -3902,7 +3864,6 @@ struct LoweringVisitor } else if (ns == "sv_sampleindex") { - setSampleRateFlag(); globalVarExpr = createGLSLBuiltinRef("gl_SampleID", getIntType()); } else if (ns == "sv_stencilref") -- cgit v1.2.3