diff --git a/.run/spice.run.xml b/.run/spice.run.xml index b74e2481f..efc46a910 100644 --- a/.run/spice.run.xml +++ b/.run/spice.run.xml @@ -1,5 +1,5 @@ - + diff --git a/docs/docs/cli/build.md b/docs/docs/cli/build.md index 00c6b7db5..f7433ffb9 100644 --- a/docs/docs/cli/build.md +++ b/docs/docs/cli/build.md @@ -25,6 +25,7 @@ You can apply following options to the `build` subcommand: | `-cst` | `--dump-cst` | Dump CST as serialized string and SVG image | | `-ast` | `--dump-ast` | Dump AST as serialized string and SVG image | | `-symtab` | `--dump-symtab` | Dump serialized symbol tables | +| `-types` | `--dump-types` | Dump all used types | | `-ir` | `--dump-ir` | Dump LLVM-IR | | `-s`, `-asm` | `--dump-assembly` | Dump Assembly code | | `-b`, `-obj` | `--dump-object-file` | Dump object files | diff --git a/docs/docs/cli/install.md b/docs/docs/cli/install.md index 1fd833892..b1785d033 100644 --- a/docs/docs/cli/install.md +++ b/docs/docs/cli/install.md @@ -25,6 +25,7 @@ You can apply following options to the `install` subcommand: | `-cst` | `--dump-cst` | Dump CST as serialized string and SVG image | | `-ast` | `--dump-ast` | Dump AST as serialized string and SVG image | | `-symtab` | `--dump-symtab` | Dump serialized symbol tables | +| `-types` | `--dump-types` | Dump all used types | | `-ir` | `--dump-ir` | Dump LLVM-IR | | `-s`, `-asm` | `--dump-assembly` | Dump Assembly code | | `-b`, `-obj` | `--dump-object-file` | Dump object files | diff --git a/docs/docs/cli/run.md b/docs/docs/cli/run.md index d9898c29a..2b2939988 100644 --- a/docs/docs/cli/run.md +++ b/docs/docs/cli/run.md @@ -25,6 +25,7 @@ You can apply following options to the `run` subcommand: | `-cst` | `--dump-cst` | Dump CST as serialized string and SVG image | | `-ast` | `--dump-ast` | Dump AST as serialized string and SVG image | | `-symtab` | `--dump-symtab` | Dump serialized symbol tables | +| `-types` | `--dump-types` | Dump all used types | | `-ir` | `--dump-ir` | Dump LLVM-IR | | `-s`, `-asm` | `--dump-assembly` | Dump Assembly code | | `-b`, `-obj` | `--dump-object-file` | Dump object files | diff --git a/docs/docs/cli/test.md b/docs/docs/cli/test.md index eff8ddad9..a12b852cd 100644 --- a/docs/docs/cli/test.md +++ b/docs/docs/cli/test.md @@ -27,6 +27,7 @@ You can apply following options to the `test` subcommand: | `-cst` | `--dump-cst` | Dump CST as serialized string and SVG image | | `-ast` | `--dump-ast` | Dump AST as serialized string and SVG image | | `-symtab` | `--dump-symtab` | Dump serialized symbol tables | +| `-types` | `--dump-types` | Dump all used types | | `-ir` | `--dump-ir` | Dump LLVM-IR | | `-s`, `-asm` | `--dump-assembly` | Dump Assembly code | | `-j ` | `--jobs ` | Set number of jobs to parallelize compilation (default is auto) | diff --git a/media/test-project/test.spice b/media/test-project/test.spice index 76959fdec..754fe5d26 100644 --- a/media/test-project/test.spice +++ b/media/test-project/test.spice @@ -14,20 +14,6 @@ f main() { printf("\nLexed tokens: %d\n", tokenCount); } -/*import "std/iterator/number-iterator"; - -f main() { - NumberIterator itInt = range(1, 10); - dyn idxAndValueInt = itInt.getIdx(); - assert idxAndValueInt.getSecond() == 4; -}*/ - -/*import "std/data/hash-table"; - -f main() { - HashTable map = HashTable(3l); -}*/ - /*import "bootstrap/util/block-allocator"; import "bootstrap/util/memory"; diff --git a/src/SourceFile.cpp b/src/SourceFile.cpp index 7781633f4..66f9c09af 100644 --- a/src/SourceFile.cpp +++ b/src/SourceFile.cpp @@ -483,6 +483,14 @@ void SourceFile::concludeCompilation() { if (!cliOptions.ignoreCache) resourceManager.cacheManager.cacheSourceFile(this); + // Save type registry as string in the compiler output + if (mainFile && (cliOptions.dumpSettings.dumpTypes || cliOptions.testMode)) + compilerOutput.typesString = TypeRegistry::dump(); + + // Dump type registry + if (mainFile && cliOptions.dumpSettings.dumpTypes) + dumpOutput(compilerOutput.typesString, "Type Registry", "type-registry.out"); + // Print warning if verifier is disabled if (parent == nullptr && cliOptions.disableVerifier) { const std::string warningMessage = diff --git a/src/SourceFile.h b/src/SourceFile.h index 5947dad3a..d30eb9575 100644 --- a/src/SourceFile.h +++ b/src/SourceFile.h @@ -92,6 +92,7 @@ struct CompilerOutput { std::string irString; std::string irOptString; std::string asmString; + std::string typesString; std::vector warnings; TimerOutput times; }; diff --git a/src/driver/Driver.cpp b/src/driver/Driver.cpp index 10cb0264b..14ee63de5 100644 --- a/src/driver/Driver.cpp +++ b/src/driver/Driver.cpp @@ -337,6 +337,8 @@ void Driver::addCompileSubcommandOptions(CLI::App *subCmd) { subCmd->add_flag("--dump-ast,-ast", cliOptions.dumpSettings.dumpAST, "Dump AST as serialized string and SVG image"); // --dump-symtab subCmd->add_flag("--dump-symtab,-symtab", cliOptions.dumpSettings.dumpSymbolTable, "Dump serialized symbol tables"); + // --dump-types + subCmd->add_flag("--dump-types,-types", cliOptions.dumpSettings.dumpTypes, "Dump all used types"); // --dump-ir subCmd->add_flag("--dump-ir,-ir", cliOptions.dumpSettings.dumpIR, "Dump LLVM-IR"); // --dump-assembly diff --git a/src/driver/Driver.h b/src/driver/Driver.h index 5ed36ac20..1154d0bcb 100644 --- a/src/driver/Driver.h +++ b/src/driver/Driver.h @@ -55,6 +55,7 @@ struct CliOptions { bool dumpCST = false; bool dumpAST = false; bool dumpSymbolTable = false; + bool dumpTypes = false; bool dumpIR = false; bool dumpAssembly = false; bool dumpObjectFile = false; diff --git a/src/global/TypeRegistry.cpp b/src/global/TypeRegistry.cpp index 323e7170b..e81a9ffc6 100644 --- a/src/global/TypeRegistry.cpp +++ b/src/global/TypeRegistry.cpp @@ -2,6 +2,8 @@ #include "TypeRegistry.h" +#include + #include namespace spice::compiler { @@ -77,6 +79,28 @@ const Type *TypeRegistry::getOrInsert(const TypeChain &typeChain) { return getOr */ size_t TypeRegistry::getTypeCount() { return types.size(); } -void TypeRegistry::clear() { types.clear();} +/** + * Dump all types in the type registry + */ +std::string TypeRegistry::dump() { + // Sort the keys of the unordered map to get a deterministic output + std::vector keys; + keys.reserve(types.size()); + for (const auto &it : types) + keys.push_back(it.first); + std::sort(keys.begin(), keys.end()); + // Serialize type registry + std::stringstream typeRegistryString; + for (const uint64_t &key : keys) { + types.at(key)->getName(typeRegistryString); + typeRegistryString << "\n"; + } + return typeRegistryString.str(); +} + +/** + * Clear the type registry + */ +void TypeRegistry::clear() { types.clear(); } } // namespace spice::compiler diff --git a/src/global/TypeRegistry.h b/src/global/TypeRegistry.h index c1998d7a9..322abfd2c 100644 --- a/src/global/TypeRegistry.h +++ b/src/global/TypeRegistry.h @@ -24,6 +24,7 @@ class TypeRegistry { const TypeChainElementData &data, const QualTypeList &templateTypes); static const Type *getOrInsert(const TypeChain& typeChain); static size_t getTypeCount(); + static std::string dump(); static void clear(); private: diff --git a/src/symboltablebuilder/TypeChain.cpp b/src/symboltablebuilder/TypeChain.cpp index 7a5308626..e75293f1d 100644 --- a/src/symboltablebuilder/TypeChain.cpp +++ b/src/symboltablebuilder/TypeChain.cpp @@ -102,7 +102,9 @@ void TypeChainElement::getName(std::stringstream &name, bool withSize) const { name << "f"; if (data.hasCaptures) name << "[]"; - name << "<" << paramTypes.front().getName(true) << ">("; + if (!paramTypes.empty()) + name << "<" << paramTypes.front().getName(true) << ">"; + name << "("; for (size_t i = 1; i < paramTypes.size(); i++) { if (i > 1) name << ","; diff --git a/test/TestRunner.cpp b/test/TestRunner.cpp index 0ee60f107..8064787bc 100644 --- a/test/TestRunner.cpp +++ b/test/TestRunner.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -55,6 +56,7 @@ void execTestCase(const TestCase &testCase) { /* dumpCST= */ false, /* dumpAST= */ false, /* dumpSymbolTables= */ false, + /* dumpTypes= */ false, /* dumpIR= */ false, /* dumpAssembly= */ false, /* dumpObjectFile= */ false, @@ -71,6 +73,7 @@ void execTestCase(const TestCase &testCase) { /* disableVerifier= */ false, /* testMode= */ true, }; + static_assert(sizeof(CliOptions::DumpSettings) == 9, "CliOptions::DumpSettings struct size changed"); static_assert(sizeof(CliOptions) == 360, "CliOptions struct size changed"); // Instantiate GlobalResourceManager @@ -196,6 +199,9 @@ void execTestCase(const TestCase &testCase) { resourceManager.linker.link(); } + // Check type registry output + TestUtil::checkRefMatch(testCase.testPath / REF_NAME_TYPE_REGISTRY, [&]() { return TypeRegistry::dump(); }); + // Check if the execution output matches the expected output TestUtil::checkRefMatch(testCase.testPath / REF_NAME_EXECUTION_OUTPUT, [&]() { const std::filesystem::path cliFlagsFile = testCase.testPath / INPUT_NAME_CLI_FLAGS; diff --git a/test/test-files/benchmark/success-ackermann/type-registry.out b/test/test-files/benchmark/success-ackermann/type-registry.out new file mode 100644 index 000000000..ee93ce8bc --- /dev/null +++ b/test/test-files/benchmark/success-ackermann/type-registry.out @@ -0,0 +1,7 @@ +f(int,int) +f() +int +invalid +dyn +bool +f() diff --git a/test/test-files/benchmark/success-faculty/type-registry.out b/test/test-files/benchmark/success-faculty/type-registry.out new file mode 100644 index 000000000..4340a3808 --- /dev/null +++ b/test/test-files/benchmark/success-faculty/type-registry.out @@ -0,0 +1,7 @@ +f(int) +f() +int +invalid +dyn +bool +f() diff --git a/test/test-files/benchmark/success-fibonacci-threaded/type-registry.out b/test/test-files/benchmark/success-fibonacci-threaded/type-registry.out new file mode 100644 index 000000000..445a8b353 --- /dev/null +++ b/test/test-files/benchmark/success-fibonacci-threaded/type-registry.out @@ -0,0 +1,37 @@ +Error& +Error* +Pthread_attr_t& +Pthread_attr_t* +Pthread_attr_t +f(int) +f() +* +p() +byte +char +long +int +invalid +dyn +bool +string +Thread +Thread& +Thread* +Thread +import +f() +f() +byte* +char* +long* +dyn +p() +long +f(long*,Pthread_attr_t*,p()) +byte** +Error +p(p()) +p(int,string) +f(long,byte**) +p(string) diff --git a/test/test-files/benchmark/success-fibonacci/type-registry.out b/test/test-files/benchmark/success-fibonacci/type-registry.out new file mode 100644 index 000000000..0e8cd52e9 --- /dev/null +++ b/test/test-files/benchmark/success-fibonacci/type-registry.out @@ -0,0 +1,7 @@ +f() +int +invalid +dyn +bool +f() +f(int) diff --git a/test/test-files/benchmark/success-hello-world/type-registry.out b/test/test-files/benchmark/success-hello-world/type-registry.out new file mode 100644 index 000000000..ecb15d8c3 --- /dev/null +++ b/test/test-files/benchmark/success-hello-world/type-registry.out @@ -0,0 +1,5 @@ +f() +int +invalid +bool +f() diff --git a/test/test-files/benchmark/success-hello-world2/type-registry.out b/test/test-files/benchmark/success-hello-world2/type-registry.out new file mode 100644 index 000000000..b1585b0f6 --- /dev/null +++ b/test/test-files/benchmark/success-hello-world2/type-registry.out @@ -0,0 +1,7 @@ +f() +char +long +int +invalid +bool +f() diff --git a/test/test-files/benchmark/success-pidigits/type-registry.out b/test/test-files/benchmark/success-pidigits/type-registry.out new file mode 100644 index 000000000..d087dce85 --- /dev/null +++ b/test/test-files/benchmark/success-pidigits/type-registry.out @@ -0,0 +1,6 @@ +f() +long +int +invalid +bool +f() diff --git a/test/util/TestUtil.h b/test/util/TestUtil.h index b111223fa..4b2897c29 100644 --- a/test/util/TestUtil.h +++ b/test/util/TestUtil.h @@ -30,6 +30,7 @@ const char *const REF_NAME_SOURCE = "source.spice"; const char *const REF_NAME_PARSE_TREE = "parse-tree.dot"; const char *const REF_NAME_SYNTAX_TREE = "syntax-tree.dot"; const char *const REF_NAME_SYMBOL_TABLE = "symbol-table.json"; +const char *const REF_NAME_TYPE_REGISTRY = "type-registry.out"; const char *const REF_NAME_IR = "ir-code.ll"; const char *const REF_NAME_ASM = "assembly.asm"; const char *const REF_NAME_OPT_IR[5] = {"ir-code-O1.ll", "ir-code-O2.ll", "ir-code-O3.ll", "ir-code-Os.ll", "ir-code-Oz.ll"};