diff options
Diffstat (limited to 'source/slang/compiler.cpp')
| -rw-r--r-- | source/slang/compiler.cpp | 227 |
1 files changed, 131 insertions, 96 deletions
diff --git a/source/slang/compiler.cpp b/source/slang/compiler.cpp index 6db04b900..9132624f9 100644 --- a/source/slang/compiler.cpp +++ b/source/slang/compiler.cpp @@ -32,6 +32,14 @@ namespace Slang { + + // EntryPointRequest + + TranslationUnitRequest* EntryPointRequest::getTranslationUnit() + { + return compileRequest->translationUnits[translationUnitIndex].Ptr(); + } + // Profile Profile::LookUp(char const* name) @@ -47,34 +55,91 @@ namespace Slang // - String EmitHLSL(ExtraContext& context) + String emitHLSLForTranslationUnit( + TranslationUnitRequest* translationUnit) { - if (context.getOptions().passThrough != PassThroughMode::None) + auto compileRequest = translationUnit->compileRequest; + if (compileRequest->passThrough != PassThroughMode::None) { - return context.sourceText; + // Generate a string that includes the content of + // the source file(s), along with a line directive + // to ensure that we get reasonable messages + // from the downstream compiler when in pass-through + // mode. + + StringBuilder codeBuilder; + for(auto sourceFile : translationUnit->sourceFiles) + { + codeBuilder << "#line 1 \""; + for(auto c : sourceFile->path) + { + char buffer[] = { c, 0 }; + switch(c) + { + default: + codeBuilder << buffer; + break; + + case '\\': + codeBuilder << "\\\\"; + } + } + codeBuilder << "\"\n"; + codeBuilder << sourceFile->content << "\n"; + } + + return codeBuilder.ProduceString(); } else { - // TODO(tfoley): probably need a way to customize the emit logic... return emitProgram( - context.programSyntax.Ptr(), - context.programLayout, + translationUnit->SyntaxNode.Ptr(), + compileRequest->layout.Ptr(), CodeGenTarget::HLSL); } } - String emitGLSLForEntryPoint(ExtraContext& context, EntryPointOption const& /*entryPoint*/) + String emitGLSLForEntryPoint( + EntryPointRequest* entryPoint) { - if (context.getOptions().passThrough != PassThroughMode::None) + auto compileRequest = entryPoint->compileRequest; + auto translationUnit = entryPoint->getTranslationUnit(); + + if (compileRequest->passThrough != PassThroughMode::None) { - return context.sourceText; + // Generate a string that includes the content of + // the source file(s), along with a line directive + // to ensure that we get reasonable messages + // from the downstream compiler when in pass-through + // mode. + + StringBuilder codeBuilder; + int translationUnitCounter = 0; + for(auto sourceFile : translationUnit->sourceFiles) + { + int translationUnitIndex = translationUnitCounter++; + + // We want to output `#line` directives, but we need + // to skip this for the first file, since otherwise + // some GLSL implementations will get tripped up by + // not having the `#version` directive be the first + // thing in the file. + if(translationUnitIndex != 0) + { + codeBuilder << "#line 1 " << translationUnitIndex << "\n"; + } + codeBuilder << sourceFile->content << "\n"; + } + + return codeBuilder.ProduceString(); } else { - // TODO(tfoley): probably need a way to customize the emit logic... + // TODO(tfoley): need to pass along the entry point + // so that we properly emit it as the `main` function. return emitProgram( - context.programSyntax.Ptr(), - context.programLayout, + translationUnit->SyntaxNode.Ptr(), + compileRequest->layout.Ptr(), CodeGenTarget::GLSL); } } @@ -103,8 +168,7 @@ namespace Slang } List<uint8_t> EmitDXBytecodeForEntryPoint( - ExtraContext& context, - EntryPointOption const& entryPoint) + EntryPointRequest* entryPoint) { static pD3DCompile D3DCompile_ = nullptr; if (!D3DCompile_) @@ -122,38 +186,20 @@ namespace Slang // // To work around that, we prepend a custom `#line` directive. - String rawHlslCode = EmitHLSL(context); + auto translationUnit = entryPoint->getTranslationUnit(); - StringBuilder hlslCodeBuilder; - hlslCodeBuilder << "#line 1 \""; - for(auto c : context.sourcePath) - { - char buffer[] = { c, 0 }; - switch(c) - { - default: - hlslCodeBuilder << buffer; - break; - - case '\\': - hlslCodeBuilder << "\\\\"; - } - } - hlslCodeBuilder << "\"\n"; - hlslCodeBuilder << rawHlslCode; - - auto hlslCode = hlslCodeBuilder.ProduceString(); + auto hlslCode = emitHLSLForTranslationUnit(translationUnit); ID3DBlob* codeBlob; ID3DBlob* diagnosticsBlob; HRESULT hr = D3DCompile_( hlslCode.begin(), hlslCode.Length(), - context.sourcePath.begin(), + "slang", nullptr, nullptr, - entryPoint.name.begin(), - GetHLSLProfileName(entryPoint.profile), + entryPoint->name.begin(), + GetHLSLProfileName(entryPoint->profile), 0, 0, &codeBlob, @@ -181,6 +227,7 @@ namespace Slang return data; } +#if 0 List<uint8_t> EmitDXBytecode( ExtraContext& context) { @@ -200,10 +247,10 @@ namespace Slang return EmitDXBytecodeForEntryPoint(context, context.getTranslationUnitOptions().entryPoints[0]); } +#endif String EmitDXBytecodeAssemblyForEntryPoint( - ExtraContext& context, - EntryPointOption const& entryPoint) + EntryPointRequest* entryPoint) { static pD3DDisassemble D3DDisassemble_ = nullptr; if (!D3DDisassemble_) @@ -215,7 +262,7 @@ namespace Slang assert(D3DDisassemble_); } - List<uint8_t> dxbc = EmitDXBytecodeForEntryPoint(context, entryPoint); + List<uint8_t> dxbc = EmitDXBytecodeForEntryPoint(entryPoint); if (!dxbc.Count()) { return ""; @@ -242,7 +289,7 @@ namespace Slang return result; } - +#if 0 String EmitDXBytecodeAssembly( ExtraContext& context) { @@ -260,6 +307,7 @@ namespace Slang } return sb.ProduceString(); } +#endif HMODULE getGLSLCompilerDLL() @@ -273,10 +321,9 @@ namespace Slang String emitSPIRVAssemblyForEntryPoint( - ExtraContext& context, - EntryPointOption const& entryPoint) + EntryPointRequest* entryPoint) { - String rawGLSL = emitGLSLForEntryPoint(context, entryPoint); + String rawGLSL = emitGLSLForEntryPoint(entryPoint); static glslang_CompileFunc glslang_compile = nullptr; if (!glslang_compile) @@ -297,9 +344,9 @@ namespace Slang }; glslang_CompileRequest request; - request.sourcePath = context.sourcePath.begin(); + request.sourcePath = "slang"; request.sourceText = rawGLSL.begin(); - request.slangStage = (SlangStage) entryPoint.profile.GetStage(); + request.slangStage = (SlangStage) entryPoint->profile.GetStage(); request.diagnosticFunc = outputFunc; request.diagnosticUserData = &diagnosticBuilder; @@ -323,6 +370,7 @@ namespace Slang } #endif +#if 0 String emitSPIRVAssembly( ExtraContext& context) { @@ -340,24 +388,28 @@ namespace Slang } return sb.ProduceString(); } +#endif // Do emit logic for a single entry point - EntryPointResult emitEntryPoint(ExtraContext& context, EntryPointOption& entryPoint) + EntryPointResult emitEntryPoint( + EntryPointRequest* entryPoint) { EntryPointResult result; - switch (context.getOptions().Target) + auto compileRequest = entryPoint->compileRequest; + + switch (compileRequest->Target) { case CodeGenTarget::GLSL: { - String code = emitGLSLForEntryPoint(context, entryPoint); + String code = emitGLSLForEntryPoint(entryPoint); result.outputSource = code; } break; case CodeGenTarget::DXBytecode: { - auto code = EmitDXBytecodeForEntryPoint(context, entryPoint); + auto code = EmitDXBytecodeForEntryPoint(entryPoint); // TODO(tfoley): Need to figure out an appropriate interface // for returning binary code, in addition to source. @@ -396,14 +448,14 @@ namespace Slang case CodeGenTarget::DXBytecodeAssembly: { - String code = EmitDXBytecodeAssemblyForEntryPoint(context, entryPoint); + String code = EmitDXBytecodeAssemblyForEntryPoint(entryPoint); result.outputSource = code; } break; case CodeGenTarget::SPIRVAssembly: { - String code = emitSPIRVAssemblyForEntryPoint(context, entryPoint); + String code = emitSPIRVAssemblyForEntryPoint(entryPoint); result.outputSource = code; } break; @@ -421,26 +473,28 @@ namespace Slang } - TranslationUnitResult emitTranslationUnitEntryPoints(ExtraContext& context) + TranslationUnitResult emitTranslationUnitEntryPoints( + TranslationUnitRequest* translationUnit) { TranslationUnitResult result; - for (auto& entryPoint : context.getTranslationUnitOptions().entryPoints) + for (auto& entryPoint : translationUnit->entryPoints) { - EntryPointResult entryPointResult = emitEntryPoint(context, entryPoint); + EntryPointResult entryPointResult = emitEntryPoint(entryPoint.Ptr()); - result.entryPoints.Add(entryPointResult); + entryPoint->result = entryPointResult; } // The result for the translation unit will just be the concatenation // of the results for each entry point. This doesn't actually make // much sense, but it is good enough for now. + // + // TODO: Replace this with a packaged JSON and/or binary format. StringBuilder sb; - for (auto& entryPointResult : result.entryPoints) + for (auto& entryPoint : translationUnit->entryPoints) { - sb << entryPointResult.outputSource; + sb << entryPoint->result.outputSource; } - result.outputSource = sb.ProduceString(); return result; @@ -448,26 +502,29 @@ namespace Slang // Do emit logic for an entire translation unit, which might // have zero or more entry points - TranslationUnitResult emitTranslationUnit(ExtraContext& context) + TranslationUnitResult emitTranslationUnit( + TranslationUnitRequest* translationUnit) { + auto compileRequest = translationUnit->compileRequest; + // Most of our code generation targets will require us // to proceed through one entry point at a time, but // in some cases we can emit an entire translation unit // in one go. - switch (context.getOptions().Target) + switch (compileRequest->Target) { default: // The default behavior is going to loop over all the entry // points, and then collect an aggregate result. - return emitTranslationUnitEntryPoints(context); + return emitTranslationUnitEntryPoints(translationUnit); case CodeGenTarget::HLSL: // When targetting HLSL, we can emit the entire translation unit // as a single HLSL program, and include all the entry points. { - String hlsl = EmitHLSL(context); + String hlsl = emitHLSLForTranslationUnit(translationUnit); TranslationUnitResult result; result.outputSource = hlsl; @@ -475,13 +532,12 @@ namespace Slang // Because the user might ask for per-entry-point source, // we will just attach the same string as the result for // each entry point. - for( auto& entryPoint : context.getTranslationUnitOptions().entryPoints ) + for( auto& entryPoint : translationUnit->entryPoints ) { - (void)entryPoint; - EntryPointResult entryPointResult; entryPointResult.outputSource = hlsl; - result.entryPoints.Add(entryPointResult); + + entryPoint->result = entryPointResult; } return result; @@ -490,36 +546,31 @@ namespace Slang } } +#if 0 TranslationUnitResult generateOutput(ExtraContext& context) { TranslationUnitResult result = emitTranslationUnit(context); return result; } +#endif void generateOutput( - ExtraContext& context, - CollectionOfTranslationUnits* collectionOfTranslationUnits) + CompileRequest* compileRequest) { - switch (context.getOptions().Target) + switch (compileRequest->Target) { default: // For most targets, we will do things per-translation-unit - for( auto translationUnit : collectionOfTranslationUnits->translationUnits ) + for( auto translationUnit : compileRequest->translationUnits ) { - ExtraContext innerContext = context; - innerContext.translationUnitOptions = &translationUnit.options; - innerContext.programSyntax = translationUnit.SyntaxNode; - innerContext.sourcePath = "slang"; // don't have this any more! - innerContext.sourceText = ""; - - TranslationUnitResult translationUnitResult = generateOutput(innerContext); - context.compileResult->translationUnits.Add(translationUnitResult); + TranslationUnitResult translationUnitResult = emitTranslationUnit(translationUnit.Ptr()); + translationUnit->result = translationUnitResult; } break; case CodeGenTarget::ReflectionJSON: { - String reflectionJSON = emitReflectionJSON(context.programLayout); + String reflectionJSON = emitReflectionJSON(compileRequest->layout.Ptr()); // HACK(tfoley): just print it out since that is what people probably expect. // TODO: need a way to control where output gets routed across all possible targets. @@ -528,20 +579,4 @@ namespace Slang break; } } - - TranslationUnitResult passThrough( - String const& sourceText, - String const& sourcePath, - const CompileOptions & options, - TranslationUnitOptions const& translationUnitOptions) - { - ExtraContext extra; - extra.options = &options; - extra.translationUnitOptions = &translationUnitOptions; - extra.sourcePath = sourcePath; - extra.sourceText = sourceText; - - return generateOutput(extra); - } - } |
