summaryrefslogtreecommitdiffstats
path: root/source/slang/compiler.cpp
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2017-10-16 13:12:11 -0700
committerGitHub <noreply@github.com>2017-10-16 13:12:11 -0700
commitf12c2552b3f494cbc8245edb90b32b93ca8a1539 (patch)
tree4cd08ad6037067dc70844a4a847fb3228e0176ee /source/slang/compiler.cpp
parent3e3e2473bf85365593629bd1f6f070d11f0b8ab2 (diff)
Implement notion of a "container format" (#213)
The big addition here is that the Slang "bytecode" is no longer treated as just a "code generation target" (`CodeGenTarget`) akin to DX bytecode (DXBC) or SPIR-V, but instead is a `ContainerFormat` that can be used to emit all the results of a compile request (well, currently just the IR-as-BC, but the intention is there). Getting to this goal involved some prior checkins that eliminated bogus "targets" that weren't really akin to SPIR-V or DXBC: `-target slang-ir-asm` and `-target reflection-json`. Those targets were really in place to support testing, and so they've been made more explicit testing/debug options. This change eliminates `-target slang-ir` and instead tries to allow the user to specify `-o foo.slang-module` as an output file name, that indicates the intention to output a "container" file that will wrap up all the generated code. I've also gone ahead and generalized the existing `-target` option so that we are actually building up a *list* of code generation targets. This is largely just a cleanup, since it forces code to be more aware of when it is doing something target-specific vs. target independent. For example, reflection layout information lives on a requested target, and not on the compile request as a whole, and similarly output code is per-target, per-entry-point. As a cleanup, I eliminated support for per-translation-unit output. This was vestigial code from back when I used to try and do HLSL generation for a whole translation unit instead of per-entry-point (which turned out to be a lot of complexity for little gain), and it was only being used in the `hello` example and the `render-test` test fixture - in both cases fixing it up was easy enough. I've stubbed out the old `spGetTranslationUnitSource` API, but haven't removed it yet.
Diffstat (limited to 'source/slang/compiler.cpp')
-rw-r--r--source/slang/compiler.cpp207
1 files changed, 99 insertions, 108 deletions
diff --git a/source/slang/compiler.cpp b/source/slang/compiler.cpp
index 10755370a..8cf801a79 100644
--- a/source/slang/compiler.cpp
+++ b/source/slang/compiler.cpp
@@ -3,8 +3,10 @@
#include "../core/basic.h"
#include "../core/platform.h"
#include "../core/slang-io.h"
+#include "bytecode.h"
#include "compiler.h"
#include "lexer.h"
+#include "lower-to-ir.h"
#include "parameter-binding.h"
#include "parser.h"
#include "preprocessor.h"
@@ -110,7 +112,8 @@ namespace Slang
//
String emitHLSLForEntryPoint(
- EntryPointRequest* entryPoint)
+ EntryPointRequest* entryPoint,
+ TargetRequest* targetReq)
{
auto compileRequest = entryPoint->compileRequest;
auto translationUnit = entryPoint->getTranslationUnit();
@@ -149,13 +152,15 @@ namespace Slang
{
return emitEntryPoint(
entryPoint,
- compileRequest->layout.Ptr(),
- CodeGenTarget::HLSL);
+ targetReq->layout.Ptr(),
+ CodeGenTarget::HLSL,
+ targetReq->target);
}
}
String emitGLSLForEntryPoint(
- EntryPointRequest* entryPoint)
+ EntryPointRequest* entryPoint,
+ TargetRequest* targetReq)
{
auto compileRequest = entryPoint->compileRequest;
auto translationUnit = entryPoint->getTranslationUnit();
@@ -194,8 +199,9 @@ namespace Slang
// so that we properly emit it as the `main` function.
return emitEntryPoint(
entryPoint,
- compileRequest->layout.Ptr(),
- CodeGenTarget::GLSL);
+ targetReq->layout.Ptr(),
+ CodeGenTarget::GLSL,
+ targetReq->target);
}
}
@@ -232,7 +238,8 @@ namespace Slang
}
List<uint8_t> EmitDXBytecodeForEntryPoint(
- EntryPointRequest* entryPoint)
+ EntryPointRequest* entryPoint,
+ TargetRequest* targetReq)
{
static pD3DCompile D3DCompile_ = nullptr;
if (!D3DCompile_)
@@ -246,7 +253,7 @@ namespace Slang
return List<uint8_t>();
}
- auto hlslCode = emitHLSLForEntryPoint(entryPoint);
+ auto hlslCode = emitHLSLForEntryPoint(entryPoint, targetReq);
maybeDumpIntermediate(entryPoint->compileRequest, hlslCode.Buffer(), CodeGenTarget::HLSL);
ID3DBlob* codeBlob;
@@ -333,10 +340,11 @@ namespace Slang
}
String EmitDXBytecodeAssemblyForEntryPoint(
- EntryPointRequest* entryPoint)
+ EntryPointRequest* entryPoint,
+ TargetRequest* targetReq)
{
- List<uint8_t> dxbc = EmitDXBytecodeForEntryPoint(entryPoint);
+ List<uint8_t> dxbc = EmitDXBytecodeForEntryPoint(entryPoint, targetReq);
if (!dxbc.Count())
{
return String();
@@ -440,9 +448,10 @@ namespace Slang
}
List<uint8_t> emitSPIRVForEntryPoint(
- EntryPointRequest* entryPoint)
+ EntryPointRequest* entryPoint,
+ TargetRequest* targetReq)
{
- String rawGLSL = emitGLSLForEntryPoint(entryPoint);
+ String rawGLSL = emitGLSLForEntryPoint(entryPoint, targetReq);
maybeDumpIntermediate(entryPoint->compileRequest, rawGLSL.Buffer(), CodeGenTarget::GLSL);
List<uint8_t> output;
@@ -473,9 +482,10 @@ namespace Slang
}
String emitSPIRVAssemblyForEntryPoint(
- EntryPointRequest* entryPoint)
+ EntryPointRequest* entryPoint,
+ TargetRequest* targetReq)
{
- List<uint8_t> spirv = emitSPIRVForEntryPoint(entryPoint);
+ List<uint8_t> spirv = emitSPIRVForEntryPoint(entryPoint, targetReq);
if (spirv.Count() == 0)
return String();
@@ -484,26 +494,21 @@ namespace Slang
}
#endif
- List<uint8_t> emitSlangIRForEntryPoint(
- EntryPointRequest* entryPoint);
-
- String emitSlangIRAssemblyForEntryPoint(
- EntryPointRequest* entryPoint);
-
// Do emit logic for a single entry point
CompileResult emitEntryPoint(
- EntryPointRequest* entryPoint)
+ EntryPointRequest* entryPoint,
+ TargetRequest* targetReq)
{
CompileResult result;
auto compileRequest = entryPoint->compileRequest;
- auto target = compileRequest->Target;
+ auto target = targetReq->target;
switch (target)
{
case CodeGenTarget::HLSL:
{
- String code = emitHLSLForEntryPoint(entryPoint);
+ String code = emitHLSLForEntryPoint(entryPoint, targetReq);
maybeDumpIntermediate(compileRequest, code.Buffer(), target);
result = CompileResult(code);
}
@@ -511,7 +516,7 @@ namespace Slang
case CodeGenTarget::GLSL:
{
- String code = emitGLSLForEntryPoint(entryPoint);
+ String code = emitGLSLForEntryPoint(entryPoint, targetReq);
maybeDumpIntermediate(compileRequest, code.Buffer(), target);
result = CompileResult(code);
}
@@ -520,7 +525,7 @@ namespace Slang
#if SLANG_ENABLE_DXBC_SUPPORT
case CodeGenTarget::DXBytecode:
{
- List<uint8_t> code = EmitDXBytecodeForEntryPoint(entryPoint);
+ List<uint8_t> code = EmitDXBytecodeForEntryPoint(entryPoint, targetReq);
maybeDumpIntermediate(compileRequest, code.Buffer(), code.Count(), target);
result = CompileResult(code);
}
@@ -528,7 +533,7 @@ namespace Slang
case CodeGenTarget::DXBytecodeAssembly:
{
- String code = EmitDXBytecodeAssemblyForEntryPoint(entryPoint);
+ String code = EmitDXBytecodeAssemblyForEntryPoint(entryPoint, targetReq);
maybeDumpIntermediate(compileRequest, code.Buffer(), target);
result = CompileResult(code);
}
@@ -537,7 +542,7 @@ namespace Slang
case CodeGenTarget::SPIRV:
{
- List<uint8_t> code = emitSPIRVForEntryPoint(entryPoint);
+ List<uint8_t> code = emitSPIRVForEntryPoint(entryPoint, targetReq);
maybeDumpIntermediate(compileRequest, code.Buffer(), code.Count(), target);
result = CompileResult(code);
}
@@ -545,29 +550,11 @@ namespace Slang
case CodeGenTarget::SPIRVAssembly:
{
- String code = emitSPIRVAssemblyForEntryPoint(entryPoint);
- maybeDumpIntermediate(compileRequest, code.Buffer(), target);
- result = CompileResult(code);
- }
- break;
-
- case CodeGenTarget::SlangIR:
- {
- List<uint8_t> code = emitSlangIRForEntryPoint(entryPoint);
- maybeDumpIntermediate(compileRequest, code.Buffer(), code.Count(), target);
- result = CompileResult(code);
- }
- break;
-
-#if 0
- case CodeGenTarget::SlangIRAssembly:
- {
- String code = emitSlangIRAssemblyForEntryPoint(entryPoint);
+ String code = emitSPIRVAssemblyForEntryPoint(entryPoint, targetReq);
maybeDumpIntermediate(compileRequest, code.Buffer(), target);
result = CompileResult(code);
}
break;
-#endif
case CodeGenTarget::None:
// The user requested no output
@@ -632,11 +619,13 @@ namespace Slang
}
static void writeEntryPointResultToFile(
- EntryPointRequest* entryPoint)
+ EntryPointRequest* entryPoint,
+ TargetRequest* targetReq,
+ UInt entryPointIndex)
{
auto compileRequest = entryPoint->compileRequest;
auto outputPath = entryPoint->outputPath;
- auto result = entryPoint->result;
+ auto result = targetReq->entryPointResults[entryPointIndex];
switch (result.format)
{
case ResultFormat::Text:
@@ -680,10 +669,12 @@ namespace Slang
}
static void writeEntryPointResultToStandardOutput(
- EntryPointRequest* entryPoint)
+ EntryPointRequest* entryPoint,
+ TargetRequest* targetReq,
+ UInt entryPointIndex)
{
auto compileRequest = entryPoint->compileRequest;
- auto result = entryPoint->result;
+ auto& result = targetReq->entryPointResults[entryPointIndex];
switch (result.format)
{
@@ -699,7 +690,7 @@ namespace Slang
{
// Writing to console, so we need to generate text output.
- switch (compileRequest->Target)
+ switch (targetReq->target)
{
#if SLANG_ENABLE_DXBC_SUPPORT
case CodeGenTarget::DXBytecode:
@@ -750,88 +741,97 @@ namespace Slang
}
static void writeEntryPointResult(
- EntryPointRequest* entryPoint)
+ EntryPointRequest* entryPoint,
+ TargetRequest* targetReq,
+ UInt entryPointIndex)
{
+ auto& result = targetReq->entryPointResults[entryPointIndex];
+
// Skip the case with no output
- if (entryPoint->result.format == ResultFormat::None)
+ if (result.format == ResultFormat::None)
return;
if (entryPoint->outputPath.Length())
{
- writeEntryPointResultToFile(entryPoint);
+ writeEntryPointResultToFile(entryPoint, targetReq, entryPointIndex);
}
else
{
- writeEntryPointResultToStandardOutput(entryPoint);
+ writeEntryPointResultToStandardOutput(entryPoint, targetReq, entryPointIndex);
}
}
- CompileResult emitTranslationUnitEntryPoints(
- TranslationUnitRequest* translationUnit)
+ void emitEntryPoints(
+ TargetRequest* targetReq)
{
- CompileResult result;
-
- for (auto& entryPoint : translationUnit->entryPoints)
- {
- CompileResult entryPointResult = emitEntryPoint(entryPoint.Ptr());
-
- entryPoint->result = entryPointResult;
- }
+ CompileRequest* compileReq = targetReq->compileRequest;
- // 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.
- for (auto& entryPoint : translationUnit->entryPoints)
- {
- result.append(entryPoint->result);
- }
-
- return result;
}
- // Do emit logic for an entire translation unit, which might
- // have zero or more entry points
- CompileResult emitTranslationUnit(
- TranslationUnitRequest* translationUnit)
+ void generateOutputForTarget(
+ TargetRequest* targetReq)
{
- return emitTranslationUnitEntryPoints(translationUnit);
- }
+ CompileRequest* compileReq = targetReq->compileRequest;
-#if 0
- TranslationUnitResult generateOutput(ExtraContext& context)
- {
- TranslationUnitResult result = emitTranslationUnit(context);
- return result;
+ // Generate target code any entry points that
+ // have been requested for compilation.
+ for (auto& entryPoint : compileReq->entryPoints)
+ {
+ CompileResult entryPointResult = emitEntryPoint(entryPoint, targetReq);
+ targetReq->entryPointResults.Add(entryPointResult);
+ }
}
-#endif
void generateOutput(
CompileRequest* compileRequest)
{
- // Start of with per-translation-unit and per-entry-point lowering
- for( auto translationUnit : compileRequest->translationUnits )
+ // Go through the code-generation targets that the user
+ // has specified, and generate code for each of them.
+ //
+ for (auto targetReq : compileRequest->targets)
{
- CompileResult translationUnitResult = emitTranslationUnit(translationUnit.Ptr());
- translationUnit->result = translationUnitResult;
+ generateOutputForTarget(targetReq);
+ }
+
+ // If we are being asked to generate code in a container
+ // format, then we are now in a position to do so.
+ switch (compileRequest->containerFormat)
+ {
+ default:
+ break;
+
+ case ContainerFormat::SlangModule:
+ generateBytecodeForCompileRequest(compileRequest);
+ break;
}
// If we are in command-line mode, we might be expected to actually
// write output to one or more files here.
- // But don't write any output if we were told to skip it.
- if (compileRequest->shouldSkipCodegen)
- return;
-
if (compileRequest->isCommandLineCompile)
{
- for( auto entryPoint : compileRequest->entryPoints )
+ for (auto targetReq : compileRequest->targets)
{
- writeEntryPointResult(entryPoint);
+ UInt entryPointCount = compileRequest->entryPoints.Count();
+ for (UInt ee = 0; ee < entryPointCount; ++ee)
+ {
+ writeEntryPointResult(
+ compileRequest->entryPoints[ee],
+ targetReq,
+ ee);
+ }
}
- }
+ if (compileRequest->containerOutputPath.Length() != 0)
+ {
+ auto& data = compileRequest->generatedBytecode;
+ writeOutputFile(compileRequest,
+ compileRequest->containerOutputPath,
+ data.begin(),
+ data.end() - data.begin(),
+ OutputFileKind::Binary);
+ }
+ }
}
// Debug logic for dumping intermediate outputs
@@ -943,15 +943,6 @@ namespace Slang
}
break;
#endif
-
- case CodeGenTarget::SlangIR:
- dumpIntermediateBinary(compileRequest, data, size, ".slang-ir");
- {
- // TODO: need to support dissassembly from Slang IR binary
-// String slangIRAssembly = dissassembleSlangIR(compileRequest, data, size);
-// dumpIntermediateText(compileRequest, slangIRAssembly.begin(), slangIRAssembly.Length(), ".slang-ir.asm");
- }
- break;
}
}