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.cpp227
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);
- }
-
}