summaryrefslogtreecommitdiffstats
path: root/source/slang/compiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/compiler.cpp')
-rw-r--r--source/slang/compiler.cpp857
1 files changed, 376 insertions, 481 deletions
diff --git a/source/slang/compiler.cpp b/source/slang/compiler.cpp
index e78de9133..d02e5d10b 100644
--- a/source/slang/compiler.cpp
+++ b/source/slang/compiler.cpp
@@ -53,606 +53,501 @@ namespace Slang
//
- int compilerInstances = 0;
-
- class ShaderCompilerImpl : public ShaderCompiler
+ String EmitHLSL(ExtraContext& context)
{
- public:
-
- // Actual context for compilation... :(
- struct ExtraContext
+ if (context.getOptions().passThrough != PassThroughMode::None)
{
- CompileOptions const* options = nullptr;
- TranslationUnitOptions const* translationUnitOptions = nullptr;
-
- CompileResult* compileResult = nullptr;
-
- RefPtr<ProgramSyntaxNode> programSyntax;
- ProgramLayout* programLayout;
-
- String sourceText;
- String sourcePath;
-
- CompileOptions const& getOptions() { return *options; }
- TranslationUnitOptions const& getTranslationUnitOptions() { return *translationUnitOptions; }
- };
-
-
- String EmitHLSL(ExtraContext& context)
+ return context.sourceText;
+ }
+ else
{
- if (context.getOptions().passThrough != PassThroughMode::None)
- {
- return context.sourceText;
- }
- else
- {
- // TODO(tfoley): probably need a way to customize the emit logic...
- return emitProgram(
- context.programSyntax.Ptr(),
- context.programLayout,
- CodeGenTarget::HLSL);
- }
+ // TODO(tfoley): probably need a way to customize the emit logic...
+ return emitProgram(
+ context.programSyntax.Ptr(),
+ context.programLayout,
+ CodeGenTarget::HLSL);
}
+ }
- String emitGLSLForEntryPoint(ExtraContext& context, EntryPointOption const& entryPoint)
+ String emitGLSLForEntryPoint(ExtraContext& context, EntryPointOption const& /*entryPoint*/)
+ {
+ if (context.getOptions().passThrough != PassThroughMode::None)
{
- if (context.getOptions().passThrough != PassThroughMode::None)
- {
- return context.sourceText;
- }
- else
- {
- // TODO(tfoley): probably need a way to customize the emit logic...
- return emitProgram(
- context.programSyntax.Ptr(),
- context.programLayout,
- CodeGenTarget::GLSL);
- }
+ return context.sourceText;
}
+ else
+ {
+ // TODO(tfoley): probably need a way to customize the emit logic...
+ return emitProgram(
+ context.programSyntax.Ptr(),
+ context.programLayout,
+ CodeGenTarget::GLSL);
+ }
+ }
- char const* GetHLSLProfileName(Profile profile)
+ char const* GetHLSLProfileName(Profile profile)
+ {
+ switch(profile.raw)
{
- switch(profile.raw)
- {
- #define PROFILE(TAG, NAME, STAGE, VERSION) case Profile::TAG: return #NAME;
- #include "profile-defs.h"
+ #define PROFILE(TAG, NAME, STAGE, VERSION) case Profile::TAG: return #NAME;
+ #include "profile-defs.h"
- default:
- // TODO: emit an error here!
- return "unknown";
- }
+ default:
+ // TODO: emit an error here!
+ return "unknown";
}
+ }
#ifdef _WIN32
- void* GetD3DCompilerDLL()
- {
- // TODO(tfoley): let user specify version of d3dcompiler DLL to use.
- static HMODULE d3dCompiler = LoadLibraryA("d3dcompiler_47");
- // TODO(tfoley): handle case where we can't find it gracefully
- assert(d3dCompiler);
- return d3dCompiler;
- }
+ void* GetD3DCompilerDLL()
+ {
+ // TODO(tfoley): let user specify version of d3dcompiler DLL to use.
+ static HMODULE d3dCompiler = LoadLibraryA("d3dcompiler_47");
+ // TODO(tfoley): handle case where we can't find it gracefully
+ assert(d3dCompiler);
+ return d3dCompiler;
+ }
- List<uint8_t> EmitDXBytecodeForEntryPoint(
- ExtraContext& context,
- EntryPointOption const& entryPoint)
+ List<uint8_t> EmitDXBytecodeForEntryPoint(
+ ExtraContext& context,
+ EntryPointOption const& entryPoint)
+ {
+ static pD3DCompile D3DCompile_ = nullptr;
+ if (!D3DCompile_)
{
- static pD3DCompile D3DCompile_ = nullptr;
- if (!D3DCompile_)
- {
- HMODULE d3dCompiler = (HMODULE)GetD3DCompilerDLL();
- assert(d3dCompiler);
+ HMODULE d3dCompiler = (HMODULE)GetD3DCompilerDLL();
+ assert(d3dCompiler);
- D3DCompile_ = (pD3DCompile)GetProcAddress(d3dCompiler, "D3DCompile");
- assert(D3DCompile_);
- }
+ D3DCompile_ = (pD3DCompile)GetProcAddress(d3dCompiler, "D3DCompile");
+ assert(D3DCompile_);
+ }
- // The HLSL compiler will try to "canonicalize" our input file path,
- // and we don't want it to do that, because they it won't report
- // the same locations on error messages that we would.
- //
- // To work around that, we prepend a custom `#line` directive.
+ // The HLSL compiler will try to "canonicalize" our input file path,
+ // and we don't want it to do that, because they it won't report
+ // the same locations on error messages that we would.
+ //
+ // To work around that, we prepend a custom `#line` directive.
- String rawHlslCode = EmitHLSL(context);
+ String rawHlslCode = EmitHLSL(context);
- StringBuilder hlslCodeBuilder;
- hlslCodeBuilder << "#line 1 \"";
- for(auto c : context.sourcePath)
+ StringBuilder hlslCodeBuilder;
+ hlslCodeBuilder << "#line 1 \"";
+ for(auto c : context.sourcePath)
+ {
+ char buffer[] = { c, 0 };
+ switch(c)
{
- char buffer[] = { c, 0 };
- switch(c)
- {
- default:
- hlslCodeBuilder << buffer;
- break;
+ default:
+ hlslCodeBuilder << buffer;
+ break;
- case '\\':
- hlslCodeBuilder << "\\\\";
- }
+ case '\\':
+ hlslCodeBuilder << "\\\\";
}
- hlslCodeBuilder << "\"\n";
- hlslCodeBuilder << rawHlslCode;
-
- auto hlslCode = hlslCodeBuilder.ProduceString();
-
- ID3DBlob* codeBlob;
- ID3DBlob* diagnosticsBlob;
- HRESULT hr = D3DCompile_(
- hlslCode.begin(),
- hlslCode.Length(),
- context.sourcePath.begin(),
- nullptr,
- nullptr,
- entryPoint.name.begin(),
- GetHLSLProfileName(entryPoint.profile),
- 0,
- 0,
- &codeBlob,
- &diagnosticsBlob);
- List<uint8_t> data;
- if (codeBlob)
- {
- data.AddRange((uint8_t const*)codeBlob->GetBufferPointer(), (int)codeBlob->GetBufferSize());
- codeBlob->Release();
- }
- if (diagnosticsBlob)
+ }
+ hlslCodeBuilder << "\"\n";
+ hlslCodeBuilder << rawHlslCode;
+
+ auto hlslCode = hlslCodeBuilder.ProduceString();
+
+ ID3DBlob* codeBlob;
+ ID3DBlob* diagnosticsBlob;
+ HRESULT hr = D3DCompile_(
+ hlslCode.begin(),
+ hlslCode.Length(),
+ context.sourcePath.begin(),
+ nullptr,
+ nullptr,
+ entryPoint.name.begin(),
+ GetHLSLProfileName(entryPoint.profile),
+ 0,
+ 0,
+ &codeBlob,
+ &diagnosticsBlob);
+ List<uint8_t> data;
+ if (codeBlob)
+ {
+ data.AddRange((uint8_t const*)codeBlob->GetBufferPointer(), (int)codeBlob->GetBufferSize());
+ codeBlob->Release();
+ }
+ if (diagnosticsBlob)
+ {
+ // TODO(tfoley): need a better policy for how we translate diagnostics
+ // back into the Slang world (although we should always try to generate
+ // HLSL that doesn't produce any diagnostics...)
+ String diagnostics = (char const*) diagnosticsBlob->GetBufferPointer();
+ fprintf(stderr, "%s", diagnostics.begin());
+ OutputDebugStringA(diagnostics.begin());
+ diagnosticsBlob->Release();
+ }
+ if (FAILED(hr))
+ {
+ // TODO(tfoley): What to do on failure?
+ }
+ return data;
+ }
+
+ List<uint8_t> EmitDXBytecode(
+ ExtraContext& context)
+ {
+ if(context.getTranslationUnitOptions().entryPoints.Count() != 1)
+ {
+ if(context.getTranslationUnitOptions().entryPoints.Count() == 0)
{
- // TODO(tfoley): need a better policy for how we translate diagnostics
- // back into the Slang world (although we should always try to generate
- // HLSL that doesn't produce any diagnostics...)
- String diagnostics = (char const*) diagnosticsBlob->GetBufferPointer();
- fprintf(stderr, "%s", diagnostics.begin());
- OutputDebugStringA(diagnostics.begin());
- diagnosticsBlob->Release();
+ // TODO(tfoley): need to write diagnostics into this whole thing...
+ fprintf(stderr, "no entry point specified\n");
}
- if (FAILED(hr))
+ else
{
- // TODO(tfoley): What to do on failure?
+ fprintf(stderr, "multiple entry points specified\n");
}
- return data;
+ return List<uint8_t>();
}
- List<uint8_t> EmitDXBytecode(
- ExtraContext& context)
+ return EmitDXBytecodeForEntryPoint(context, context.getTranslationUnitOptions().entryPoints[0]);
+ }
+
+ String EmitDXBytecodeAssemblyForEntryPoint(
+ ExtraContext& context,
+ EntryPointOption const& entryPoint)
+ {
+ static pD3DDisassemble D3DDisassemble_ = nullptr;
+ if (!D3DDisassemble_)
{
- if(context.getTranslationUnitOptions().entryPoints.Count() != 1)
- {
- if(context.getTranslationUnitOptions().entryPoints.Count() == 0)
- {
- // TODO(tfoley): need to write diagnostics into this whole thing...
- fprintf(stderr, "no entry point specified\n");
- }
- else
- {
- fprintf(stderr, "multiple entry points specified\n");
- }
- return List<uint8_t>();
- }
+ HMODULE d3dCompiler = (HMODULE)GetD3DCompilerDLL();
+ assert(d3dCompiler);
- return EmitDXBytecodeForEntryPoint(context, context.getTranslationUnitOptions().entryPoints[0]);
+ D3DDisassemble_ = (pD3DDisassemble)GetProcAddress(d3dCompiler, "D3DDisassemble");
+ assert(D3DDisassemble_);
}
- String EmitDXBytecodeAssemblyForEntryPoint(
- ExtraContext& context,
- EntryPointOption const& entryPoint)
+ List<uint8_t> dxbc = EmitDXBytecodeForEntryPoint(context, entryPoint);
+ if (!dxbc.Count())
{
- static pD3DDisassemble D3DDisassemble_ = nullptr;
- if (!D3DDisassemble_)
- {
- HMODULE d3dCompiler = (HMODULE)GetD3DCompilerDLL();
- assert(d3dCompiler);
-
- D3DDisassemble_ = (pD3DDisassemble)GetProcAddress(d3dCompiler, "D3DDisassemble");
- assert(D3DDisassemble_);
- }
-
- List<uint8_t> dxbc = EmitDXBytecodeForEntryPoint(context, entryPoint);
- if (!dxbc.Count())
- {
- return "";
- }
+ return "";
+ }
- ID3DBlob* codeBlob;
- HRESULT hr = D3DDisassemble_(
- &dxbc[0],
- dxbc.Count(),
- 0,
- nullptr,
- &codeBlob);
+ ID3DBlob* codeBlob;
+ HRESULT hr = D3DDisassemble_(
+ &dxbc[0],
+ dxbc.Count(),
+ 0,
+ nullptr,
+ &codeBlob);
- String result;
- if (codeBlob)
- {
- result = String((char const*) codeBlob->GetBufferPointer());
- codeBlob->Release();
- }
- if (FAILED(hr))
- {
- // TODO(tfoley): need to figure out what to diagnose here...
- }
- return result;
+ String result;
+ if (codeBlob)
+ {
+ result = String((char const*) codeBlob->GetBufferPointer());
+ codeBlob->Release();
+ }
+ if (FAILED(hr))
+ {
+ // TODO(tfoley): need to figure out what to diagnose here...
}
+ return result;
+ }
- String EmitDXBytecodeAssembly(
- ExtraContext& context)
+ String EmitDXBytecodeAssembly(
+ ExtraContext& context)
+ {
+ if(context.getTranslationUnitOptions().entryPoints.Count() == 0)
{
- if(context.getTranslationUnitOptions().entryPoints.Count() == 0)
- {
- // TODO(tfoley): need to write diagnostics into this whole thing...
- fprintf(stderr, "no entry point specified\n");
- return "";
- }
-
- StringBuilder sb;
- for (auto entryPoint : context.getTranslationUnitOptions().entryPoints)
- {
- sb << EmitDXBytecodeAssemblyForEntryPoint(context, entryPoint);
- }
- return sb.ProduceString();
+ // TODO(tfoley): need to write diagnostics into this whole thing...
+ fprintf(stderr, "no entry point specified\n");
+ return "";
}
-
- HMODULE getGLSLCompilerDLL()
+ StringBuilder sb;
+ for (auto entryPoint : context.getTranslationUnitOptions().entryPoints)
{
- // TODO(tfoley): let user specify version of glslang DLL to use.
- static HMODULE glslCompiler = LoadLibraryA("glslang");
- // TODO(tfoley): handle case where we can't find it gracefully
- assert(glslCompiler);
- return glslCompiler;
+ sb << EmitDXBytecodeAssemblyForEntryPoint(context, entryPoint);
}
+ return sb.ProduceString();
+ }
- String emitSPIRVAssemblyForEntryPoint(
- ExtraContext& context,
- EntryPointOption const& entryPoint)
- {
- String rawGLSL = emitGLSLForEntryPoint(context, entryPoint);
+ HMODULE getGLSLCompilerDLL()
+ {
+ // TODO(tfoley): let user specify version of glslang DLL to use.
+ static HMODULE glslCompiler = LoadLibraryA("glslang");
+ // TODO(tfoley): handle case where we can't find it gracefully
+ assert(glslCompiler);
+ return glslCompiler;
+ }
- static glslang_CompileFunc glslang_compile = nullptr;
- if (!glslang_compile)
- {
- HMODULE glslCompiler = getGLSLCompilerDLL();
- assert(glslCompiler);
- glslang_compile = (glslang_CompileFunc)GetProcAddress(glslCompiler, "glslang_compile");
- assert(glslang_compile);
- }
+ String emitSPIRVAssemblyForEntryPoint(
+ ExtraContext& context,
+ EntryPointOption const& entryPoint)
+ {
+ String rawGLSL = emitGLSLForEntryPoint(context, entryPoint);
- StringBuilder diagnosticBuilder;
- StringBuilder outputBuilder;
+ static glslang_CompileFunc glslang_compile = nullptr;
+ if (!glslang_compile)
+ {
+ HMODULE glslCompiler = getGLSLCompilerDLL();
+ assert(glslCompiler);
- auto outputFunc = [](char const* text, void* userData)
- {
- *(StringBuilder*)userData << text;
- };
+ glslang_compile = (glslang_CompileFunc)GetProcAddress(glslCompiler, "glslang_compile");
+ assert(glslang_compile);
+ }
- glslang_CompileRequest request;
- request.sourcePath = context.sourcePath.begin();
- request.sourceText = rawGLSL.begin();
- request.slangStage = (SlangStage) entryPoint.profile.GetStage();
+ StringBuilder diagnosticBuilder;
+ StringBuilder outputBuilder;
- request.diagnosticFunc = outputFunc;
- request.diagnosticUserData = &diagnosticBuilder;
+ auto outputFunc = [](char const* text, void* userData)
+ {
+ *(StringBuilder*)userData << text;
+ };
- request.outputFunc = outputFunc;
- request.outputUserData = &outputBuilder;
+ glslang_CompileRequest request;
+ request.sourcePath = context.sourcePath.begin();
+ request.sourceText = rawGLSL.begin();
+ request.slangStage = (SlangStage) entryPoint.profile.GetStage();
- int err = glslang_compile(&request);
+ request.diagnosticFunc = outputFunc;
+ request.diagnosticUserData = &diagnosticBuilder;
- String diagnostics = diagnosticBuilder.ProduceString();
- String output = outputBuilder.ProduceString();
+ request.outputFunc = outputFunc;
+ request.outputUserData = &outputBuilder;
- if(err)
- {
- OutputDebugStringA(diagnostics.Buffer());
- fprintf(stderr, "%s", diagnostics.Buffer());
- exit(1);
- }
+ int err = glslang_compile(&request);
- return output;
+ String diagnostics = diagnosticBuilder.ProduceString();
+ String output = outputBuilder.ProduceString();
+
+ if(err)
+ {
+ OutputDebugStringA(diagnostics.Buffer());
+ fprintf(stderr, "%s", diagnostics.Buffer());
+ exit(1);
}
+
+ return output;
+ }
#endif
- String emitSPIRVAssembly(
- ExtraContext& context)
+ String emitSPIRVAssembly(
+ ExtraContext& context)
+ {
+ if(context.getTranslationUnitOptions().entryPoints.Count() == 0)
{
- if(context.getTranslationUnitOptions().entryPoints.Count() == 0)
- {
- // TODO(tfoley): need to write diagnostics into this whole thing...
- fprintf(stderr, "no entry point specified\n");
- return "";
- }
-
- StringBuilder sb;
- for (auto entryPoint : context.getTranslationUnitOptions().entryPoints)
- {
- sb << emitSPIRVAssemblyForEntryPoint(context, entryPoint);
- }
- return sb.ProduceString();
+ // TODO(tfoley): need to write diagnostics into this whole thing...
+ fprintf(stderr, "no entry point specified\n");
+ return "";
}
- // Do emit logic for a single entry point
- EntryPointResult emitEntryPoint(ExtraContext& context, EntryPointOption& entryPoint)
+ StringBuilder sb;
+ for (auto entryPoint : context.getTranslationUnitOptions().entryPoints)
{
- EntryPointResult result;
+ sb << emitSPIRVAssemblyForEntryPoint(context, entryPoint);
+ }
+ return sb.ProduceString();
+ }
- switch (context.getOptions().Target)
+ // Do emit logic for a single entry point
+ EntryPointResult emitEntryPoint(ExtraContext& context, EntryPointOption& entryPoint)
+ {
+ EntryPointResult result;
+
+ switch (context.getOptions().Target)
+ {
+ case CodeGenTarget::GLSL:
{
- case CodeGenTarget::GLSL:
- {
- String code = emitGLSLForEntryPoint(context, entryPoint);
- result.outputSource = code;
- }
- break;
+ String code = emitGLSLForEntryPoint(context, entryPoint);
+ result.outputSource = code;
+ }
+ break;
- case CodeGenTarget::DXBytecode:
- {
- auto code = EmitDXBytecodeForEntryPoint(context, entryPoint);
+ case CodeGenTarget::DXBytecode:
+ {
+ auto code = EmitDXBytecodeForEntryPoint(context, entryPoint);
- // TODO(tfoley): Need to figure out an appropriate interface
- // for returning binary code, in addition to source.
+ // TODO(tfoley): Need to figure out an appropriate interface
+ // for returning binary code, in addition to source.
#if 0
- if (context.compileResult)
- {
- StringBuilder sb;
- sb.Append((char*) code.begin(), code.Count());
+ if (context.compileResult)
+ {
+ StringBuilder sb;
+ sb.Append((char*) code.begin(), code.Count());
- String codeString = sb.ProduceString();
- result.outputSource = codeString;
- }
- else
+ String codeString = sb.ProduceString();
+ result.outputSource = codeString;
+ }
+ else
#endif
+ {
+ int col = 0;
+ for(auto ii : code)
{
- int col = 0;
- for(auto ii : code)
- {
- if(col != 0) fputs(" ", stdout);
- fprintf(stdout, "%02X", ii);
- col++;
- if(col == 8)
- {
- fputs("\n", stdout);
- col = 0;
- }
- }
- if(col != 0)
+ if(col != 0) fputs(" ", stdout);
+ fprintf(stdout, "%02X", ii);
+ col++;
+ if(col == 8)
{
fputs("\n", stdout);
+ col = 0;
}
}
- return result;
- }
- break;
-
- case CodeGenTarget::DXBytecodeAssembly:
- {
- String code = EmitDXBytecodeAssemblyForEntryPoint(context, entryPoint);
- result.outputSource = code;
- }
- break;
-
- case CodeGenTarget::SPIRVAssembly:
- {
- String code = emitSPIRVAssemblyForEntryPoint(context, entryPoint);
- result.outputSource = code;
+ if(col != 0)
+ {
+ fputs("\n", stdout);
+ }
}
- break;
-
- // Note(tfoley): We currently hit this case when compiling the stdlib
- case CodeGenTarget::Unknown:
- break;
-
- default:
- throw "unimplemented";
+ return result;
}
+ break;
- return result;
-
-
- }
-
- TranslationUnitResult emitTranslationUnitEntryPoints(ExtraContext& context)
- {
- TranslationUnitResult result;
-
- for (auto& entryPoint : context.getTranslationUnitOptions().entryPoints)
+ case CodeGenTarget::DXBytecodeAssembly:
{
- EntryPointResult entryPointResult = emitEntryPoint(context, entryPoint);
-
- result.entryPoints.Add(entryPointResult);
+ String code = EmitDXBytecodeAssemblyForEntryPoint(context, entryPoint);
+ result.outputSource = code;
}
+ break;
- // 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.
- StringBuilder sb;
- for (auto& entryPointResult : result.entryPoints)
+ case CodeGenTarget::SPIRVAssembly:
{
- sb << entryPointResult.outputSource;
+ String code = emitSPIRVAssemblyForEntryPoint(context, entryPoint);
+ result.outputSource = code;
}
+ break;
- result.outputSource = sb.ProduceString();
+ // Note(tfoley): We currently hit this case when compiling the stdlib
+ case CodeGenTarget::Unknown:
+ break;
- return result;
+ default:
+ throw "unimplemented";
}
- // Do emit logic for an entire translation unit, which might
- // have zero or more entry points
- TranslationUnitResult emitTranslationUnit(ExtraContext& context)
- {
- // 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.
+ return result;
- switch (context.getOptions().Target)
- {
- default:
- // The default behavior is going to loop over all the entry
- // points, and then collect an aggregate result.
- return emitTranslationUnitEntryPoints(context);
- 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);
-
- TranslationUnitResult result;
- result.outputSource = hlsl;
+ }
- // 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 )
- {
- (void)entryPoint;
+ TranslationUnitResult emitTranslationUnitEntryPoints(ExtraContext& context)
+ {
+ TranslationUnitResult result;
- EntryPointResult entryPointResult;
- entryPointResult.outputSource = hlsl;
- result.entryPoints.Add(entryPointResult);
- }
+ for (auto& entryPoint : context.getTranslationUnitOptions().entryPoints)
+ {
+ EntryPointResult entryPointResult = emitEntryPoint(context, entryPoint);
- return result;
- }
- break;
- }
+ result.entryPoints.Add(entryPointResult);
}
- TranslationUnitResult DoNewEmitLogic(ExtraContext& context)
+ // 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.
+ StringBuilder sb;
+ for (auto& entryPointResult : result.entryPoints)
{
- TranslationUnitResult result = emitTranslationUnit(context);
-
- // As a bit of a hack, we include a mode where we just
- // print things to standard output, so that we can see them
- //
- // TODO(tfoley): Is this path ever needed/used?
- if( !context.compileResult )
- {
- fprintf(stdout, "%s", result.outputSource.Buffer());
- }
-
- return result;
+ sb << entryPointResult.outputSource;
}
- void DoNewEmitLogic(
- ExtraContext& context,
- CollectionOfTranslationUnits* collectionOfTranslationUnits)
- {
- switch (context.getOptions().Target)
- {
- default:
- // For most targets, we will do things per-translation-unit
- for( auto translationUnit : collectionOfTranslationUnits->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 = DoNewEmitLogic(innerContext);
- context.compileResult->translationUnits.Add(translationUnitResult);
- }
- break;
+ result.outputSource = sb.ProduceString();
- case CodeGenTarget::ReflectionJSON:
- {
- String reflectionJSON = emitReflectionJSON(context.programLayout);
+ return result;
+ }
- // 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.
- fprintf(stdout, "%s", reflectionJSON.begin());
- }
- break;
- }
- }
+ // Do emit logic for an entire translation unit, which might
+ // have zero or more entry points
+ TranslationUnitResult emitTranslationUnit(ExtraContext& context)
+ {
+ // 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.
- virtual void Compile(
- CompileResult& result,
- CollectionOfTranslationUnits* collectionOfTranslationUnits,
- const CompileOptions& options) override
+ switch (context.getOptions().Target)
{
- RefPtr<SyntaxVisitor> visitor = CreateSemanticsVisitor(result.GetErrorWriter(), options);
- try
+ default:
+ // The default behavior is going to loop over all the entry
+ // points, and then collect an aggregate result.
+ return emitTranslationUnitEntryPoints(context);
+
+ case CodeGenTarget::HLSL:
+ // When targetting HLSL, we can emit the entire translation unit
+ // as a single HLSL program, and include all the entry points.
{
- for( auto& translationUnit : collectionOfTranslationUnits->translationUnits )
- {
- visitor->setSourceLanguage(translationUnit.options.sourceLanguage);
- translationUnit.SyntaxNode->Accept(visitor.Ptr());
- }
- if (result.GetErrorCount() > 0)
- return;
+ String hlsl = EmitHLSL(context);
- // Do binding generation, and then reflection (globally)
- // before we move on to any code-generation activites.
- GenerateParameterBindings(collectionOfTranslationUnits);
+ TranslationUnitResult result;
+ result.outputSource = hlsl;
+ // 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 )
+ {
+ (void)entryPoint;
- // HACK(tfoley): for right now I just want to pretty-print an AST
- // into another language, so the whole compiler back-end is just
- // getting in the way.
- //
- // I'm going to bypass it for now and see what I can do:
+ EntryPointResult entryPointResult;
+ entryPointResult.outputSource = hlsl;
+ result.entryPoints.Add(entryPointResult);
+ }
- ExtraContext extra;
- extra.options = &options;
- extra.programLayout = collectionOfTranslationUnits->layout.Ptr();
- extra.compileResult = &result;
- DoNewEmitLogic(extra, collectionOfTranslationUnits);
- }
- catch (int)
- {
+ return result;
}
- catch (...)
- {
- throw;
- }
- return;
+ break;
}
+ }
- ShaderCompilerImpl()
- {
- if (compilerInstances == 0)
- {
- BasicExpressionType::Init();
- }
- compilerInstances++;
- }
+ TranslationUnitResult generateOutput(ExtraContext& context)
+ {
+ TranslationUnitResult result = emitTranslationUnit(context);
+ return result;
+ }
- ~ShaderCompilerImpl()
+ void generateOutput(
+ ExtraContext& context,
+ CollectionOfTranslationUnits* collectionOfTranslationUnits)
+ {
+ switch (context.getOptions().Target)
{
- compilerInstances--;
- if (compilerInstances == 0)
+ default:
+ // For most targets, we will do things per-translation-unit
+ for( auto translationUnit : collectionOfTranslationUnits->translationUnits )
{
- BasicExpressionType::Finalize();
- SlangStdLib::Finalize();
+ 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);
}
- }
+ break;
- virtual TranslationUnitResult PassThrough(
- String const& sourceText,
- String const& sourcePath,
- const CompileOptions & options,
- TranslationUnitOptions const& translationUnitOptions) override
- {
- ExtraContext extra;
- extra.options = &options;
- extra.translationUnitOptions = &translationUnitOptions;
- extra.sourcePath = sourcePath;
- extra.sourceText = sourceText;
+ case CodeGenTarget::ReflectionJSON:
+ {
+ String reflectionJSON = emitReflectionJSON(context.programLayout);
- return DoNewEmitLogic(extra);
+ // 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.
+ fprintf(stdout, "%s", reflectionJSON.begin());
+ }
+ break;
}
+ }
- };
-
- ShaderCompiler * CreateShaderCompiler()
+ TranslationUnitResult passThrough(
+ String const& sourceText,
+ String const& sourcePath,
+ const CompileOptions & options,
+ TranslationUnitOptions const& translationUnitOptions)
{
- return new ShaderCompilerImpl();
+ ExtraContext extra;
+ extra.options = &options;
+ extra.translationUnitOptions = &translationUnitOptions;
+ extra.sourcePath = sourcePath;
+ extra.sourceText = sourceText;
+
+ return generateOutput(extra);
}
}