1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
|
// slang-check.cpp
#include "slang-check.h"
// This file provides general facilities related to semantic
// checking that don't cleanly land in one of the more
// specialized `slang-check-*` files.
#include "../core/slang-type-text-util.h"
#include "slang-check-impl.h"
namespace Slang
{
namespace
{ // anonymous
class SinkSharedLibraryLoader : public RefObject, public ISlangSharedLibraryLoader
{
public:
SLANG_REF_OBJECT_IUNKNOWN_ALL
virtual SLANG_NO_THROW SlangResult SLANG_MCALL
loadSharedLibrary(const char* path, ISlangSharedLibrary** outSharedLibrary) SLANG_OVERRIDE
{
SlangResult res = m_loader->loadSharedLibrary(path, outSharedLibrary);
// Special handling for failure...
if (SLANG_FAILED(res) && m_sink)
{
String filename = Path::getFileNameWithoutExt(path);
if (filename == "dxil")
{
m_sink->diagnose(SourceLoc(), Diagnostics::dxilNotFound);
}
else
{
m_sink->diagnose(SourceLoc(), Diagnostics::noteFailedToLoadDynamicLibrary, path);
}
}
return res;
}
SinkSharedLibraryLoader(ISlangSharedLibraryLoader* loader, DiagnosticSink* sink)
: m_loader(loader), m_sink(sink)
{
}
protected:
ISlangUnknown* getInterface(const Guid& guid)
{
return (guid == ISlangUnknown::getTypeGuid() ||
guid == ISlangSharedLibraryLoader::getTypeGuid())
? static_cast<ISlangSharedLibraryLoader*>(this)
: nullptr;
}
ISlangSharedLibraryLoader* m_loader;
DiagnosticSink* m_sink;
};
} // namespace
void Session::_setSharedLibraryLoader(ISlangSharedLibraryLoader* loader)
{
if (m_sharedLibraryLoader != loader)
{
// Need to clear all of the libraries
m_downstreamCompilerSet->clear();
m_downstreamCompilerInitialized = 0;
for (Index i = 0; i < Index(SLANG_PASS_THROUGH_COUNT_OF); ++i)
{
m_downstreamCompilers[i].setNull();
}
// Set the loader
m_sharedLibraryLoader = loader;
}
}
void Session::resetDownstreamCompiler(PassThroughMode type)
{
// Mark as initialized
m_downstreamCompilerInitialized &= ~(1 << int(type));
m_downstreamCompilers[int(type)].setNull();
}
IDownstreamCompiler* Session::getOrLoadDownstreamCompiler(
PassThroughMode type,
DiagnosticSink* sink)
{
if (m_downstreamCompilerInitialized & (1 << int(type)))
{
return m_downstreamCompilers[int(type)];
}
if (type == PassThroughMode::GenericCCpp)
{
// try testing for availability on all C/C++ compilers
getOrLoadDownstreamCompiler(PassThroughMode::Clang, nullptr);
getOrLoadDownstreamCompiler(PassThroughMode::Gcc, nullptr);
getOrLoadDownstreamCompiler(PassThroughMode::VisualStudio, nullptr);
getOrLoadDownstreamCompiler(PassThroughMode::LLVM, nullptr);
}
// Mark that we have tried to load it
m_downstreamCompilerInitialized |= (1 << int(type));
m_downstreamCompilers[int(type)].setNull();
// Do we have a locator
auto locator = m_downstreamCompilerLocators[int(type)];
if (locator)
{
m_downstreamCompilerSet->remove(SlangPassThrough(type));
// We want to be able to report a diagnostic to the user if a loader
// was unable to locate the desired downstream compiler, but we
// also need to deal with the fact that the locator might "probe"
// multiple possible library versions/names, and failing to load
// one library should not be taken as a hard error.
//
// The approach we use here is to first apply the `locator` directly
// with our `m_sharedLibraryLoader` and see if it succeeds. If
// it does, then we will move along.
//
if (SLANG_FAILED(locator(
m_downstreamCompilerPaths[int(type)],
m_sharedLibraryLoader,
m_downstreamCompilerSet)))
{
// If the locator reported a failure the first time we invoked
// it, then we will invoke it against with a wrapper shared library
// loader that reported library load failures to our diagnost `sink`.
//
// This means that in the case of failure the user will see a listing
// of all the libraries that the locator attempted to load but failed
// to find. The user will know that making one or more of these libraries
// available could fix the issue, but we cannot communicate precise
// information to them with this approach (e.g., the difference between
// "I need all of these libraries" vs. "I need at least one of these
// libraries").
//
if (sink)
{
sink->diagnose(SourceLoc(), Diagnostics::failedToLoadDownstreamCompiler, type);
}
SinkSharedLibraryLoader loader(m_sharedLibraryLoader, sink);
locator(m_downstreamCompilerPaths[int(type)], &loader, m_downstreamCompilerSet);
}
DownstreamCompilerUtil::updateDefaults(m_downstreamCompilerSet);
}
IDownstreamCompiler* compiler = nullptr;
if (type == PassThroughMode::GenericCCpp)
{
compiler = m_downstreamCompilerSet->getDefaultCompiler(SLANG_SOURCE_LANGUAGE_CPP);
}
else
{
DownstreamCompilerDesc desc;
desc.type = SlangPassThrough(type);
compiler = DownstreamCompilerUtil::findCompiler(
m_downstreamCompilerSet,
DownstreamCompilerUtil::MatchType::Newest,
desc);
}
m_downstreamCompilers[int(type)] = compiler;
return compiler;
}
void checkTranslationUnit(
TranslationUnitRequest* translationUnit,
LoadedModuleDictionary& loadedModules)
{
SLANG_AST_BUILDER_RAII(translationUnit->compileRequest->getLinkage()->getASTBuilder());
SharedSemanticsContext sharedSemanticsContext(
translationUnit->compileRequest->getLinkage(),
translationUnit->getModule(),
translationUnit->compileRequest->getSink(),
&loadedModules,
translationUnit);
SemanticsDeclVisitorBase visitor((SemanticsContext(&sharedSemanticsContext)));
// Apply the visitor to do the main semantic
// checking that is required on all declarations
// in the translation unit.
visitor.checkModule(translationUnit->getModuleDecl());
translationUnit->getModule()->_collectShaderParams();
}
void SemanticsVisitor::dispatchStmt(Stmt* stmt, SemanticsContext const& context)
{
SemanticsStmtVisitor visitor(context);
try
{
visitor.dispatch(stmt);
}
catch (const AbortCompilationException&)
{
throw;
}
catch (...)
{
getSink()->noteInternalErrorLoc(stmt->loc);
throw;
}
}
Expr* SemanticsVisitor::dispatchExpr(Expr* expr, SemanticsContext const& context)
{
SemanticsExprVisitor visitor(context);
try
{
return visitor.dispatch(expr);
}
catch (const AbortCompilationException&)
{
throw;
}
catch (...)
{
getSink()->noteInternalErrorLoc(expr->loc);
throw;
}
}
ASTBuilder* semanticsVisitorGetASTBuilder(SemanticsVisitor* sv)
{
return sv->getASTBuilder();
}
} // namespace Slang
|