diff options
| -rw-r--r-- | examples/hello/hello.cpp | 4 | ||||
| -rw-r--r-- | slang.h | 3 | ||||
| -rw-r--r-- | source/slang/check.cpp | 29 | ||||
| -rw-r--r-- | source/slang/compiled-program.h | 36 | ||||
| -rw-r--r-- | source/slang/compiler.cpp | 227 | ||||
| -rw-r--r-- | source/slang/compiler.h | 172 | ||||
| -rw-r--r-- | source/slang/options.cpp | 2 | ||||
| -rw-r--r-- | source/slang/parameter-binding.cpp | 40 | ||||
| -rw-r--r-- | source/slang/parameter-binding.h | 6 | ||||
| -rw-r--r-- | source/slang/parser.cpp | 22 | ||||
| -rw-r--r-- | source/slang/parser.h | 4 | ||||
| -rw-r--r-- | source/slang/preprocessor.h | 2 | ||||
| -rw-r--r-- | source/slang/slang.cpp | 769 | ||||
| -rw-r--r-- | source/slang/syntax-visitors.h | 12 | ||||
| -rw-r--r-- | source/slangc/main.cpp | 37 | ||||
| -rw-r--r-- | tools/render-test/render-d3d11.cpp | 4 | ||||
| -rw-r--r-- | tools/render-test/slang-support.cpp | 8 |
17 files changed, 676 insertions, 701 deletions
diff --git a/examples/hello/hello.cpp b/examples/hello/hello.cpp index c9121b790..8e48b3c13 100644 --- a/examples/hello/hello.cpp +++ b/examples/hello/hello.cpp @@ -100,8 +100,8 @@ HRESULT initialize( ID3D11Device* dxDevice ) char const* vertexProfileName = "vs_4_0"; char const* fragmentProfileName = "ps_4_0"; - spAddTranslationUnitEntryPoint(slangRequest, translationUnitIndex, vertexEntryPointName, spFindProfile(slangSession, vertexProfileName)); - spAddTranslationUnitEntryPoint(slangRequest, translationUnitIndex, fragmentEntryPointName, spFindProfile(slangSession, fragmentProfileName)); + spAddEntryPoint(slangRequest, translationUnitIndex, vertexEntryPointName, spFindProfile(slangSession, vertexProfileName)); + spAddEntryPoint(slangRequest, translationUnitIndex, fragmentEntryPointName, spFindProfile(slangSession, fragmentProfileName)); int compileErr = spCompile(slangRequest); if(auto diagnostics = spGetDiagnosticOutput(slangRequest)) @@ -281,7 +281,7 @@ extern "C" /** Add an entry point in a particular translation unit */ - SLANG_API int spAddTranslationUnitEntryPoint( + SLANG_API int spAddEntryPoint( SlangCompileRequest* request, int translationUnitIndex, char const* name, @@ -337,7 +337,6 @@ extern "C" */ SLANG_API char const* spGetEntryPointSource( SlangCompileRequest* request, - int translationUnitIndex, int entryPointIndex); diff --git a/source/slang/check.cpp b/source/slang/check.cpp index f79df0c40..128afcefe 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -46,27 +46,25 @@ namespace Slang { ProgramSyntaxNode * program = nullptr; FunctionSyntaxNode * function = nullptr; - CompileOptions const* options = nullptr; - TranslationUnitOptions const* translationUnitOptions = nullptr; + CompileRequest* request = nullptr; + TranslationUnitRequest* translationUnit = nullptr; // lexical outer statements List<StatementSyntaxNode*> outerStmts; public: SemanticsVisitor( DiagnosticSink * pErr, - CompileOptions const& options, - TranslationUnitOptions const& translationUnitOptions, - CompileRequest* request) + CompileRequest* request, + TranslationUnitRequest* translationUnit) : SyntaxVisitor(pErr) - , options(&options) - , translationUnitOptions(&translationUnitOptions) , request(request) + , translationUnit(translationUnit) { } - CompileOptions const& getOptions() { return *options; } - TranslationUnitOptions const& getTranslationUnitOptions() { return *translationUnitOptions; } + CompileRequest* getCompileRequest() { return request; } + TranslationUnitRequest* getTranslationUnit() { return translationUnit; } public: // Translate Types @@ -969,7 +967,7 @@ namespace Slang // expressions without a type, and we need to ignore them. if( !fromExpr->Type.type ) { - if(getTranslationUnitOptions().compileFlags & SLANG_COMPILE_FLAG_NO_CHECKING ) + if(getTranslationUnit()->compileFlags & SLANG_COMPILE_FLAG_NO_CHECKING ) return fromExpr; } @@ -981,7 +979,7 @@ namespace Slang fromExpr.Ptr(), nullptr)) { - if(!(getTranslationUnitOptions().compileFlags & SLANG_COMPILE_FLAG_NO_CHECKING)) + if(!(getTranslationUnit()->compileFlags & SLANG_COMPILE_FLAG_NO_CHECKING)) { getSink()->diagnose(fromExpr->Position, Diagnostics::typeMismatch, toType, fromExpr->Type); } @@ -4967,12 +4965,11 @@ namespace Slang }; SyntaxVisitor* CreateSemanticsVisitor( - DiagnosticSink* err, - CompileOptions const& options, - TranslationUnitOptions const& translationUnitOptions, - CompileRequest* request) + DiagnosticSink* err, + CompileRequest* request, + TranslationUnitRequest* translationUnit) { - return new SemanticsVisitor(err, options, translationUnitOptions, request); + return new SemanticsVisitor(err, request, translationUnit); } // diff --git a/source/slang/compiled-program.h b/source/slang/compiled-program.h index 1766127b2..7f5b674a0 100644 --- a/source/slang/compiled-program.h +++ b/source/slang/compiled-program.h @@ -8,42 +8,6 @@ namespace Slang { - void IndentString(StringBuilder & sb, String src); - - struct EntryPointResult - { - String outputSource; - }; - - struct TranslationUnitResult - { - String outputSource; - List<EntryPointResult> entryPoints; - }; - - class CompileResult - { - public: - DiagnosticSink* mSink = nullptr; - - // Per-translation-unit results - List<TranslationUnitResult> translationUnits; - - CompileResult() - {} - ~CompileResult() - { - } - DiagnosticSink * GetErrorWriter() - { - return mSink; - } - int GetErrorCount() - { - return mSink->GetErrorCount(); - } - }; - } #endif
\ No newline at end of file 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); - } - } diff --git a/source/slang/compiler.h b/source/slang/compiler.h index 39c91e21b..36fc5f42f 100644 --- a/source/slang/compiler.h +++ b/source/slang/compiler.h @@ -14,7 +14,7 @@ namespace Slang { struct IncludeHandler; - struct CompileRequest; + class CompileRequest; enum class CompilerMode { @@ -48,11 +48,42 @@ namespace Slang ReflectionJSON = SLANG_REFLECTION_JSON, }; + class CompileRequest; + class TranslationUnitRequest; + + // Result of compiling an entry point + struct EntryPointResult + { + String outputSource; + }; + // Describes an entry point that we've been requested to compile - struct EntryPointOption + class EntryPointRequest : public RefObject { + public: + // The parent compile request + CompileRequest* compileRequest = nullptr; + + // The name of the entry point function (e.g., `main`) String name; + + // The profile that the entry point will be compiled for + // (this is a combination of the target state, and also + // a feature level that sets capabilities) Profile profile; + + // The index of the translation unit (within the parent + // compile request) that the entry point function is + // supposed to be defined in. + int translationUnitIndex; + + // The resulting output for the enry point + // + // TODO: low-level code generation should be a distinct step + EntryPointResult result; + + // The translation unit that this entry point came from + TranslationUnitRequest* getTranslationUnit(); }; enum class PassThroughMode : SlangPassThrough @@ -74,27 +105,49 @@ namespace Slang String content; }; - // Options for a single translation unit being requested by the user - class TranslationUnitOptions + // Result of compiling a translation unit + struct TranslationUnitResult + { + String outputSource; + }; + + // A single translation unit requested to be compiled. + // + class TranslationUnitRequest : public RefObject { public: - SourceLanguage sourceLanguage = SourceLanguage::Unknown; + // The parent compile request + CompileRequest* compileRequest = nullptr; - // All entry points we've been asked to compile for this translation unit - List<EntryPointOption> entryPoints; + // The language in which the source file(s) + // are assumed to be written + SourceLanguage sourceLanguage = SourceLanguage::Unknown; // The source file(s) that will be compiled to form this translation unit + // + // Usually, for HLSL or GLSL there will be only one file. List<RefPtr<SourceFile> > sourceFiles; + // The entry points associated with this translation unit + List<RefPtr<EntryPointRequest> > entryPoints; + // Preprocessor definitions to use for this translation unit only // (whereas the ones on `CompileOptions` will be shared) Dictionary<String, String> preprocessorDefinitions; // Compile flags for this translation unit SlangCompileFlags compileFlags = 0; - }; + // The parsed syntax for the translation unit + RefPtr<ProgramSyntaxNode> SyntaxNode; + // The resulting output for the translation unit + // + // TODO: low-level code generation should be a distinct step + TranslationUnitResult result; + }; + + // A directory to be searched when looking for files (e.g., `#include`) struct SearchDirectory { enum Kind @@ -114,9 +167,14 @@ namespace Slang Kind kind; }; - class CompileOptions + class Session; + + class CompileRequest : public RefObject { public: + // Pointer to parent session + Session* mSession; + // What target language are we compiling to? CodeGenTarget Target = CodeGenTarget::Unknown; @@ -127,7 +185,11 @@ namespace Slang Dictionary<String, String> preprocessorDefinitions; // Translation units we are being asked to compile - List<TranslationUnitOptions> translationUnits; + List<RefPtr<TranslationUnitRequest> > translationUnits; + + // Entry points we've been asked to compile (each + // assocaited with a translation unit). + List<RefPtr<EntryPointRequest> > entryPoints; // The code generation profile we've been asked to use. Profile profile; @@ -137,53 +199,73 @@ namespace Slang // Compile flags to be shared by all translation units SlangCompileFlags compileFlags = 0; - }; - // This is the representation of a given translation unit - class CompileUnit - { - public: - TranslationUnitOptions options; - RefPtr<ProgramSyntaxNode> SyntaxNode; - }; + // Output stuff + DiagnosticSink mSink; + String mDiagnosticOutput; - // TODO: pick an appropriate name for this... - class CollectionOfTranslationUnits : public RefObject - { - public: - List<CompileUnit> translationUnits; + // Files that compilation depended on + List<String> mDependencyFilePaths; - // TODO: this is more output-oriented, but maybe okay to have here... + // The resulting reflection layout information RefPtr<ProgramLayout> layout; - }; - // Context information for code generation - struct ExtraContext - { - CompileOptions const* options = nullptr; - TranslationUnitOptions const* translationUnitOptions = nullptr; + // Modules that have been dynamically loaded via `import` + Dictionary<String, RefPtr<ProgramSyntaxNode>> loadedModules; + + + CompileRequest(Session* session) + : mSession(session) + {} - CompileResult* compileResult = nullptr; + ~CompileRequest() + {} - RefPtr<ProgramSyntaxNode> programSyntax; - ProgramLayout* programLayout; + void parseTranslationUnit( + TranslationUnitRequest* translationUnit); - String sourceText; - String sourcePath; + void CompileRequest::checkTranslationUnit( + TranslationUnitRequest* translationUnit); - CompileOptions const& getOptions() { return *options; } - TranslationUnitOptions const& getTranslationUnitOptions() { return *translationUnitOptions; } - }; + void checkAllTranslationUnits(); + + int executeActionsInner(); + int executeActions(); + + int addTranslationUnit(SourceLanguage language, String const& name); + + void addTranslationUnitSourceString( + int translationUnitIndex, + String const& path, + String const& source); - TranslationUnitResult passThrough( - String const& sourceText, - String const& sourcePath, - const CompileOptions & options, - TranslationUnitOptions const& translationUnitOptions); + void addTranslationUnitSourceFile( + int translationUnitIndex, + String const& path); + + int addEntryPoint( + int translationUnitIndex, + String const& name, + Profile profile); + + RefPtr<ProgramSyntaxNode> loadModule( + String const& name, + String const& path, + String const& source, + CodePosition const& loc); + + String autoImportModule( + String const& path, + String const& source, + CodePosition const& loc); + + RefPtr<ProgramSyntaxNode> findOrImportModule( + String const& name, + CodePosition const& loc); + }; void generateOutput( - ExtraContext& context, - CollectionOfTranslationUnits* collectionOfTranslationUnits); + CompileRequest* compileRequest); } #endif
\ No newline at end of file diff --git a/source/slang/options.cpp b/source/slang/options.cpp index b3f0629c6..81b893d66 100644 --- a/source/slang/options.cpp +++ b/source/slang/options.cpp @@ -520,7 +520,7 @@ struct OptionsParser // Now place all those entry points where they belong for( auto& entryPoint : rawEntryPoints ) { - spAddTranslationUnitEntryPoint( + spAddEntryPoint( compileRequest, entryPoint.translationUnitIndex, entryPoint.name.begin(), diff --git a/source/slang/parameter-binding.cpp b/source/slang/parameter-binding.cpp index 0756eb68c..70cb4e7ba 100644 --- a/source/slang/parameter-binding.cpp +++ b/source/slang/parameter-binding.cpp @@ -941,7 +941,7 @@ static void processEntryPointParameter( static void collectEntryPointParameters( ParameterBindingContext* context, - EntryPointOption const& entryPoint, + EntryPointRequest* entryPoint, ProgramSyntaxNode* translationUnitSyntax) { // First, look for the entry point with the specified name @@ -950,7 +950,7 @@ static void collectEntryPointParameters( buildMemberDictionary(translationUnitSyntax); Decl* entryPointDecl; - if( !translationUnitSyntax->memberDictionary.TryGetValue(entryPoint.name, entryPointDecl) ) + if( !translationUnitSyntax->memberDictionary.TryGetValue(entryPoint->name, entryPointDecl) ) { // No such entry point! return; @@ -970,7 +970,7 @@ static void collectEntryPointParameters( // Create the layout object here auto entryPointLayout = new EntryPointLayout(); - entryPointLayout->profile = entryPoint.profile; + entryPointLayout->profile = entryPoint->profile; entryPointLayout->entryPoint = entryPointFuncDecl; @@ -1043,18 +1043,18 @@ static void collectEntryPointParameters( // inputs and outputs). static Stage inferStageForTranslationUnit( - CompileUnit const& translationUnit) + TranslationUnitRequest* translationUnit) { // In the specific case where we are compiling GLSL input, // and have only a single entry point, use the stage // of the entry point. // // TODO: can we generalize this at all? - if( translationUnit.options.sourceLanguage == SourceLanguage::GLSL ) + if( translationUnit->sourceLanguage == SourceLanguage::GLSL ) { - if( translationUnit.options.entryPoints.Count() == 1 ) + if( translationUnit->entryPoints.Count() == 1 ) { - return translationUnit.options.entryPoints[0].profile.GetStage(); + return translationUnit->entryPoints[0]->profile.GetStage(); } } @@ -1063,36 +1063,36 @@ inferStageForTranslationUnit( static void collectParameters( ParameterBindingContext* inContext, - CollectionOfTranslationUnits* program) + CompileRequest* request) { ParameterBindingContext contextData = *inContext; auto context = &contextData; - for( auto& translationUnit : program->translationUnits ) + for( auto& translationUnit : request->translationUnits ) { - context->stage = inferStageForTranslationUnit(translationUnit); + context->stage = inferStageForTranslationUnit(translationUnit.Ptr()); // First look at global-scope parameters - collectGlobalScopeParameters(context, translationUnit.SyntaxNode.Ptr()); + collectGlobalScopeParameters(context, translationUnit->SyntaxNode.Ptr()); // Next consider parameters for entry points - for( auto& entryPoint : translationUnit.options.entryPoints ) + for( auto& entryPoint : translationUnit->entryPoints ) { - context->stage = entryPoint.profile.GetStage(); - collectEntryPointParameters(context, entryPoint, translationUnit.SyntaxNode.Ptr()); + context->stage = entryPoint->profile.GetStage(); + collectEntryPointParameters(context, entryPoint.Ptr(), translationUnit->SyntaxNode.Ptr()); } } } -void GenerateParameterBindings( - CollectionOfTranslationUnits* program) +void generateParameterBindings( + CompileRequest* request) { // TODO: infer a language or set of language rules to use based on the // source files and entry points given auto language = SourceLanguage::Unknown; - for( auto& translationUnit : program->translationUnits ) + for( auto& translationUnit : request->translationUnits ) { - auto translationUnitLanguage = translationUnit.options.sourceLanguage; + auto translationUnitLanguage = translationUnit->sourceLanguage; if( language == SourceLanguage::Unknown ) { language = translationUnitLanguage; @@ -1129,7 +1129,7 @@ void GenerateParameterBindings( context.layoutRules = sharedContext.defaultLayoutRules; // Walk through AST to discover all the parameters - collectParameters(&context, program); + collectParameters(&context, request); // Now walk through the parameters to generate initial binding information for( auto& parameter : sharedContext.parameters ) @@ -1245,7 +1245,7 @@ void GenerateParameterBindings( // We now have a bunch of layout information, which we should // record into a suitable object that represents the program programLayout->globalScopeLayout = globalScopeLayout; - program->layout = programLayout; + request->layout = programLayout; } } diff --git a/source/slang/parameter-binding.h b/source/slang/parameter-binding.h index 2fff08090..66c8053d3 100644 --- a/source/slang/parameter-binding.h +++ b/source/slang/parameter-binding.h @@ -8,7 +8,7 @@ namespace Slang { -class CollectionOfTranslationUnits; +class CompileRequest; // The parameter-binding interface is responsible for assigning // binding locations/registers to every parameter of a shader @@ -23,8 +23,8 @@ class CollectionOfTranslationUnits; // and attach that information to the syntax nodes // of the program. -void GenerateParameterBindings( - CollectionOfTranslationUnits* program); +void generateParameterBindings( + CompileRequest* compileRequest); } diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp index 75398a40d..5e06aa877 100644 --- a/source/slang/parser.cpp +++ b/source/slang/parser.cpp @@ -32,8 +32,7 @@ namespace Slang class Parser { public: - CompileOptions const& options; - TranslationUnitOptions const& translationUnitOptions; + TranslationUnitRequest* translationUnit; int anonymousCounter = 0; @@ -67,15 +66,11 @@ namespace Slang currentScope = currentScope->parent; } Parser( - CompileOptions const& options, - TranslationUnitOptions const& translationUnitOptions, TokenSpan const& _tokens, DiagnosticSink * sink, String _fileName, RefPtr<Scope> const& outerScope) - : options(options) - , translationUnitOptions(translationUnitOptions) - , tokenReader(_tokens) + : tokenReader(_tokens) , sink(sink) , fileName(_fileName) , outerScope(outerScope) @@ -2500,7 +2495,7 @@ parser->ReadToken(TokenType::Comma); RefPtr<StatementSyntaxNode> Parser::ParseBlockStatement() { - if( translationUnitOptions.compileFlags & SLANG_COMPILE_FLAG_NO_CHECKING ) + if( translationUnit->compileFlags & SLANG_COMPILE_FLAG_NO_CHECKING ) { // We have been asked to parse the input, but not attempt to understand it. @@ -3157,15 +3152,16 @@ parser->ReadToken(TokenType::Comma); // Parse a source file into an existing translation unit void parseSourceFile( - ProgramSyntaxNode* translationUnitSyntax, - CompileOptions const& options, - TranslationUnitOptions const& translationUnitOptions, + TranslationUnitRequest* translationUnit, TokenSpan const& tokens, DiagnosticSink* sink, String const& fileName, RefPtr<Scope> const& outerScope) { - Parser parser(options, translationUnitOptions, tokens, sink, fileName, outerScope); - return parser.parseSourceFile(translationUnitSyntax); + Parser parser(tokens, sink, fileName, outerScope); + + parser.translationUnit = translationUnit; + + return parser.parseSourceFile(translationUnit->SyntaxNode.Ptr()); } } diff --git a/source/slang/parser.h b/source/slang/parser.h index d74a3f5a8..8dfef4c12 100644 --- a/source/slang/parser.h +++ b/source/slang/parser.h @@ -9,9 +9,7 @@ namespace Slang { // Parse a source file into an existing translation unit void parseSourceFile( - ProgramSyntaxNode* translationUnitSyntax, - CompileOptions const& options, - TranslationUnitOptions const& translationUnitOptions, + TranslationUnitRequest* translationUnit, TokenSpan const& tokens, DiagnosticSink* sink, String const& fileName, diff --git a/source/slang/preprocessor.h b/source/slang/preprocessor.h index f16bc3929..0c7848bb4 100644 --- a/source/slang/preprocessor.h +++ b/source/slang/preprocessor.h @@ -7,7 +7,7 @@ namespace Slang { -struct CompileRequest; +class CompileRequest; class DiagnosticSink; class ProgramSyntaxNode; diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index d86825766..37d72cadc 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -79,66 +79,50 @@ public: ExpressionType::Finalize(); } - CompileUnit createPredefUnit() - { - CompileUnit translationUnit; - - - RefPtr<ProgramSyntaxNode> translationUnitSyntax = new ProgramSyntaxNode(); - - TranslationUnitOptions translationUnitOptions; - translationUnit.options = translationUnitOptions; - translationUnit.SyntaxNode = translationUnitSyntax; - - return translationUnit; - } - void addBuiltinSource( RefPtr<Scope> const& scope, String const& path, String const& source); }; -struct CompileRequest +struct IncludeHandlerImpl : IncludeHandler { - // Pointer to parent session - Session* mSession; - - // Input options - CompileOptions Options; - - // Output stuff - DiagnosticSink mSink; - String mDiagnosticOutput; - - RefPtr<CollectionOfTranslationUnits> mCollectionOfTranslationUnits; - - RefPtr<ProgramLayout> mReflectionData; + CompileRequest* request; - CompileResult mResult; + virtual IncludeResult TryToFindIncludeFile( + String const& pathToInclude, + String const& pathIncludedFrom, + String* outFoundPath, + String* outFoundSource) override + { + String path = Path::Combine(Path::GetDirectoryName(pathIncludedFrom), pathToInclude); + if (File::Exists(path)) + { + *outFoundPath = path; + *outFoundSource = File::ReadAllText(path); - List<String> mDependencyFilePaths; + request->mDependencyFilePaths.Add(path); - CompileRequest(Session* session) - : mSession(session) - {} + // HACK(tfoley): We might have found the file in the same directory, + // but what if this is also inside an auto-import path? + for (auto & dir : request->searchDirectories) + { + // Only consider auto-import paths + if(dir.kind != SearchDirectory::Kind::AutoImport) + continue; - ~CompileRequest() - {} + String otherPath = Path::Combine(dir.path, pathToInclude); - struct IncludeHandlerImpl : IncludeHandler - { - CompileRequest* request; + if(otherPath == path) + return IncludeResult::FoundAutoImportFile; + } - List<SearchDirectory> searchDirs; + return IncludeResult::FoundIncludeFile; + } - virtual IncludeResult TryToFindIncludeFile( - String const& pathToInclude, - String const& pathIncludedFrom, - String* outFoundPath, - String* outFoundSource) override + for (auto & dir : request->searchDirectories) { - String path = Path::Combine(Path::GetDirectoryName(pathIncludedFrom), pathToInclude); + path = Path::Combine(dir.path, pathToInclude); if (File::Exists(path)) { *outFoundPath = path; @@ -146,464 +130,381 @@ struct CompileRequest request->mDependencyFilePaths.Add(path); - // HACK(tfoley): We might have found the file in the same directory, - // but what if this is also inside an auto-import path? - for (auto & dir : searchDirs) - { - // Only consider auto-import paths - if(dir.kind != SearchDirectory::Kind::AutoImport) - continue; - - String otherPath = Path::Combine(dir.path, pathToInclude); - - if(otherPath == path) - return IncludeResult::FoundAutoImportFile; - } - - return IncludeResult::FoundIncludeFile; - } - - for (auto & dir : searchDirs) - { - path = Path::Combine(dir.path, pathToInclude); - if (File::Exists(path)) + switch( dir.kind ) { - *outFoundPath = path; - *outFoundSource = File::ReadAllText(path); - - request->mDependencyFilePaths.Add(path); + case SearchDirectory::Kind::Default: + return IncludeResult::FoundIncludeFile; - switch( dir.kind ) - { - case SearchDirectory::Kind::Default: - return IncludeResult::FoundIncludeFile; - - case SearchDirectory::Kind::AutoImport: - return IncludeResult::FoundAutoImportFile; - } + case SearchDirectory::Kind::AutoImport: + return IncludeResult::FoundAutoImportFile; } } - return IncludeResult::NotFound; - } - }; - - - CompileUnit parseTranslationUnit( - TranslationUnitOptions const& translationUnitOptions, - CompileOptions& options) - { - IncludeHandlerImpl includeHandler; - includeHandler.request = this; - - CompileUnit translationUnit; - - RefPtr<Scope> languageScope; - switch (translationUnitOptions.sourceLanguage) - { - case SourceLanguage::HLSL: - languageScope = mSession->hlslLanguageScope; - break; - - case SourceLanguage::GLSL: - languageScope = mSession->glslLanguageScope; - break; - - case SourceLanguage::Slang: - default: - languageScope = mSession->slangLanguageScope; - break; - } - - Dictionary<String, String> preprocessorDefinitions; - for(auto& def : options.preprocessorDefinitions) - preprocessorDefinitions.Add(def.Key, def.Value); - for(auto& def : translationUnitOptions.preprocessorDefinitions) - preprocessorDefinitions.Add(def.Key, def.Value); - - RefPtr<ProgramSyntaxNode> translationUnitSyntax = new ProgramSyntaxNode(); - - for (auto sourceFile : translationUnitOptions.sourceFiles) - { - auto sourceFilePath = sourceFile->path; - - auto searchDirs = options.searchDirectories; - searchDirs.Reverse(); - searchDirs.Add(SearchDirectory(Path::GetDirectoryName(sourceFilePath), SearchDirectory::Kind::Default)); - searchDirs.Reverse(); - includeHandler.searchDirs = searchDirs; - - String source = sourceFile->content; - - auto tokens = preprocessSource( - source, - sourceFilePath, - mResult.GetErrorWriter(), - &includeHandler, - preprocessorDefinitions, - translationUnitSyntax.Ptr(), - this); - - parseSourceFile( - translationUnitSyntax.Ptr(), - options, - translationUnitOptions, - tokens, - mResult.GetErrorWriter(), - sourceFilePath, - languageScope); } + return IncludeResult::NotFound; + } +}; - translationUnit.options = translationUnitOptions; - translationUnit.SyntaxNode = translationUnitSyntax; - return translationUnit; - } +void CompileRequest::parseTranslationUnit( + TranslationUnitRequest* translationUnit) +{ + IncludeHandlerImpl includeHandler; + includeHandler.request = this; - CompileUnit parseTranslationUnit( - TranslationUnitOptions const& translationUnitOptions) + RefPtr<Scope> languageScope; + switch (translationUnit->sourceLanguage) { - return parseTranslationUnit(translationUnitOptions, Options); + case SourceLanguage::HLSL: + languageScope = mSession->hlslLanguageScope; + break; + + case SourceLanguage::GLSL: + languageScope = mSession->glslLanguageScope; + break; + + case SourceLanguage::Slang: + default: + languageScope = mSession->slangLanguageScope; + break; } - void checkTranslationUnit( - CompileUnit& translationUnit, - RefPtr<SyntaxVisitor> visitor) - { - visitor->setSourceLanguage(translationUnit.options.sourceLanguage); - translationUnit.SyntaxNode->Accept(visitor.Ptr()); - } + Dictionary<String, String> combinedPreprocessorDefinitions; + for(auto& def : preprocessorDefinitions) + combinedPreprocessorDefinitions.Add(def.Key, def.Value); + for(auto& def : translationUnit->preprocessorDefinitions) + combinedPreprocessorDefinitions.Add(def.Key, def.Value); + + RefPtr<ProgramSyntaxNode> translationUnitSyntax = new ProgramSyntaxNode(); + translationUnit->SyntaxNode = translationUnitSyntax; - void checkTranslationUnit( - CompileUnit& translationUnit, - CompileOptions& options) + for (auto sourceFile : translationUnit->sourceFiles) { - RefPtr<SyntaxVisitor> visitor = CreateSemanticsVisitor( - mResult.GetErrorWriter(), - options, - translationUnit.options, + auto sourceFilePath = sourceFile->path; + String source = sourceFile->content; + + auto tokens = preprocessSource( + source, + sourceFilePath, + &mSink, + &includeHandler, + combinedPreprocessorDefinitions, + translationUnitSyntax.Ptr(), this); - checkTranslationUnit(translationUnit, visitor); + parseSourceFile( + translationUnit, + tokens, + &mSink, + sourceFilePath, + languageScope); } +} + +void CompileRequest::checkTranslationUnit( + TranslationUnitRequest* translationUnit) +{ + RefPtr<SyntaxVisitor> visitor = CreateSemanticsVisitor( + &mSink, + this, + translationUnit); - void checkCollectionOfTranslationUnits( - RefPtr<CollectionOfTranslationUnits> collectionOfTranslationUnits) + visitor->setSourceLanguage(translationUnit->sourceLanguage); + translationUnit->SyntaxNode->Accept(visitor.Ptr()); +} + +void CompileRequest::checkAllTranslationUnits() +{ + for( auto& translationUnit : translationUnits ) { - for( auto& translationUnit : collectionOfTranslationUnits->translationUnits ) - { - checkTranslationUnit(translationUnit, Options); - } + checkTranslationUnit(translationUnit.Ptr()); } +} - void generateOutputForCollectionOfTranslationUnits( - RefPtr<CollectionOfTranslationUnits> collectionOfTranslationUnits) +int CompileRequest::executeActionsInner() +{ + // Do some cleanup on settings specified by user. + // In particular, we want to propagate flags from the overall request down to + // each translation unit. + for( auto& translationUnit : translationUnits ) { - // Do binding generation, and then reflection (globally) - // before we move on to any code-generation activites. - GenerateParameterBindings(collectionOfTranslationUnits.Ptr()); - - - // 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: - - ExtraContext extra; - extra.options = &Options; - extra.programLayout = collectionOfTranslationUnits->layout.Ptr(); - extra.compileResult = &mResult; + translationUnit->compileFlags |= compileFlags; - generateOutput(extra, collectionOfTranslationUnits.Ptr()); + // However, the "no checking" flag shouldn't be applied to + // any translation unit that is native Slang code. + if( translationUnit->sourceLanguage == SourceLanguage::Slang ) + { + translationUnit->compileFlags &= ~SLANG_COMPILE_FLAG_NO_CHECKING; + } } - int executeCompilerDriverActions() +#if 0 + // If we are being asked to do pass-through, then we need to do that here... + if (passThrough != PassThroughMode::None) { - // Do some cleanup on settings specified by user. - // In particular, we want to propagate flags from the overall request down to - // each translation unit. - for( auto& translationUnitOptions : Options.translationUnits ) + for (auto& translationUnitOptions : Options.translationUnits) { - translationUnitOptions.compileFlags |= Options.compileFlags; - - // However, the "no checking" flag shouldn't be applied to - // any translation unit that is native Slang code. - if( translationUnitOptions.sourceLanguage == SourceLanguage::Slang ) + switch (translationUnitOptions.sourceLanguage) { - translationUnitOptions.compileFlags &= SLANG_COMPILE_FLAG_NO_CHECKING; + // We can pass-through code written in a native shading language + case SourceLanguage::GLSL: + case SourceLanguage::HLSL: + break; + + // All other translation units need to be skipped + default: + continue; } - } - // If we are being asked to do pass-through, then we need to do that here... - if (Options.passThrough != PassThroughMode::None) - { - for (auto& translationUnitOptions : Options.translationUnits) - { - switch (translationUnitOptions.sourceLanguage) - { - // We can pass-through code written in a native shading language - case SourceLanguage::GLSL: - case SourceLanguage::HLSL: - break; - - // All other translation units need to be skipped - default: - continue; - } - - auto sourceFile = translationUnitOptions.sourceFiles[0]; - auto sourceFilePath = sourceFile->path; - String source = sourceFile->content; + auto sourceFile = translationUnitOptions.sourceFiles[0]; + auto sourceFilePath = sourceFile->path; + String source = sourceFile->content; - auto translationUnitResult = passThrough( - source, - sourceFilePath, - Options, - translationUnitOptions); + auto translationUnitResult = passThrough( + source, + sourceFilePath, + Options, + translationUnitOptions); - mResult.translationUnits.Add(translationUnitResult); - } - return 0; + mResult.translationUnits.Add(translationUnitResult); } + return 0; + } +#endif - // TODO: load the stdlib - - mCollectionOfTranslationUnits = new CollectionOfTranslationUnits(); - + // We only do parsing and semantic checking if we *aren't* doing + // a pass-through compilation. + // + // Note that we *do* perform output generation as normal in pass-through mode. + if( passThrough == PassThroughMode::None ) + { // Parse everything from the input files requested - // - // TODO: this may trigger the loading and/or compilation of additional modules. - for (auto& translationUnitOptions : Options.translationUnits) + for (auto& translationUnit : translationUnits) { - auto translationUnit = parseTranslationUnit(translationUnitOptions); - mCollectionOfTranslationUnits->translationUnits.Add(translationUnit); + parseTranslationUnit(translationUnit.Ptr()); } - if (mResult.GetErrorCount() != 0) + if (mSink.GetErrorCount() != 0) return 1; // Perform semantic checking on the whole collection - checkCollectionOfTranslationUnits(mCollectionOfTranslationUnits); - if (mResult.GetErrorCount() != 0) + checkAllTranslationUnits(); + if (mSink.GetErrorCount() != 0) return 1; - // Generate output code, in whatever format was requested - generateOutputForCollectionOfTranslationUnits(mCollectionOfTranslationUnits); - if (mResult.GetErrorCount() != 0) + // Now do shader parameter binding generation, which + // needs to be performed globally. + generateParameterBindings(this); + if (mSink.GetErrorCount() != 0) return 1; + } - // Extract the reflection layout information so that users - // can easily query it. - mReflectionData = mCollectionOfTranslationUnits->layout; + // Generate output code, in whatever format was requested + generateOutput(this); + if (mSink.GetErrorCount() != 0) + return 1; - return 0; - } + return 0; +} - // Act as expected of the API-based compiler - int executeAPIActions() - { - mResult.mSink = &mSink; +// Act as expected of the API-based compiler +int CompileRequest::executeActions() +{ + int err = executeActionsInner(); - int err = executeCompilerDriverActions(); + mDiagnosticOutput = mSink.outputBuffer.ProduceString(); - mDiagnosticOutput = mSink.outputBuffer.ProduceString(); + return err; +} - if (mSink.GetErrorCount() != 0) - return mSink.GetErrorCount(); +int CompileRequest::addTranslationUnit(SourceLanguage language, String const& name) +{ + int result = translationUnits.Count(); - return err; - } + RefPtr<TranslationUnitRequest> translationUnit = new TranslationUnitRequest(); + translationUnit->compileRequest = this; + translationUnit->sourceLanguage = SourceLanguage(language); - int addTranslationUnit(SourceLanguage language, String const& name) - { - int result = Options.translationUnits.Count(); + translationUnits.Add(translationUnit); - TranslationUnitOptions translationUnit; - translationUnit.sourceLanguage = SourceLanguage(language); + return result; +} - Options.translationUnits.Add(translationUnit); +void CompileRequest::addTranslationUnitSourceString( + int translationUnitIndex, + String const& path, + String const& source) +{ + RefPtr<SourceFile> sourceFile = new SourceFile(); + sourceFile->path = path; + sourceFile->content = source; - return result; - } + translationUnits[translationUnitIndex]->sourceFiles.Add(sourceFile); +} - void addTranslationUnitSourceString( - int translationUnitIndex, - String const& path, - String const& source) +void CompileRequest::addTranslationUnitSourceFile( + int translationUnitIndex, + String const& path) +{ + String source; + try { - RefPtr<SourceFile> sourceFile = new SourceFile(); - sourceFile->path = path; - sourceFile->content = source; - - Options.translationUnits[translationUnitIndex].sourceFiles.Add(sourceFile); + source = File::ReadAllText(path); } - - void addTranslationUnitSourceFile( - int translationUnitIndex, - String const& path) + catch (...) { - String source; - try - { - source = File::ReadAllText(path); - } - catch (...) - { - // Emit a diagnostic! - mSink.diagnose( - CodePosition(0, 0, 0, path), - Diagnostics::cannotOpenFile, - path); - return; - } + // Emit a diagnostic! + mSink.diagnose( + CodePosition(0, 0, 0, path), + Diagnostics::cannotOpenFile, + path); + return; + } - addTranslationUnitSourceString( - translationUnitIndex, - path, - source); + addTranslationUnitSourceString( + translationUnitIndex, + path, + source); - mDependencyFilePaths.Add(path); - } + mDependencyFilePaths.Add(path); +} - int addTranslationUnitEntryPoint( - int translationUnitIndex, - String const& name, - Profile profile) - { - EntryPointOption entryPoint; - entryPoint.name = name; - entryPoint.profile = profile; +int CompileRequest::addEntryPoint( + int translationUnitIndex, + String const& name, + Profile profile) +{ + RefPtr<EntryPointRequest> entryPoint = new EntryPointRequest(); + entryPoint->compileRequest = this; + entryPoint->name = name; + entryPoint->profile = profile; + entryPoint->translationUnitIndex = translationUnitIndex; - // TODO: realistically want this to be global across all TUs... - int result = Options.translationUnits[translationUnitIndex].entryPoints.Count(); + auto translationUnit = translationUnits[translationUnitIndex].Ptr(); + translationUnit->entryPoints.Add(entryPoint); - Options.translationUnits[translationUnitIndex].entryPoints.Add(entryPoint); - return result; - } + int result = entryPoints.Count(); + entryPoints.Add(entryPoint); + return result; +} - Dictionary<String, RefPtr<ProgramSyntaxNode>> loadedModules; +RefPtr<ProgramSyntaxNode> CompileRequest::loadModule( + String const& name, + String const& path, + String const& source, + CodePosition const& loc) +{ + RefPtr<TranslationUnitRequest> translationUnit = new TranslationUnitRequest(); + translationUnit->compileRequest = this; - RefPtr<ProgramSyntaxNode> loadModule( - String const& name, - String const& path, - String const& source, - CodePosition const& loc) - { - // now we need to try compiling it, etc. + // We don't want to use the same options that the user specified + // for loading modules on-demand. In particular, we always want + // semantic checking to be enabled. + // + // TODO: decide which options, if any, should be inherited. - // We don't want to use the same options that the user specified - // for loading modules on-demand. In particular, we always want - // semantic checking to be enabled. - CompileOptions moduleOptions; - moduleOptions.searchDirectories = Options.searchDirectories; - moduleOptions.profile = Options.profile; + RefPtr<SourceFile> sourceFile = new SourceFile(); + sourceFile->path = path; + sourceFile->content = source; - RefPtr<SourceFile> sourceFile = new SourceFile(); - sourceFile->path = path; - sourceFile->content = source; + translationUnit->sourceFiles.Add(sourceFile); - TranslationUnitOptions translationUnitOptions; - translationUnitOptions.sourceFiles.Add(sourceFile); + parseTranslationUnit(translationUnit.Ptr()); - CompileUnit translationUnit = parseTranslationUnit(translationUnitOptions, moduleOptions); + // TODO: handle errors - // TODO: handle errors + checkTranslationUnit(translationUnit.Ptr()); - checkTranslationUnit(translationUnit, moduleOptions); + // Skip code generation - // Skip code generation + // - // + RefPtr<ProgramSyntaxNode> moduleDecl = translationUnit->SyntaxNode; - RefPtr<ProgramSyntaxNode> moduleDecl = translationUnit.SyntaxNode; + loadedModules.Add(name, moduleDecl); - loadedModules.Add(name, moduleDecl); + return moduleDecl; - return moduleDecl; +} - } +String CompileRequest::autoImportModule( + String const& path, + String const& source, + CodePosition const& loc) +{ + // TODO: may want to have some kind of canonicalization step here + String name = path; - String autoImportModule( - String const& path, - String const& source, - CodePosition const& loc) - { - // TODO: may want to have some kind of canonicalization step here - String name = path; + // Have we already loaded a module matching this name? + if (loadedModules.TryGetValue(name)) + return name; + + loadModule(name, path, source, loc); - // Have we already loaded a module matching this name? - if (loadedModules.TryGetValue(name)) - return name; + return name; +} - loadModule(name, path, source, loc); +RefPtr<ProgramSyntaxNode> CompileRequest::findOrImportModule( + String const& name, + CodePosition const& loc) +{ + // Have we already loaded a module matching this name? + // If so, return it. + RefPtr<ProgramSyntaxNode> moduleDecl; + if (loadedModules.TryGetValue(name, moduleDecl)) + return moduleDecl; - return name; - } + // Derive a file name for the module, by taking the given + // identifier, replacing all occurences of `_` with `-`, + // and then appending `.slang`. + // + // For example, `foo_bar` becomes `foo-bar.slang`. - RefPtr<ProgramSyntaxNode> findOrImportModule( - String const& name, - CodePosition const& loc) + StringBuilder sb; + for (auto c : name) { - // Have we already loaded a module matching this name? - // If so, return it. - RefPtr<ProgramSyntaxNode> moduleDecl; - if (loadedModules.TryGetValue(name, moduleDecl)) - return moduleDecl; - - // Derive a file name for the module, by taking the given - // identifier, replacing all occurences of `_` with `-`, - // and then appending `.slang`. - // - // For example, `foo_bar` becomes `foo-bar.slang`. + if (c == '_') + c = '-'; - StringBuilder sb; - for (auto c : name) - { - if (c == '_') - c = '-'; - - sb.Append(c); - } - sb.Append(".slang"); + sb.Append(c); + } + sb.Append(".slang"); - String fileName = sb.ProduceString(); + String fileName = sb.ProduceString(); - // Next, try to find the file of the given name, - // using our ordinary include-handling logic. + // Next, try to find the file of the given name, + // using our ordinary include-handling logic. - IncludeHandlerImpl includeHandler; - includeHandler.request = this; + IncludeHandlerImpl includeHandler; + includeHandler.request = this; - String pathIncludedFrom = loc.FileName; + String pathIncludedFrom = loc.FileName; - String foundPath; - String foundSource; - IncludeResult includeResult = includeHandler.TryToFindIncludeFile(fileName, pathIncludedFrom, &foundPath, &foundSource); - switch( includeResult ) + String foundPath; + String foundSource; + IncludeResult includeResult = includeHandler.TryToFindIncludeFile(fileName, pathIncludedFrom, &foundPath, &foundSource); + switch( includeResult ) + { + case IncludeResult::NotFound: + case IncludeResult::Error: { - case IncludeResult::NotFound: - case IncludeResult::Error: - { - this->mSink.diagnose(loc, Diagnostics::cannotFindFile, fileName); - - loadedModules[name] = nullptr; - return nullptr; - } - break; + this->mSink.diagnose(loc, Diagnostics::cannotFindFile, fileName); - default: - break; + loadedModules[name] = nullptr; + return nullptr; } + break; - // We've found a file that we can load for the given module, so - // go ahead and perform the module-load action - return loadModule( - name, - foundPath, - foundSource, - loc); + default: + break; } -}; + // We've found a file that we can load for the given module, so + // go ahead and perform the module-load action + return loadModule( + name, + foundPath, + foundSource, + loc); +} RefPtr<ProgramSyntaxNode> findOrImportModule( CompileRequest* request, @@ -627,29 +528,29 @@ void Session::addBuiltinSource( String const& path, String const& source) { - CompileRequest compileRequest(this); + RefPtr<CompileRequest> compileRequest = new CompileRequest(this); - auto translationUnitIndex = compileRequest.addTranslationUnit(SourceLanguage::Slang, path); + auto translationUnitIndex = compileRequest->addTranslationUnit(SourceLanguage::Slang, path); - compileRequest.addTranslationUnitSourceString( + compileRequest->addTranslationUnitSourceString( translationUnitIndex, path, source); - int err = compileRequest.executeAPIActions(); + int err = compileRequest->executeActions(); if (err) { - fprintf(stderr, "%s", compileRequest.mDiagnosticOutput.Buffer()); + fprintf(stderr, "%s", compileRequest->mDiagnosticOutput.Buffer()); #ifdef _WIN32 - OutputDebugStringA(compileRequest.mDiagnosticOutput.Buffer()); + OutputDebugStringA(compileRequest->mDiagnosticOutput.Buffer()); #endif assert(!"error in stdlib"); } // Extract the AST for the code we just parsed - auto syntax = compileRequest.mCollectionOfTranslationUnits->translationUnits[translationUnitIndex].SyntaxNode; + auto syntax = compileRequest->translationUnits[translationUnitIndex]->SyntaxNode; // HACK(tfoley): mark all declarations in the "stdlib" so // that we can detect them later (e.g., so we don't emit them) @@ -739,21 +640,21 @@ SLANG_API void spSetCompileFlags( SlangCompileRequest* request, SlangCompileFlags flags) { - REQ(request)->Options.compileFlags = flags; + REQ(request)->compileFlags = flags; } SLANG_API void spSetCodeGenTarget( SlangCompileRequest* request, int target) { - REQ(request)->Options.Target = (Slang::CodeGenTarget)target; + REQ(request)->Target = (Slang::CodeGenTarget)target; } SLANG_API void spSetPassThrough( SlangCompileRequest* request, SlangPassThrough passThrough) { - REQ(request)->Options.passThrough = Slang::PassThroughMode(passThrough); + REQ(request)->passThrough = Slang::PassThroughMode(passThrough); } SLANG_API void spSetDiagnosticCallback( @@ -772,14 +673,14 @@ SLANG_API void spAddSearchPath( SlangCompileRequest* request, const char* path) { - REQ(request)->Options.searchDirectories.Add(Slang::SearchDirectory(path, Slang::SearchDirectory::Kind::Default)); + REQ(request)->searchDirectories.Add(Slang::SearchDirectory(path, Slang::SearchDirectory::Kind::Default)); } SLANG_API void spAddAutoImportPath( SlangCompileRequest* request, const char* path) { - REQ(request)->Options.searchDirectories.Add(Slang::SearchDirectory(path, Slang::SearchDirectory::Kind::AutoImport)); + REQ(request)->searchDirectories.Add(Slang::SearchDirectory(path, Slang::SearchDirectory::Kind::AutoImport)); } SLANG_API void spAddPreprocessorDefine( @@ -787,7 +688,7 @@ SLANG_API void spAddPreprocessorDefine( const char* key, const char* value) { - REQ(request)->Options.preprocessorDefinitions[key] = value; + REQ(request)->preprocessorDefinitions[key] = value; } SLANG_API char const* spGetDiagnosticOutput( @@ -820,7 +721,7 @@ SLANG_API void spTranslationUnit_addPreprocessorDefine( { auto req = REQ(request); - req->Options.translationUnits[translationUnitIndex].preprocessorDefinitions[key] = value; + req->translationUnits[translationUnitIndex]->preprocessorDefinitions[key] = value; } @@ -833,7 +734,7 @@ SLANG_API void spAddTranslationUnitSourceFile( auto req = REQ(request); if(!path) return; if(translationUnitIndex < 0) return; - if(translationUnitIndex >= req->Options.translationUnits.Count()) return; + if(translationUnitIndex >= req->translationUnits.Count()) return; req->addTranslationUnitSourceFile( translationUnitIndex, @@ -851,7 +752,7 @@ SLANG_API void spAddTranslationUnitSourceString( auto req = REQ(request); if(!source) return; if(translationUnitIndex < 0) return; - if(translationUnitIndex >= req->Options.translationUnits.Count()) return; + if(translationUnitIndex >= req->translationUnits.Count()) return; if(!path) path = ""; @@ -869,7 +770,7 @@ SLANG_API SlangProfileID spFindProfile( return Slang::Profile::LookUp(name).raw; } -SLANG_API int spAddTranslationUnitEntryPoint( +SLANG_API int spAddEntryPoint( SlangCompileRequest* request, int translationUnitIndex, char const* name, @@ -879,10 +780,9 @@ SLANG_API int spAddTranslationUnitEntryPoint( auto req = REQ(request); if(!name) return -1; if(translationUnitIndex < 0) return -1; - if(translationUnitIndex >= req->Options.translationUnits.Count()) return -1; + if(translationUnitIndex >= req->translationUnits.Count()) return -1; - - return req->addTranslationUnitEntryPoint( + return req->addEntryPoint( translationUnitIndex, name, Slang::Profile(Slang::Profile::RawVal(profile))); @@ -895,7 +795,7 @@ SLANG_API int spCompile( { auto req = REQ(request); - int anyErrors = req->executeAPIActions(); + int anyErrors = req->executeActions(); return anyErrors; } @@ -925,7 +825,7 @@ spGetTranslationUnitCount( SlangCompileRequest* request) { auto req = REQ(request); - return req->mResult.translationUnits.Count(); + return req->translationUnits.Count(); } // Get the output code associated with a specific translation unit @@ -934,16 +834,15 @@ SLANG_API char const* spGetTranslationUnitSource( int translationUnitIndex) { auto req = REQ(request); - return req->mResult.translationUnits[translationUnitIndex].outputSource.Buffer(); + return req->translationUnits[translationUnitIndex]->result.outputSource.Buffer(); } SLANG_API char const* spGetEntryPointSource( SlangCompileRequest* request, - int translationUnitIndex, int entryPointIndex) { auto req = REQ(request); - return req->mResult.translationUnits[translationUnitIndex].entryPoints[entryPointIndex].outputSource.Buffer(); + return req->entryPoints[entryPointIndex]->result.outputSource.Buffer(); } @@ -955,7 +854,7 @@ SLANG_API SlangReflection* spGetReflection( if( !request ) return 0; auto req = REQ(request); - return (SlangReflection*) req->mReflectionData.Ptr(); + return (SlangReflection*) req->layout.Ptr(); } diff --git a/source/slang/syntax-visitors.h b/source/slang/syntax-visitors.h index dbcbf2781..5d712b671 100644 --- a/source/slang/syntax-visitors.h +++ b/source/slang/syntax-visitors.h @@ -7,18 +7,16 @@ namespace Slang { - class CompileOptions; - struct CompileRequest; + class CompileRequest; class ShaderCompiler; class ShaderLinkInfo; class ShaderSymbol; - class TranslationUnitOptions; + class TranslationUnitRequest; SyntaxVisitor* CreateSemanticsVisitor( - DiagnosticSink* err, - CompileOptions const& options, - TranslationUnitOptions const& translationUnitOptions, - CompileRequest* request); + DiagnosticSink* err, + CompileRequest* request, + TranslationUnitRequest* translationUnit); // Look for a module that matches the given name: // either one we've loaded already, or one we diff --git a/source/slangc/main.cpp b/source/slangc/main.cpp index 06f004531..4a783a17c 100644 --- a/source/slangc/main.cpp +++ b/source/slangc/main.cpp @@ -12,7 +12,7 @@ using namespace Slang; static void diagnosticCallback( char const* message, - void* userData) + void* /*userData*/) { fputs(message, stderr); fflush(stderr); @@ -89,29 +89,36 @@ int MAIN(int argc, char** argv) } #endif -#ifdef _MSC_VER - _CrtDumpMemoryLeaks(); -#endif return 0; } #ifdef _WIN32 int wmain(int argc, wchar_t** argv) { - // Conver the wide-character Unicode arguments to UTF-8, - // since that is what Slang expects on the API side. + int result = 0; - List<String> args; - for(int ii = 0; ii < argc; ++ii) - { - args.Add(String::FromWString(argv[ii])); - } - List<char const*> argBuffers; - for(int ii = 0; ii < argc; ++ii) { - argBuffers.Add(args[ii].Buffer()); + // Conver the wide-character Unicode arguments to UTF-8, + // since that is what Slang expects on the API side. + + List<String> args; + for(int ii = 0; ii < argc; ++ii) + { + args.Add(String::FromWString(argv[ii])); + } + List<char const*> argBuffers; + for(int ii = 0; ii < argc; ++ii) + { + argBuffers.Add(args[ii].Buffer()); + } + + result = MAIN(argc, (char**) &argBuffers[0]); } - return MAIN(argc, (char**) &argBuffers[0]); +#ifdef _MSC_VER + _CrtDumpMemoryLeaks(); +#endif + + return result; } #endif diff --git a/tools/render-test/render-d3d11.cpp b/tools/render-test/render-d3d11.cpp index 4f1071905..19795d685 100644 --- a/tools/render-test/render-d3d11.cpp +++ b/tools/render-test/render-d3d11.cpp @@ -113,8 +113,8 @@ HRESULT initializeSlang(ID3D11Device* dxDevice, char const* sourceText) spAddTranslationUnitSourceString(slangRequest, translationUnitIndex, gOptions.sourcePath, sourceText); - spAddTranslationUnitEntryPoint(slangRequest, translationUnitIndex, vertexEntryPointName, spFindProfile(slangSession, vertexProfileName)); - spAddTranslationUnitEntryPoint(slangRequest, translationUnitIndex, fragmentEntryPointName, spFindProfile(slangSession, fragmentProfileName)); + spAddEntryPoint(slangRequest, translationUnitIndex, vertexEntryPointName, spFindProfile(slangSession, vertexProfileName)); + spAddEntryPoint(slangRequest, translationUnitIndex, fragmentEntryPointName, spFindProfile(slangSession, fragmentProfileName)); int compileErr = spCompile(slangRequest); if(auto diagnostics = spGetDiagnosticOutput(slangRequest)) diff --git a/tools/render-test/slang-support.cpp b/tools/render-test/slang-support.cpp index 8db62ebef..d87f693eb 100644 --- a/tools/render-test/slang-support.cpp +++ b/tools/render-test/slang-support.cpp @@ -73,8 +73,8 @@ struct SlangShaderCompilerWrapper : public ShaderCompiler spSetCompileFlags(slangRequest, SLANG_COMPILE_FLAG_NO_CHECKING); } - int vertexEntryPoint = spAddTranslationUnitEntryPoint(slangRequest, vertexTranslationUnit, request.vertexShader.name, spFindProfile(slangSession, request.vertexShader.profile)); - int fragmentEntryPoint = spAddTranslationUnitEntryPoint(slangRequest, fragmentTranslationUnit, request.fragmentShader.name, spFindProfile(slangSession, request.fragmentShader.profile)); + int vertexEntryPoint = spAddEntryPoint(slangRequest, vertexTranslationUnit, request.vertexShader.name, spFindProfile(slangSession, request.vertexShader.profile)); + int fragmentEntryPoint = spAddEntryPoint(slangRequest, fragmentTranslationUnit, request.fragmentShader.name, spFindProfile(slangSession, request.fragmentShader.profile)); int compileErr = spCompile(slangRequest); if(auto diagnostics = spGetDiagnosticOutput(slangRequest)) @@ -97,8 +97,8 @@ struct SlangShaderCompilerWrapper : public ShaderCompiler innerRequest.source.text = translatedCode; } - char const* vertexCode = spGetEntryPointSource(slangRequest, vertexTranslationUnit, vertexEntryPoint); - char const* fragmentCode = spGetEntryPointSource(slangRequest, fragmentTranslationUnit, fragmentEntryPoint); + char const* vertexCode = spGetEntryPointSource(slangRequest, vertexEntryPoint); + char const* fragmentCode = spGetEntryPointSource(slangRequest, fragmentEntryPoint); innerRequest.vertexShader.source.text = vertexCode; innerRequest.fragmentShader.source.text = fragmentCode; |
