summaryrefslogtreecommitdiff
path: root/source/slang/slang-compiler.h
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/slang-compiler.h')
-rwxr-xr-xsource/slang/slang-compiler.h370
1 files changed, 283 insertions, 87 deletions
diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h
index 7f8257777..bf715d5d4 100755
--- a/source/slang/slang-compiler.h
+++ b/source/slang/slang-compiler.h
@@ -133,11 +133,11 @@ namespace Slang
Maximal = SLANG_OPTIMIZATION_LEVEL_MAXIMAL,
};
+ struct CodeGenContext;
+ class EndToEndCompileRequest;
+ class FrontEndCompileRequest;
class Linkage;
class Module;
- class FrontEndCompileRequest;
- class BackEndCompileRequest;
- class EndToEndCompileRequest;
class TranslationUnitRequest;
// Result of compiling an entry point.
@@ -2143,8 +2143,9 @@ namespace Slang
}
CompileResult& _createWholeProgramResult(
- BackEndCompileRequest* backEndRequest,
- EndToEndCompileRequest* endToEndRequest);
+ DiagnosticSink* sink,
+ EndToEndCompileRequest* endToEndReq = nullptr);
+
/// Internal helper for `getOrCreateEntryPointResult`.
///
/// This is used so that command-line and API-based
@@ -2154,8 +2155,8 @@ namespace Slang
///
CompileResult& _createEntryPointResult(
Int entryPointIndex,
- BackEndCompileRequest* backEndRequest,
- EndToEndCompileRequest* endToEndRequest);
+ DiagnosticSink* sink,
+ EndToEndCompileRequest* endToEndReq = nullptr);
RefPtr<IRModule> getOrCreateIRModuleForLayout(DiagnosticSink* sink);
@@ -2185,40 +2186,257 @@ namespace Slang
RefPtr<IRModule> m_irModuleForLayout;
};
- /// A request to generate code for a program
- class BackEndCompileRequest : public CompileRequestBase
+ /// A back-end-specific object to track optional feaures/capabilities/extensions
+ /// that are discovered to be used by a program/kernel as part of code generation.
+ class ExtensionTracker : public RefObject
{
+ // TODO: The existence of this type is evidence of a design/architecture problem.
+ //
+ // A better formulation of things requires a few key changes:
+ //
+ // 1. All optional capabilities need to be enumerated as part of the `CapabilitySet`
+ // system, so that they can be reasoned about uniformly across different targets
+ // and different layers of the compiler.
+ //
+ // 2. The front-end should be responsible for either or both of:
+ //
+ // * Checking that `public` or otherwise externally-visible items (declarations/definitions)
+ // explicitly declare the capabilities they require, and that they only ever
+ // make use of items that are comatible with those required capabilities.
+ //
+ // * Inferring the capabilities required by items that are not externally visible,
+ // and attaching those capabilities explicit as a modifier or other synthesized AST node.
+ //
+ // 3. The capabilities required by a given `ComponentType` and its entry points should be
+ // explicitly know-able, and they should be something we can compare to the capabilities
+ // of a code generation target *before* back-end code generation is started. We should be
+ // able to issue error messages around lacking capabilities in a way the user can understand,
+ // in terms of the high-level-language entities.
+
public:
- BackEndCompileRequest(
- Linkage* linkage,
- DiagnosticSink* sink,
- ComponentType* program = nullptr);
+ };
- // Should we dump intermediate results along the way, for debugging?
- bool shouldDumpIntermediates = false;
+ /// A context for code generation in the compiler back-end
+ struct CodeGenContext
+ {
+ public:
+ typedef List<Index> EntryPointIndices;
- ComponentType* getProgram() { return m_program; }
- void setProgram(ComponentType* program) { m_program = program; }
+ struct Shared
+ {
+ public:
+ Shared(
+ TargetProgram* targetProgram,
+ EntryPointIndices const& entryPointIndices,
+ DiagnosticSink* sink,
+ EndToEndCompileRequest* endToEndReq)
+ : targetProgram(targetProgram)
+ , entryPointIndices(entryPointIndices)
+ , sink(sink)
+ , endToEndReq(endToEndReq)
+ {}
+
+// Shared(
+// TargetProgram* targetProgram,
+// EndToEndCompileRequest* endToEndReq);
+
+ TargetProgram* targetProgram = nullptr;
+ EntryPointIndices entryPointIndices;
+ DiagnosticSink* sink = nullptr;
+ EndToEndCompileRequest* endToEndReq = nullptr;
+ };
+
+ CodeGenContext(
+ Shared* shared)
+ : m_shared(shared)
+ , m_targetFormat(shared->targetProgram->getTargetReq()->getTarget())
+ {}
+
+ CodeGenContext(
+ CodeGenContext* base,
+ CodeGenTarget targetFormat,
+ ExtensionTracker* extensionTracker = nullptr)
+ : m_shared(base->m_shared)
+ , m_targetFormat(targetFormat)
+ , m_extensionTracker(extensionTracker)
+ {}
+
+ /// Get the diagnostic sink
+ DiagnosticSink* getSink()
+ {
+ return m_shared->sink;
+ }
+
+ TargetProgram* getTargetProgram()
+ {
+ return m_shared->targetProgram;
+ }
+
+ EntryPointIndices const& getEntryPointIndices()
+ {
+ return m_shared->entryPointIndices;
+ }
+
+ CodeGenTarget getTargetFormat()
+ {
+ return m_targetFormat;
+ }
+
+ ExtensionTracker* getExtensionTracker()
+ {
+ return m_extensionTracker;
+ }
+
+ TargetRequest* getTargetReq()
+ {
+ return getTargetProgram()->getTargetReq();
+ }
+
+ CapabilitySet getTargetCaps()
+ {
+ return getTargetReq()->getTargetCaps();
+ }
+
+ CodeGenTarget getFinalTargetFormat()
+ {
+ return getTargetReq()->getTarget();
+ }
+
+ ComponentType* getProgram()
+ {
+ return getTargetProgram()->getProgram();
+ }
+
+ Linkage* getLinkage()
+ {
+ return getProgram()->getLinkage();
+ }
+
+ Session* getSession()
+ {
+ return getLinkage()->getSessionImpl();
+ }
+
+ /// Get the source manager
+ SourceManager* getSourceManager()
+ {
+ return getLinkage()->getSourceManager();
+ }
+
+ ISlangFileSystemExt* getFileSystemExt()
+ {
+ return getLinkage()->getFileSystemExt();
+ }
+
+ EndToEndCompileRequest* isEndToEndCompile()
+ {
+ return m_shared->endToEndReq;
+ }
+
+ EndToEndCompileRequest* isPassThroughEnabled();
+
+ Count getEntryPointCount()
+ {
+ return getEntryPointIndices().getCount();
+ }
+
+ EntryPoint* getEntryPoint(Index index)
+ {
+ return getProgram()->getEntryPoint(index);
+ }
+
+ Index getSingleEntryPointIndex()
+ {
+ SLANG_ASSERT(getEntryPointCount() == 1);
+ return getEntryPointIndices()[0];
+ }
- // Should R/W images without explicit formats be assumed to have "unknown" format?
//
- // The default behavior is to make a best-effort guess as to what format is intended.
+
+ IRDumpOptions getIRDumpOptions();
+
+ bool shouldValidateIR();
+ bool shouldDumpIR();
+
+ bool shouldDumpIntermediates();
+ String getIntermediateDumpPrefix();
+
+ bool getUseUnknownImageFormatAsDefault();
+
+ bool isSpecializationDisabled();
+
//
- bool useUnknownImageFormatAsDefault = false;
- // If true will disable generics/existential value specialization pass.
- bool disableSpecialization = false;
+ CompileResult emitEntryPoints();
- // If true will disable generating dynamic dispatch code.
- bool disableDynamicDispatch = false;
+ SlangResult dissassembleWithDownstream(
+ const void* data,
+ size_t dataSizeInBytes,
+ ISlangBlob** outBlob);
- // The default IR dumping options
- IRDumpOptions m_irDumpOptions;
+ SlangResult dissassembleWithDownstream(
+ DownstreamCompileResult* downstreamResult,
+ ISlangBlob** outBlob);
- String m_dumpIntermediatePrefix;
+ protected:
+ CodeGenTarget m_targetFormat = CodeGenTarget::Unknown;
+ ExtensionTracker* m_extensionTracker = nullptr;
+
+ // Helper to dump intermediate output when debugging
+ void maybeDumpIntermediate(
+ void const* data,
+ size_t size);
+ void maybeDumpIntermediate(
+ char const* text);
+
+ void maybeDumpIntermediate(
+ DownstreamCompileResult* compileResult);
+
+ void dumpIntermediate(
+ void const* data,
+ size_t size,
+ char const* ext,
+ bool isBinary);
+
+ void dumpIntermediateText(
+ void const* data,
+ size_t size,
+ char const* ext);
+
+ void dumpIntermediateBinary(
+ void const* data,
+ size_t size,
+ char const* ext);
+
+ /* Emits entry point source taking into account if a pass-through or not. Uses 'targetFormat' to determine
+ the target (not targetReq) */
+ SlangResult emitEntryPointsSource(
+ String& outSource);
+
+ SlangResult emitEntryPointsSourceFromIR(
+ String& outSource);
+
+ SlangResult emitWithDownstreamForEntryPoints(
+ RefPtr<DownstreamCompileResult>& outResult);
+
+ /* Determines a suitable filename to identify the input for a given entry point being compiled.
+ If the end-to-end compile is a pass-through case, will attempt to find the (unique) source file
+ pathname for the translation unit containing the entry point at `entryPointIndex.
+ If the compilation is not in a pass-through case, then always returns `"slang-generated"`.
+ @param endToEndReq The end-to-end compile request which might be using pass-through compilation
+ @param entryPointIndex The index of the entry point to compute a filename for.
+ @return the appropriate source filename */
+ String calcSourcePathForEntryPoints();
+
+ TranslationUnitRequest* findPassThroughTranslationUnit(
+ Int entryPointIndex);
+
+
+ SlangResult _emitEntryPoints(
+ RefPtr<DownstreamCompileResult>& outDownstreamResult);
private:
- RefPtr<ComponentType> m_program;
+ Shared* m_shared = nullptr;
};
/// A compile request that spans the front and back ends of the compiler
@@ -2402,7 +2620,6 @@ namespace Slang
NamePool* getNamePool() { return getLinkage()->getNamePool(); }
FrontEndCompileRequest* getFrontEndReq() { return m_frontEndReq; }
- BackEndCompileRequest* getBackEndReq() { return m_backEndReq; }
ComponentType* getUnspecializedGlobalComponentType() { return getFrontEndReq()->getGlobalComponentType(); }
ComponentType* getUnspecializedGlobalAndEntryPointsComponentType()
@@ -2422,10 +2639,47 @@ namespace Slang
m_linkage = nullptr;
m_frontEndReq = nullptr;
}
+
+ void generateOutput();
+
+
+ // Note: The following settings used to be considered part of the "back-end" compile
+ // request, but were only being used as part of end-to-end compilation anyway,
+ // so they were moved here.
+ //
+
+ // Should we dump intermediate results along the way, for debugging?
+ bool shouldDumpIntermediates = false;
+
+ // Should R/W images without explicit formats be assumed to have "unknown" format?
+ //
+ // The default behavior is to make a best-effort guess as to what format is intended.
+ //
+ bool useUnknownImageFormatAsDefault = false;
+
+ // If true will disable generics/existential value specialization pass.
+ bool disableSpecialization = false;
+
+ // If true will disable generating dynamic dispatch code.
+ bool disableDynamicDispatch = false;
+
+ // The default IR dumping options
+// IRDumpOptions m_irDumpOptions;
+
+ String m_dumpIntermediatePrefix;
+
private:
+ void writeWholeProgramResult(
+ TargetRequest* targetReq);
+ void writeEntryPointResult(
+ TargetRequest* targetReq,
+ Int entryPointIndex);
ISlangUnknown* getInterface(const Guid& guid);
+ void generateOutput(ComponentType* program);
+ void generateOutput(TargetProgram* targetProgram);
+
void init();
Session* m_session = nullptr;
@@ -2435,35 +2689,12 @@ namespace Slang
RefPtr<ComponentType> m_specializedGlobalComponentType;
RefPtr<ComponentType> m_specializedGlobalAndEntryPointsComponentType;
List<RefPtr<ComponentType>> m_specializedEntryPoints;
- RefPtr<BackEndCompileRequest> m_backEndReq;
// For output
RefPtr<StdWriters> m_writers;
};
- void generateOutput(
- BackEndCompileRequest* compileRequest);
-
- void generateOutput(
- EndToEndCompileRequest* compileRequest);
-
- // Helper to dump intermediate output when debugging
- void maybeDumpIntermediate(
- BackEndCompileRequest* compileRequest,
- void const* data,
- size_t size,
- CodeGenTarget target);
- void maybeDumpIntermediate(
- BackEndCompileRequest* compileRequest,
- char const* text,
- CodeGenTarget target);
-
- void maybeDumpIntermediate(
- BackEndCompileRequest* compileRequest,
- DownstreamCompileResult* compileResult,
- CodeGenTarget target);
-
/* Returns SLANG_OK if pass through support is available */
SlangResult checkExternalCompilerSupport(Session* session, PassThroughMode passThrough);
/* Report an error appearing from external compiler to the diagnostic sink error to the diagnostic sink.
@@ -2473,41 +2704,6 @@ namespace Slang
@param sink The diagnostic sink to report to */
void reportExternalCompileError(const char* compilerName, SlangResult res, const UnownedStringSlice& diagnostic, DiagnosticSink* sink);
- /* Determines a suitable filename to identify the input for a given entry point being compiled.
- If the end-to-end compile is a pass-through case, will attempt to find the (unique) source file
- pathname for the translation unit containing the entry point at `entryPointIndex.
- If the compilation is not in a pass-through case, then always returns `"slang-generated"`.
- @param endToEndReq The end-to-end compile request which might be using pass-through compilation
- @param entryPointIndex The index of the entry point to compute a filename for.
- @return the appropriate source filename */
- String calcSourcePathForEntryPoint(EndToEndCompileRequest* endToEndReq, Int entryPointIndex);
- String calcSourcePathForEntryPoints(EndToEndCompileRequest* endToEndReq, const List<Int>& entryPointIndices);
-
- class ExtensionTracker : public RefObject
- {
- public:
- };
-
- /* Emits entry point source taking into account if a pass-through or not. Uses 'target' to determine
- the target (not targetReq) */
- SlangResult emitEntryPointsSource(
- BackEndCompileRequest* compileRequest,
- const List<Int>& entryPointIndices,
- TargetRequest* targetReq,
- CodeGenTarget target,
- EndToEndCompileRequest* endToEndReq,
- ExtensionTracker* extensionTracker,
- String& outSource);
-
- SlangResult emitEntryPointSource(
- BackEndCompileRequest* compileRequest,
- Int entryPointIndex,
- TargetRequest* targetReq,
- CodeGenTarget target,
- EndToEndCompileRequest* endToEndReq,
- ExtensionTracker* extensionTracker,
- String& outSource);
-
//
// Information about BaseType that's useful for checking literals