summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2022-06-21 09:25:51 -0700
committerGitHub <noreply@github.com>2022-06-21 09:25:51 -0700
commit92dfec2320421113498ae7b5b72e78bd8b5b09a8 (patch)
tree94abc8d02468c50112841a86ee2843024d22d51b
parentd2a467c7a941c4453b3d825c9d5bb4d72230c8ba (diff)
Add CPU executable compile test (#2278)
* Add cpu executable compile test * Fix. * Fix permission on linux * retrigger build Co-authored-by: Yong He <yhe@nvidia.com>
-rw-r--r--source/slang/slang-emit-cpp.cpp9
-rw-r--r--tests/cpu-program/cpu-hello-world.slang9
-rw-r--r--tests/cpu-program/cpu-hello-world.slang.expected6
-rw-r--r--tools/slang-test/slang-test-main.cpp138
4 files changed, 152 insertions, 10 deletions
diff --git a/source/slang/slang-emit-cpp.cpp b/source/slang/slang-emit-cpp.cpp
index c23135c70..31f09e400 100644
--- a/source/slang/slang-emit-cpp.cpp
+++ b/source/slang/slang-emit-cpp.cpp
@@ -2595,6 +2595,15 @@ void CPPSourceEmitter::_maybeEmitExportLike(IRInst* inst)
// Specially handle export, as we don't want to emit it multiple times
if (getTargetReq()->isWholeProgramRequest())
{
+ if (auto nameHint = inst->findDecoration<IRNameHintDecoration>())
+ {
+ if (nameHint->getName() == "main")
+ {
+ // Don't output any decorations on main function.
+ return;
+ }
+ }
+
bool isExternC = false;
bool isExported = false;
diff --git a/tests/cpu-program/cpu-hello-world.slang b/tests/cpu-program/cpu-hello-world.slang
new file mode 100644
index 000000000..9385b239c
--- /dev/null
+++ b/tests/cpu-program/cpu-hello-world.slang
@@ -0,0 +1,9 @@
+//TEST:EXECUTABLE:
+__target_intrinsic(cpp, "printf(\"%s\\n\", ($0).getBuffer())")
+void writeln(String text);
+
+public __extern_cpp int main()
+{
+ writeln("Hello World.");
+ return 0;
+} \ No newline at end of file
diff --git a/tests/cpu-program/cpu-hello-world.slang.expected b/tests/cpu-program/cpu-hello-world.slang.expected
new file mode 100644
index 000000000..81531657f
--- /dev/null
+++ b/tests/cpu-program/cpu-hello-world.slang.expected
@@ -0,0 +1,6 @@
+result code = 0
+standard error = {
+}
+standard output = {
+Hello World.
+}
diff --git a/tools/slang-test/slang-test-main.cpp b/tools/slang-test/slang-test-main.cpp
index f80521707..7e504da74 100644
--- a/tools/slang-test/slang-test-main.cpp
+++ b/tools/slang-test/slang-test-main.cpp
@@ -1269,6 +1269,15 @@ static bool _areResultsEqual(TestOptions::Type type, const String& a, const Stri
}
}
+static String _calcModulePath(const TestInput& input)
+{
+ // Make the module name the same as the source file
+ auto filePath = input.filePath;
+ String directory = Path::getParentDirectory(input.outputStem);
+ String moduleName = Path::getFileNameWithoutExt(filePath);
+ return Path::combine(directory, moduleName);
+}
+
TestResult runDocTest(TestContext* context, TestInput& input)
{
// need to execute the stand-alone Slang compiler on the file, and compare its output to what we expect
@@ -1330,6 +1339,124 @@ TestResult runDocTest(TestContext* context, TestInput& input)
return result;
}
+TestResult runExecutableTest(TestContext* context, TestInput& input)
+{
+ DownstreamCompiler* compiler = context->getDefaultCompiler(SLANG_SOURCE_LANGUAGE_CPP);
+ if (!compiler)
+ {
+ return TestResult::Ignored;
+ }
+
+ // If we are just collecting requirements, say it passed
+ if (context->isCollectingRequirements())
+ {
+ std::lock_guard<std::mutex> lock(context->mutex);
+ context->getTestRequirements()->addUsedBackEnd(SLANG_PASS_THROUGH_GENERIC_C_CPP);
+ return TestResult::Pass;
+ }
+
+ auto filePath = input.filePath;
+ auto outputStem = input.outputStem;
+
+ String actualOutputPath = outputStem + ".actual";
+ File::remove(actualOutputPath);
+
+ // Make the module name the same as the source file
+ String ext = Path::getPathExt(filePath);
+ String modulePath = _calcModulePath(input);
+
+ // Remove the binary..
+ String moduleExePath;
+ {
+ StringBuilder buf;
+ buf << modulePath;
+ buf << Process::getExecutableSuffix();
+ moduleExePath = buf;
+ }
+
+ // Remove the exe if it exists
+ File::remove(moduleExePath);
+
+ CommandLine cmdLine;
+ _initSlangCompiler(context, cmdLine);
+
+ StringEscapeHandler* escapeHandler = StringEscapeUtil::getHandler(StringEscapeUtil::Style::Space);
+
+ List<String> args;
+ args.add(filePath);
+ args.add("-o");
+ args.add(moduleExePath);
+ args.add("-target");
+ args.add("exe");
+ for (auto arg : args)
+ {
+ // If unescaping is needed, do it
+ if (StringEscapeUtil::isUnescapeShellLikeNeeded(escapeHandler, arg.getUnownedSlice()))
+ {
+ StringBuilder buf;
+ StringEscapeUtil::unescapeShellLike(escapeHandler, arg.getUnownedSlice(), buf);
+ cmdLine.addArg(buf.ProduceString());
+ }
+ else
+ {
+ cmdLine.addArg(arg);
+ }
+ }
+ ExecuteResult exeRes;
+ TEST_RETURN_ON_DONE(spawnAndWait(context, outputStem, input.spawnType, cmdLine, exeRes));
+
+ String actualOutput;
+
+ // If the actual compilation failed, then the output will be the summary
+ if (exeRes.resultCode != 0)
+ {
+ actualOutput = getOutput(exeRes);
+ }
+ else
+ {
+ // Execute the binary and see what we get
+ CommandLine cmdLine;
+
+ ExecutableLocation exe;
+ exe.setPath(moduleExePath);
+
+ cmdLine.setExecutableLocation(exe);
+
+ File::makeExecutable(moduleExePath);
+
+ ExecuteResult exeRes;
+ if (SLANG_FAILED(ProcessUtil::execute(cmdLine, exeRes)))
+ {
+ return TestResult::Fail;
+ }
+
+ // Write the output, and compare to expected
+ actualOutput = getOutput(exeRes);
+ }
+
+ // Write the output
+ Slang::File::writeAllText(actualOutputPath, actualOutput);
+
+ // Check that they are the same
+ {
+ // Read the expected
+ String expectedOutput;
+
+ String expectedOutputPath = outputStem + ".expected";
+ Slang::File::readAllText(expectedOutputPath, expectedOutput);
+
+ // Compare if they are the same
+ if (!StringUtil::areLinesEqual(
+ actualOutput.getUnownedSlice(), expectedOutput.getUnownedSlice()))
+ {
+ context->getTestReporter()->dumpOutputDifference(expectedOutput, actualOutput);
+ return TestResult::Fail;
+ }
+ }
+
+ return TestResult::Pass;
+}
+
TestResult runLanguageServerTest(TestContext* context, TestInput& input)
{
RefPtr<JSONRPCConnection> connection;
@@ -1984,15 +2111,6 @@ static String _calcSummary(const DownstreamDiagnostics& inOutput)
return builder;
}
-static String _calcModulePath(const TestInput& input)
-{
- // Make the module name the same as the source file
- auto filePath = input.filePath;
- String directory = Path::getParentDirectory(input.outputStem);
- String moduleName = Path::getFileNameWithoutExt(filePath);
- return Path::combine(directory, moduleName);
-}
-
static TestResult runCPPCompilerCompile(TestContext* context, TestInput& input)
{
DownstreamCompiler* compiler = context->getDefaultCompiler(SLANG_SOURCE_LANGUAGE_CPP);
@@ -3257,7 +3375,7 @@ static const TestCommandInfo s_testCommandInfos[] =
{ "COMPILE", &runCompile, 0 },
{ "DOC", &runDocTest, 0 },
{ "LANG_SERVER", &runLanguageServerTest, 0},
-
+ { "EXECUTABLE", &runExecutableTest, RenderApiFlag::CPU}
};
const TestCommandInfo* _findTestCommandInfoByCommand(const UnownedStringSlice& name)