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
|
// main.cpp
#include "slang.h"
SLANG_API void spSetCommandLineCompilerMode(SlangCompileRequest* request);
#include "../core/slang-io.h"
#include "../core/slang-test-tool-util.h"
using namespace Slang;
#include <assert.h>
#ifdef _WIN32
#define MAIN slangc_main
#else
#define MAIN main
#endif
static void _diagnosticCallback(char const* message, void* /*userData*/)
{
auto stdError = StdWriters::getError();
stdError.put(message);
stdError.flush();
}
static SlangResult _compile(SlangCompileRequest* compileRequest, int argc, const char* const* argv)
{
spSetDiagnosticCallback(compileRequest, &_diagnosticCallback, nullptr);
spSetCommandLineCompilerMode(compileRequest);
char const* appName = "slangc";
if (argc > 0)
appName = argv[0];
{
const SlangResult res = spProcessCommandLineArguments(compileRequest, &argv[1], argc - 1);
if (SLANG_FAILED(res))
{
// TODO: print usage message
return res;
}
}
SlangResult res = SLANG_OK;
#ifndef _DEBUG
try
#endif
{
// Run the compiler (this will produce any diagnostics through
// SLANG_WRITER_TARGET_TYPE_DIAGNOSTIC).
res = spCompile(compileRequest);
// If the compilation failed, then get out of here...
// Turn into an internal Result -> such that return code can be used to vary result to match
// previous behavior
res = SLANG_FAILED(res) ? SLANG_E_INTERNAL_FAIL : res;
}
#ifndef _DEBUG
catch (const Exception& e)
{
StdWriters::getOut().print("internal compiler error: %S\n", e.Message.toWString().begin());
res = SLANG_FAIL;
}
#endif
return res;
}
bool shouldEmbedPrelude(const char* const* argv, int argc)
{
for (int i = 0; i < argc; i++)
{
if (UnownedStringSlice(argv[i]) == "-embed-prelude")
return true;
}
return false;
}
SLANG_TEST_TOOL_API SlangResult innerMain(
StdWriters* stdWriters,
slang::IGlobalSession* sharedSession,
int argc,
const char* const* argv)
{
StdWriters::setSingleton(stdWriters);
// Assume we will used the shared session
ComPtr<slang::IGlobalSession> session(sharedSession);
// The sharedSession always has a pre-loaded core module, is sharedSession is not nullptr.
// This differed test checks if the command line has an option to setup the core module.
// If so we *don't* use the sharedSession, and create a new session without the core module just
// for this compilation.
if (TestToolUtil::hasDeferredCoreModule(Index(argc - 1), argv + 1))
{
SLANG_RETURN_ON_FAIL(
slang_createGlobalSessionWithoutCoreModule(SLANG_API_VERSION, session.writeRef()));
}
else if (!session)
{
// Just create the global session in the regular way if there isn't one set
SlangGlobalSessionDesc desc = {};
desc.enableGLSL = true;
SLANG_RETURN_ON_FAIL(slang_createGlobalSession2(&desc, session.writeRef()));
}
if (!shouldEmbedPrelude(argv, argc))
TestToolUtil::setSessionDefaultPreludeFromExePath(argv[0], session);
SlangCompileRequest* compileRequest = spCreateCompileRequest(session);
compileRequest->addSearchPath(Path::getParentDirectory(Path::getExecutablePath()).getBuffer());
SlangResult res = _compile(compileRequest, argc, argv);
// Now that we are done, clean up after ourselves
spDestroyCompileRequest(compileRequest);
return res;
}
int MAIN(int argc, char** argv)
{
auto stdWriters = StdWriters::initDefaultSingleton();
SlangResult res = innerMain(stdWriters, nullptr, argc, argv);
slang::shutdown();
return (int)TestToolUtil::getReturnCode(res);
}
#ifdef _WIN32
int wmain(int argc, wchar_t** argv)
{
int result = 0;
{
// Convert 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].getBuffer());
}
result = MAIN(argc, (char**)&argBuffers[0]);
}
#ifdef _MSC_VER
// _CrtXXX functions are functional only for debug build. The spec says,
// "When _DEBUG isn't defined, calls to _CrtSetReportMode are removed
// during preprocessing."
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
int memleakDetected = _CrtDumpMemoryLeaks();
SLANG_UNUSED(memleakDetected);
assert(!memleakDetected);
#endif
return result;
}
#endif
|