diff options
| author | Yong He <yonghe@outlook.com> | 2025-04-28 11:42:22 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-04-28 11:42:22 -0700 |
| commit | c39c29bf4c52a85d7c83cc8b66ae45e265f9e078 (patch) | |
| tree | 969339828d49d7db92ed9294a17bd34cc021db84 /tools | |
| parent | 8f6c6e333c06ae1c3b9f00396563c14a2ae09b4d (diff) | |
Add Slang Byte Code generation and interpreter. (#6896)
* Add Slang Byte Code generation and interpreter.
* Fix compile issues.
* format code
* More compile fix.
* Fix clang issue.
* Fix more clang issues.
* Another clang fix.
* Fix clang issues.
* Fix another clang issue.
* Fix wasm build.
* Update building.md
* Fix test-server.
* Fix compile error.
* Fix bug.
---------
Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com>
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/CMakeLists.txt | 13 | ||||
| -rw-r--r-- | tools/slang-test/slang-test-main.cpp | 83 | ||||
| -rw-r--r-- | tools/slang-test/slangi-tool-impl.h | 234 | ||||
| -rw-r--r-- | tools/slang-test/slangi-tool.cpp | 10 | ||||
| -rw-r--r-- | tools/slang-test/slangi-tool.h | 19 | ||||
| -rw-r--r-- | tools/slang-unit-test/unit-test-slang-vm.cpp | 102 | ||||
| -rw-r--r-- | tools/slangi/main.cpp | 232 | ||||
| -rw-r--r-- | tools/test-server/test-server-main.cpp | 7 |
8 files changed, 698 insertions, 2 deletions
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 18a50d357..53698726b 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -96,6 +96,19 @@ if(SLANG_ENABLE_SLANGD) ) endif() +# +# Slang Interpreter +# +if(SLANG_ENABLE_SLANGI) + slang_add_target( + slangi + EXECUTABLE + LINK_WITH_PRIVATE core compiler-core slang + INSTALL + EXPORT_SET_NAME SlangTargets + ) +endif() + if(SLANG_ENABLE_GFX) # # `platform` contains all the platform abstractions for a GUI application. diff --git a/tools/slang-test/slang-test-main.cpp b/tools/slang-test/slang-test-main.cpp index 3f7e41cf6..c0697b4a4 100644 --- a/tools/slang-test/slang-test-main.cpp +++ b/tools/slang-test/slang-test-main.cpp @@ -28,6 +28,7 @@ #include "options.h" #include "parse-diagnostic-util.h" #include "slangc-tool.h" +#include "slangi-tool.h" #include "test-context.h" #include "test-reporter.h" @@ -860,7 +861,7 @@ Result spawnAndWaitSharedLibrary( stdWriters.setWriter(SLANG_WRITER_CHANNEL_STD_ERROR, &stdError); stdWriters.setWriter(SLANG_WRITER_CHANNEL_STD_OUTPUT, &stdOut); - if (exeName == "slangc") + if (exeName == "slangc" || exeName == "slangi") { stdWriters.setWriter(SLANG_WRITER_CHANNEL_DIAGNOSTIC, &stdError); } @@ -902,7 +903,7 @@ Result spawnAndWaitProxy( // Get the name of the thing to execute String exeName = Path::getFileNameWithoutExt(inCmdLine.m_executableLocation.m_pathOrName); - if (exeName == "slangc") + if (exeName == "slangc" || exeName == "slangi") { // If the test is slangc there is a command line version we can just directly use // return spawnAndWaitExe(context, testPath, inCmdLine, outRes); @@ -1065,6 +1066,7 @@ static PassThroughFlags _getPassThroughFlagsForTarget(SlangCompileTarget target) case SLANG_CUDA_SOURCE: case SLANG_METAL: case SLANG_WGSL: + case SLANG_HOST_VM: { return 0; } @@ -1303,6 +1305,10 @@ static SlangResult _extractTestRequirements(const CommandLine& cmdLine, TestRequ { return _extractSlangCTestRequirements(cmdLine, ioInfo); } + else if (exeName == "slangi") + { + return SLANG_OK; + } else if (exeName == "slang-reflection-test") { return _extractReflectionTestRequirements(cmdLine, ioInfo); @@ -1562,6 +1568,12 @@ String findExpectedPath(const TestInput& input, const char* postFix) return ""; } +static SlangResult _initSlangInterpreter(TestContext* context, CommandLine& ioCmdLine) +{ + ioCmdLine.setExecutableLocation(ExecutableLocation(context->options.binDir, "slangi")); + return SLANG_OK; +} + static SlangResult _initSlangCompiler(TestContext* context, CommandLine& ioCmdLine) { ioCmdLine.setExecutableLocation(ExecutableLocation(context->options.binDir, "slangc")); @@ -2373,6 +2385,67 @@ TestResult runSimpleLineTest(TestContext* context, TestInput& input) return _validateOutput(context, input, actualOutput, false); } +TestResult runInterpreterTest(TestContext* context, TestInput& input) +{ + // need to execute the stand-alone Slang compiler on the file, and compare its output to what we + // expect + auto outputStem = input.outputStem; + + CommandLine cmdLine; + + List<String> args; + + for (Index i = 0; i < input.testOptions->args.getCount(); i++) + { + auto& arg = input.testOptions->args[i]; + if (arg == "-disasm") + cmdLine.addArg(arg); + else if (arg == "-entry") + { + cmdLine.addArg(arg); + i++; + if (i < input.testOptions->args.getCount()) + { + cmdLine.addArg(input.testOptions->args[i]); + } + } + else + { + args.add(arg); + } + } + + cmdLine.addArg(input.filePath); + + for (auto arg : args) + { + cmdLine.addArg(arg); + } + + if (SLANG_FAILED(_initSlangInterpreter(context, cmdLine))) + { + return TestResult::Ignored; + } + + ExecuteResult exeRes; + TEST_RETURN_ON_DONE(spawnAndWait(context, outputStem, input.spawnType, cmdLine, exeRes)); + + if (context->isCollectingRequirements()) + { + return TestResult::Pass; + } + + String actualOutput = getOutput(exeRes); + + return _validateOutput( + context, + input, + actualOutput, + false, + "result code = 0\nstandard error = {\n}\nstandard output = {\n}\n", + [&input](auto e, auto a) { return _areResultsEqual(input.testOptions->type, e, a); }); +} + TestResult runCompile(TestContext* context, TestInput& input) { auto outputStem = input.outputStem; @@ -3952,6 +4025,7 @@ static const TestCommandInfo s_testCommandInfos[] = { {"SIMPLE", &runSimpleTest, 0}, {"SIMPLE_EX", &runSimpleTest, 0}, {"SIMPLE_LINE", &runSimpleLineTest, 0}, + {"INTERPRET", &runInterpreterTest, 0}, {"REFLECTION", &runReflectionTest, 0}, {"CPU_REFLECTION", &runReflectionTest, 0}, {"COMMAND_LINE_SIMPLE", &runSimpleCompareCommandLineTest, 0}, @@ -4851,6 +4925,11 @@ SlangResult innerMain(int argc, char** argv) context.setInnerMainFunc("slangc", &SlangCTool::innerMain); } + { + // We can set the slangc command line tool, to just use the function defined here + context.setInnerMainFunc("slangi", &SlangITool::innerMain); + } + SLANG_RETURN_ON_FAIL( Options::parse(argc, argv, &categorySet, StdWriters::getError(), &context.options)); diff --git a/tools/slang-test/slangi-tool-impl.h b/tools/slang-test/slangi-tool-impl.h new file mode 100644 index 000000000..b442800f2 --- /dev/null +++ b/tools/slang-test/slangi-tool-impl.h @@ -0,0 +1,234 @@ +namespace SlangITool +{ +static void printCallback(const char* message, void* userData) +{ + auto stdWriters = (StdWriters*)userData; + if (stdWriters) + { + stdWriters->getOut().print("%s", message); + } +} + +static SlangResult compileAndInterpret( + slang::IGlobalSession* sharedSession, + StdWriters* stdWriters, + UnownedStringSlice fileName, + const char* entryPointName, + bool disasm, + int argc, + const char* const* argv) +{ + auto maybePrintDiagnostic = [&](const ComPtr<slang::IBlob>& diagnosticBlob) + { + if (diagnosticBlob) + { + const char* diagText = (const char*)diagnosticBlob->getBufferPointer(); + stdWriters->getError().print("%s\n", diagText); + } + }; + + ComPtr<slang::IGlobalSession> globalSession; + SLANG_RETURN_ON_FAIL(slang_createGlobalSession(SLANG_API_VERSION, globalSession.writeRef())); + slang::TargetDesc targetDesc = {}; + targetDesc.format = SLANG_HOST_VM; + slang::SessionDesc sessionDesc = {}; + sessionDesc.targetCount = 1; + sessionDesc.targets = &targetDesc; + sessionDesc.compilerOptionEntryCount = 0; + String pathName = Path::getParentDirectory(fileName); + String moduleName = Path::getFileNameWithoutExt(fileName); + const char* searchPaths[] = {pathName.getBuffer()}; + if (pathName.getLength()) + { + sessionDesc.searchPathCount = 1; + sessionDesc.searchPaths = searchPaths; + } + ComPtr<slang::ISession> session; + SLANG_RETURN_ON_FAIL(globalSession->createSession(sessionDesc, session.writeRef())); + + ComPtr<slang::IBlob> diagnosticBlob; + auto module = session->loadModule(moduleName.getBuffer(), diagnosticBlob.writeRef()); + if (!module) + { + maybePrintDiagnostic(diagnosticBlob); + return SLANG_FAIL; + } + ComPtr<slang::IEntryPoint> entryPoint; + if (SLANG_FAILED(module->findAndCheckEntryPoint( + entryPointName, + SLANG_STAGE_DISPATCH, + entryPoint.writeRef(), + diagnosticBlob.writeRef()))) + { + maybePrintDiagnostic(diagnosticBlob); + return SLANG_FAIL; + } + + ComPtr<slang::IComponentType> compositeComponent; + slang::IComponentType* components[] = {module, entryPoint.get()}; + if (SLANG_FAILED(session->createCompositeComponentType( + components, + 2, + compositeComponent.writeRef(), + diagnosticBlob.writeRef()))) + { + maybePrintDiagnostic(diagnosticBlob); + return SLANG_FAIL; + } + + ComPtr<slang::IComponentType> linkedProgram; + if (SLANG_FAILED(compositeComponent->link(linkedProgram.writeRef(), diagnosticBlob.writeRef()))) + { + maybePrintDiagnostic(diagnosticBlob); + return SLANG_FAIL; + } + ComPtr<slang::IBlob> code; + + if (SLANG_FAILED(linkedProgram->getTargetCode(0, code.writeRef(), diagnosticBlob.writeRef()))) + { + maybePrintDiagnostic(diagnosticBlob); + return SLANG_FAIL; + } + + if (code->getBufferSize() == 0) + { + return SLANG_FAIL; + } + + if (disasm) + { + ComPtr<slang::IBlob> disasmBlob; + if (SLANG_FAILED(slang_disassembleByteCode(code, disasmBlob.writeRef()))) + { + maybePrintDiagnostic(diagnosticBlob); + return SLANG_FAIL; + } + const char* disasmText = (const char*)disasmBlob->getBufferPointer(); + stdWriters->getOut().print("%s\n", disasmText); + return SLANG_OK; + } + + // Create a byte code runner and interpret the code. + ComPtr<slang::IByteCodeRunner> runner; + slang::ByteCodeRunnerDesc runnerDesc = {}; + SLANG_RETURN_ON_FAIL(slang_createByteCodeRunner(&runnerDesc, runner.writeRef())); + runner->setPrintCallback(printCallback, stdWriters); + + if (SLANG_FAILED(runner->loadModule(code))) + { + runner->getErrorString(diagnosticBlob.writeRef()); + maybePrintDiagnostic(diagnosticBlob); + } + auto funcIndex = runner->findFunctionByName(entryPointName); + if (funcIndex < 0) + { + stdWriters->getError().print("Function '%s' not found in byte code.\n", entryPointName); + return SLANG_FAIL; + } + + if (SLANG_FAILED(runner->selectFunctionByIndex((uint32_t)funcIndex))) + { + runner->getErrorString(diagnosticBlob.writeRef()); + maybePrintDiagnostic(diagnosticBlob); + return SLANG_FAIL; + } + + struct Arguments + { + uint32_t argc; + const char* const* argv; + }; + Arguments args; + args.argc = argc; + args.argv = argv; + void* arguments = nullptr; + size_t argSize = 0; + slang::ByteCodeFuncInfo funcInfo; + if (SLANG_FAILED(runner->getFunctionInfo((uint32_t)funcIndex, &funcInfo))) + { + runner->getErrorString(diagnosticBlob.writeRef()); + maybePrintDiagnostic(diagnosticBlob); + return SLANG_FAIL; + } + if (funcInfo.parameterCount == 2) + { + arguments = &args; + argSize = sizeof(Arguments); + } + if (SLANG_FAILED(runner->execute(arguments, argSize))) + { + runner->getErrorString(diagnosticBlob.writeRef()); + maybePrintDiagnostic(diagnosticBlob); + return SLANG_FAIL; + } + return SLANG_OK; +} + +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. + // 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())); + } + + String entryPointName = toSlice("main"); + UnownedStringSlice fileName; + bool disasm = false; + int innerArgIndex = 0; + if (argc < 2) + { + return SLANG_FAIL; + } + for (auto i = 1; i < argc; i++) + { + auto arg = UnownedStringSlice(argv[i]); + if (arg == "-entry") + { + entryPointName = UnownedStringSlice(argv[++i]); + } + else if (arg == "-disasm") + { + disasm = true; + } + else if (arg.startsWith("-")) + { + return SLANG_FAIL; + } + else + { + fileName = arg; + innerArgIndex = i; + break; + } + } + if (!fileName.getLength()) + { + return SLANG_FAIL; + } + + auto result = compileAndInterpret( + session, + stdWriters, + fileName, + entryPointName.getBuffer(), + disasm, + argc - innerArgIndex, + argv + innerArgIndex); + + return result; +} +} // namespace SlangITool diff --git a/tools/slang-test/slangi-tool.cpp b/tools/slang-test/slangi-tool.cpp new file mode 100644 index 000000000..ef9d311f7 --- /dev/null +++ b/tools/slang-test/slangi-tool.cpp @@ -0,0 +1,10 @@ +// test-context.cpp +#include "slangi-tool.h" + +#include "../../source/core/slang-exception.h" +#include "../../source/core/slang-io.h" +#include "../../source/core/slang-test-tool-util.h" + +using namespace Slang; + +#include "slangi-tool-impl.h" diff --git a/tools/slang-test/slangi-tool.h b/tools/slang-test/slangi-tool.h new file mode 100644 index 000000000..1cba47018 --- /dev/null +++ b/tools/slang-test/slangi-tool.h @@ -0,0 +1,19 @@ +// slangi-tool.h + +#ifndef SLANGI_TOOL_H_INCLUDED +#define SLANGI_TOOL_H_INCLUDED + +#include "../../source/core/slang-std-writers.h" + +/* The slangi 'tool' interface, such that slangc like functionality is available directly without +invoking slangc command line tool, or need for a dll/shared library. */ +namespace SlangITool +{ +SlangResult innerMain( + Slang::StdWriters* stdWriters, + SlangSession* session, + int argc, + const char* const* argv); +}; + +#endif // SLANGI_TOOL_H_INCLUDED diff --git a/tools/slang-unit-test/unit-test-slang-vm.cpp b/tools/slang-unit-test/unit-test-slang-vm.cpp new file mode 100644 index 000000000..0f5e0f9f3 --- /dev/null +++ b/tools/slang-unit-test/unit-test-slang-vm.cpp @@ -0,0 +1,102 @@ +// unit-test-slang-vm.cpp + +#include "core/slang-memory-file-system.h" +#include "slang-com-ptr.h" +#include "slang.h" +#include "unit-test/slang-unit-test.h" + +#include <stdio.h> +#include <stdlib.h> + +using namespace Slang; + +SLANG_UNIT_TEST(slangVM) +{ + const char* testSource = R"( + int one() { return 1; } + int sum(int x) + { + int result = 0; + for (int i = 0; i <= x; i++) + { + result += i; + } + return result + one(); + } + [shader("dispatch")] + int dispatchMain(uniform int2 v, out int c) + { + int a = v.x; + int b = v.y; + int tmp = 0; + if (a > 0) + tmp = a + b; + else + tmp = b - a; + tmp += sum(b); + c = tmp; + return 100; + } + )"; + + // Create Slang session and compile code. + ComPtr<slang::IBlob> code; + String disasmText; + { + ComPtr<slang::IGlobalSession> globalSession; + SLANG_CHECK( + slang_createGlobalSession(SLANG_API_VERSION, globalSession.writeRef()) == SLANG_OK); + slang::TargetDesc targetDesc = {}; + targetDesc.format = SLANG_HOST_VM; + slang::SessionDesc sessionDesc = {}; + sessionDesc.targetCount = 1; + sessionDesc.targets = &targetDesc; + sessionDesc.compilerOptionEntryCount = 0; + + ComPtr<slang::ISession> session; + SLANG_CHECK(globalSession->createSession(sessionDesc, session.writeRef()) == SLANG_OK); + + ComPtr<slang::IBlob> diagnosticBlob; + auto module = session->loadModuleFromSourceString( + "test", + "test.slang", + testSource, + diagnosticBlob.writeRef()); + SLANG_CHECK(module != nullptr); + + ComPtr<slang::IComponentType> linkedProgram; + module->link(linkedProgram.writeRef()); + + + linkedProgram->getTargetCode(0, code.writeRef(), diagnosticBlob.writeRef()); + + SLANG_CHECK(code->getBufferSize() > 0); + + ComPtr<slang::IBlob> disasmBlob; + SLANG_CHECK(slang_disassembleByteCode(code, disasmBlob.writeRef()) == SLANG_OK); + disasmText = (const char*)disasmBlob->getBufferPointer(); + SLANG_CHECK(disasmText.indexOf("ret") != -1); + } + + // Create a byte code runner and interpret the code. + ComPtr<slang::IByteCodeRunner> runner; + slang::ByteCodeRunnerDesc runnerDesc = {}; + SLANG_CHECK(slang_createByteCodeRunner(&runnerDesc, runner.writeRef()) == SLANG_OK); + SLANG_CHECK(runner->loadModule(code) == SLANG_OK); + SLANG_CHECK(runner->selectFunctionByIndex(0) == SLANG_OK); + struct Params + { + int a; + int b; + int* result; + }; + int result = 0; + Params params = {1, 2, &result}; + SLANG_CHECK(runner->execute(¶ms, sizeof(params)) == SLANG_OK); + SLANG_CHECK(result == 7); + + size_t returnValSize = 0; + int* returnVal = (int*)runner->getReturnValue(&returnValSize); + SLANG_CHECK(returnValSize == sizeof(int)); + SLANG_CHECK(*returnVal == 100); +} diff --git a/tools/slangi/main.cpp b/tools/slangi/main.cpp new file mode 100644 index 000000000..2ef680324 --- /dev/null +++ b/tools/slangi/main.cpp @@ -0,0 +1,232 @@ +// main.cpp + +// This file implements the entry point for `slangi`, an interpreter for the Slang language. + +#include "../../source/core/slang-basic.h" +#include "core/slang-io.h" +#include "slang-com-ptr.h" +#include "slang.h" + +using namespace Slang; +using namespace slang; + +void printUsage() +{ + printf("Slang Interpreter (Experimental)\n"); + printf("Compile and interpret Slang code.\n"); + printf("Usage: slangi [options] <filename>\n"); + printf("Options:\n"); + printf(" -entry <name> Specify the entry point function name to run. (default: main)\n"); + printf(" -disasm Disassemble the bytecode after compilation.\n"); + printf(" -help Show this help message\n"); +} + +void maybePrintDiagnostic(const ComPtr<slang::IBlob>& diagnosticBlob) +{ + if (diagnosticBlob) + { + const char* diagText = (const char*)diagnosticBlob->getBufferPointer(); + fprintf(stderr, "%s\n", diagText); + } +} + +SlangResult compileAndInterpret( + UnownedStringSlice fileName, + const char* entryPointName, + bool disasm, + int argc, + const char* const* argv) +{ + ComPtr<slang::IGlobalSession> globalSession; + SLANG_RETURN_ON_FAIL(slang_createGlobalSession(SLANG_API_VERSION, globalSession.writeRef())); + slang::TargetDesc targetDesc = {}; + targetDesc.format = SLANG_HOST_VM; + slang::SessionDesc sessionDesc = {}; + sessionDesc.targetCount = 1; + sessionDesc.targets = &targetDesc; + sessionDesc.compilerOptionEntryCount = 0; + String pathName = Path::getParentDirectory(fileName); + String moduleName = Path::getFileNameWithoutExt(fileName); + const char* searchPaths[] = {pathName.getBuffer()}; + if (pathName.getLength()) + { + sessionDesc.searchPathCount = 1; + sessionDesc.searchPaths = searchPaths; + } + ComPtr<slang::ISession> session; + SLANG_RETURN_ON_FAIL(globalSession->createSession(sessionDesc, session.writeRef())); + + ComPtr<slang::IBlob> diagnosticBlob; + auto module = session->loadModule(moduleName.getBuffer(), diagnosticBlob.writeRef()); + if (!module) + { + maybePrintDiagnostic(diagnosticBlob); + return SLANG_FAIL; + } + ComPtr<slang::IEntryPoint> entryPoint; + if (SLANG_FAILED(module->findAndCheckEntryPoint( + entryPointName, + SLANG_STAGE_DISPATCH, + entryPoint.writeRef(), + diagnosticBlob.writeRef()))) + { + maybePrintDiagnostic(diagnosticBlob); + return SLANG_FAIL; + } + + ComPtr<slang::IComponentType> compositeComponent; + slang::IComponentType* components[] = {module, entryPoint.get()}; + if (SLANG_FAILED(session->createCompositeComponentType( + components, + 2, + compositeComponent.writeRef(), + diagnosticBlob.writeRef()))) + { + maybePrintDiagnostic(diagnosticBlob); + return SLANG_FAIL; + } + + ComPtr<slang::IComponentType> linkedProgram; + if (SLANG_FAILED(compositeComponent->link(linkedProgram.writeRef(), diagnosticBlob.writeRef()))) + { + maybePrintDiagnostic(diagnosticBlob); + return SLANG_FAIL; + } + ComPtr<slang::IBlob> code; + + if (SLANG_FAILED(linkedProgram->getTargetCode(0, code.writeRef(), diagnosticBlob.writeRef()))) + { + maybePrintDiagnostic(diagnosticBlob); + return SLANG_FAIL; + } + + if (code->getBufferSize() == 0) + { + return SLANG_FAIL; + } + + if (disasm) + { + ComPtr<slang::IBlob> disasmBlob; + if (SLANG_FAILED(slang_disassembleByteCode(code, disasmBlob.writeRef()))) + { + maybePrintDiagnostic(diagnosticBlob); + return SLANG_FAIL; + } + const char* disasmText = (const char*)disasmBlob->getBufferPointer(); + printf("%s\n", disasmText); + } + + // Create a byte code runner and interpret the code. + ComPtr<slang::IByteCodeRunner> runner; + slang::ByteCodeRunnerDesc runnerDesc = {}; + SLANG_RETURN_ON_FAIL(slang_createByteCodeRunner(&runnerDesc, runner.writeRef())); + if (SLANG_FAILED(runner->loadModule(code))) + { + runner->getErrorString(diagnosticBlob.writeRef()); + maybePrintDiagnostic(diagnosticBlob); + } + auto funcIndex = runner->findFunctionByName(entryPointName); + if (funcIndex < 0) + { + printf("Function '%s' not found in byte code.\n", entryPointName); + return SLANG_FAIL; + } + + if (SLANG_FAILED(runner->selectFunctionByIndex((uint32_t)funcIndex))) + { + runner->getErrorString(diagnosticBlob.writeRef()); + maybePrintDiagnostic(diagnosticBlob); + return SLANG_FAIL; + } + + struct Arguments + { + uint32_t argc; + const char* const* argv; + }; + Arguments args; + args.argc = argc; + args.argv = argv; + void* arguments = nullptr; + size_t argSize = 0; + slang::ByteCodeFuncInfo funcInfo; + if (SLANG_FAILED(runner->getFunctionInfo((uint32_t)funcIndex, &funcInfo))) + { + runner->getErrorString(diagnosticBlob.writeRef()); + maybePrintDiagnostic(diagnosticBlob); + return SLANG_FAIL; + } + if (funcInfo.parameterCount == 2) + { + arguments = &args; + argSize = sizeof(Arguments); + } + if (SLANG_FAILED(runner->execute(arguments, argSize))) + { + runner->getErrorString(diagnosticBlob.writeRef()); + maybePrintDiagnostic(diagnosticBlob); + return SLANG_FAIL; + } + size_t returnValueSize = 0; + void* returnVal = runner->getReturnValue(&returnValueSize); + SlangResult result = SLANG_OK; + memcpy(&result, returnVal, returnValueSize); + return result; +} + +int main(int argc, const char* const* argv) +{ + String entryPointName = toSlice("main"); + UnownedStringSlice fileName; + bool disasm = false; + int innerArgIndex = 0; + if (argc < 2) + { + printUsage(); + return 0; + } + for (auto i = 1; i < argc; i++) + { + auto arg = UnownedStringSlice(argv[i]); + if (arg == "-entry") + { + entryPointName = UnownedStringSlice(argv[++i]); + } + else if (arg == "-help" || arg == "--help") + { + printUsage(); + return 0; + } + else if (arg == "-disasm") + { + disasm = true; + } + else if (arg.startsWith("-")) + { + fprintf(stderr, "Unknown option: %s\n", arg.begin()); + printUsage(); + return -1; + } + else + { + fileName = arg; + innerArgIndex = i; + break; + } + } + if (!fileName.getLength()) + { + printUsage(); + return 0; + } + + auto result = compileAndInterpret( + fileName, + entryPointName.getBuffer(), + disasm, + argc - innerArgIndex, + argv + innerArgIndex); + slang::shutdown(); + return result; +} diff --git a/tools/test-server/test-server-main.cpp b/tools/test-server/test-server-main.cpp index 633a23d7e..63535ec92 100644 --- a/tools/test-server/test-server-main.cpp +++ b/tools/test-server/test-server-main.cpp @@ -188,6 +188,9 @@ SlangResult innerMain( } // namespace SlangCTool +// SlangITool +#include "../slang-test/slangi-tool-impl.h" + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!! TestServer !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ SlangResult TestServer::init(int argc, const char* const* argv) @@ -308,6 +311,10 @@ TestServer::InnerMainFunc TestServer::getToolFunction(const String& name, Diagno { return &SlangCTool::innerMain; } + else if (name == "slangi") + { + return &SlangITool::innerMain; + } StringBuilder sharedLibToolBuilder; sharedLibToolBuilder.append(name); |
