From 5ce6ebcab1add29f5e93f7a348af33b21c751c00 Mon Sep 17 00:00:00 2001 From: Marc Auberer Date: Fri, 2 Feb 2024 01:31:23 +0100 Subject: [PATCH] Finish map std (#442) --- .run/spice.run.xml | 2 +- .run/spicetest.run.xml | 2 +- media/test-project/test.spice | 74 ++-- media/test-project/test2.spice | 11 +- src/SourceFile.cpp | 10 +- src/SourceFile.h | 5 +- src/exception/SemanticError.cpp | 2 - src/exception/SemanticError.h | 1 - src/global/RuntimeModuleManager.h | 18 + src/irgenerator/DebugInfoGenerator.cpp | 2 +- src/irgenerator/GenControlStructures.cpp | 5 + src/irgenerator/GenImplicit.cpp | 2 +- src/irgenerator/IRGenerator.cpp | 3 + src/irgenerator/NameMangling.cpp | 75 ++-- src/irgenerator/NameMangling.h | 8 +- src/irgenerator/OpRuleConversionManager.cpp | 4 +- src/irgenerator/StdFunctionManager.cpp | 38 +- src/irgenerator/StdFunctionManager.h | 5 +- src/model/Function.cpp | 16 +- src/model/StructBase.cpp | 13 +- src/symboltablebuilder/SymbolType.cpp | 12 +- src/symboltablebuilder/SymbolType.h | 5 + src/symboltablebuilder/TypeSpecifiers.cpp | 11 +- src/typechecker/FunctionManager.cpp | 82 ++-- src/typechecker/FunctionManager.h | 18 +- src/typechecker/InterfaceManager.cpp | 28 +- src/typechecker/InterfaceManager.h | 8 +- src/typechecker/OpRuleManager.cpp | 3 + src/typechecker/StructManager.cpp | 39 +- src/typechecker/StructManager.h | 8 +- src/typechecker/TypeChecker.cpp | 40 +- src/typechecker/TypeCheckerImplicit.cpp | 2 +- src/typechecker/TypeCheckerPrepare.cpp | 13 - src/typechecker/TypeMatcher.cpp | 9 +- src/typechecker/TypeMatcher.h | 2 +- src/util/CommonUtil.cpp | 14 + src/util/CommonUtil.h | 1 + src/util/FileUtil.cpp | 31 +- src/util/FileUtil.h | 2 +- std/data/binary-tree.spice | 31 +- std/data/doubly-linked-list.spice | 14 +- std/data/linked-list.spice | 12 +- std/data/map.spice | 84 +++- std/data/optional.spice | 6 +- std/data/red-black-tree.spice | 418 ++++++++++++++++-- std/data/unordered-map.spice | 19 + std/io/file.spice | 8 +- std/iterator/number-iterator.spice | 7 - std/runtime/memory_rt.spice | 69 ++- std/type/result.spice | 13 +- test/TestRunner.cpp | 4 + .../success-dbg-info-complex/debug.out | 4 +- .../success-dbg-info-complex/ir-code.ll | 20 +- .../success-dbg-info-simple/ir-code.ll | 10 +- .../success-foreach-loop-break/ir-code-O2.ll | 8 +- .../success-foreach-loop-break/ir-code.ll | 8 +- .../ir-code-O2.ll | 8 +- .../success-foreach-loop-continue/ir-code.ll | 8 +- .../success-foreach-loop-indexed/ir-code.ll | 4 +- .../success-foreach-loop-normal/ir-code.ll | 4 +- .../success-indirect/ir-code.ll | 8 +- .../success-pass-by-non-value/ir-code.ll | 12 +- .../functions/success-overloading/ir-code.ll | 4 +- .../ir-code.ll | 20 +- .../success-generic-functions/ir-code.ll | 12 +- .../success-generic-functions2/ir-code.ll | 12 +- .../generics/success-type-hints/ir-code.ll | 4 +- .../success-expression-lambda/ir-code.ll | 8 +- .../success-function-lambda/ir-code.ll | 10 +- .../success-procedure-lambda/ir-code.ll | 6 +- .../methods/success-methods/ir-code.ll | 4 +- .../success-nested-pointers/ir-code.ll | 4 +- .../structs/success-constructors/ir-code.ll | 4 +- .../ir-code.ll | 4 +- .../success-default-copy-ctor/ir-code.ll | 2 +- .../success-default-ctor-nested/ir-code.ll | 6 +- .../structs/success-default-ctor/ir-code.ll | 2 +- .../success-default-dtor-nested/ir-code.ll | 4 +- .../structs/success-default-dtor/ir-code.ll | 2 +- .../success-default-field-values1/ir-code.ll | 2 +- .../success-default-field-values3/ir-code.ll | 2 +- .../structs/success-destructors1/ir-code.ll | 4 +- .../structs/success-destructors2/ir-code.ll | 4 +- .../ir-code.ll | 2 +- .../std/data/map-normal-usecase/cout.out | 1 + .../std/data/map-normal-usecase/source.spice | 50 +++ .../success-complex-alias/symbol-table.json | 26 +- .../symbol-table.json | 120 ++--- .../error-unused-template-type/exception.out | 14 - .../error-unused-template-type/source.spice | 9 - 90 files changed, 1175 insertions(+), 570 deletions(-) create mode 100644 std/data/unordered-map.spice create mode 100644 test/test-files/std/data/map-normal-usecase/cout.out create mode 100644 test/test-files/std/data/map-normal-usecase/source.spice delete mode 100644 test/test-files/typechecker/generics/error-unused-template-type/exception.out delete mode 100644 test/test-files/typechecker/generics/error-unused-template-type/source.spice diff --git a/.run/spice.run.xml b/.run/spice.run.xml index c69468147..a906fee14 100644 --- a/.run/spice.run.xml +++ b/.run/spice.run.xml @@ -1,5 +1,5 @@ - + diff --git a/.run/spicetest.run.xml b/.run/spicetest.run.xml index ccacbeee8..2b9329852 100644 --- a/.run/spicetest.run.xml +++ b/.run/spicetest.run.xml @@ -1,5 +1,5 @@ - + diff --git a/media/test-project/test.spice b/media/test-project/test.spice index 937fc514b..a4e167e52 100644 --- a/media/test-project/test.spice +++ b/media/test-project/test.spice @@ -1,31 +1,51 @@ -import "std/io/cli-parser"; +import "std/data/map"; -type CliOptions struct { - bool sayHi = false -} - -p callback(bool& value) { - printf("Callback called with value %d\n", value); -} - -f main(int argc, string[] argv) { - CliParser parser = CliParser("Test Program", "This is a simple test program"); - parser.setVersion("v0.1.0"); - parser.setFooter("Copyright (c) Marc Auberer 2021-2024"); - - CliOptions options; - parser.addFlag("--hi", options.sayHi, "Say hi to the user"); - parser.addFlag("--callback", callback, "Call a callback function"); - parser.addFlag("-cb", p(bool& value) { - printf("CB called with value %d\n", value); - }, "Call a callback function"); - - parser.parse(argc, argv); - - // Print hi if requested - if options.sayHi { - printf("Hi!\n"); - } +f main() { + Map map; + assert map.getSize() == 0l; + assert map.isEmpty(); + map.insert(1, "Hello"); + assert map.getSize() == 1l; + assert !map.isEmpty(); + map.insert(2, "World"); + assert map.getSize() == 2l; + map.insert(3, "Foo"); + assert map.getSize() == 3l; + map.insert(4, "Bar"); + assert map.getSize() == 4l; + assert map.contains(1); + assert map.contains(2); + assert map.contains(3); + assert map.contains(4); + assert map.get(1) == "Hello"; + assert map.get(2) == "World"; + assert map.get(3) == "Foo"; + assert map.get(4) == "Bar"; + map.remove(2); + assert map.getSize() == 3l; + assert !map.contains(2); + assert !map.isEmpty(); + map.remove(1); + assert map.getSize() == 2l; + assert !map.contains(1); + assert !map.isEmpty(); + string& foo = map.get(3); + assert foo == "Foo"; + foo = "Baz"; + assert map.get(3) == "Baz"; + Result bar = map.getSafe(4); + assert bar.isOk(); + assert bar.unwrap() == "Bar"; + Result baz = map.getSafe(5); + assert baz.isErr(); + map.remove(3); + assert map.getSize() == 1l; + assert !map.contains(3); + assert !map.isEmpty(); + map.remove(4); + assert map.getSize() == 0l; + assert !map.contains(4); + assert map.isEmpty(); } /*import "../../src-bootstrap/lexer/lexer"; diff --git a/media/test-project/test2.spice b/media/test-project/test2.spice index cdbd2f0b7..d94ede4e9 100644 --- a/media/test-project/test2.spice +++ b/media/test-project/test2.spice @@ -1,5 +1,10 @@ -import "test3" as s2; +type A dyn; -p test() { - printf("p: %f", s2.getDouble()); +public p printFormat(A element) { + printf("Sizeof output: %d\n", sizeof(element)); +} + +public f getAInc(A* number) { + (*number)++; + return number; } \ No newline at end of file diff --git a/src/SourceFile.cpp b/src/SourceFile.cpp index 1335970de..5ed4c2170 100644 --- a/src/SourceFile.cpp +++ b/src/SourceFile.cpp @@ -614,9 +614,13 @@ void SourceFile::collectAndPrintWarnings() { // NOLINT(misc-no-recursion) warning.print(); } -bool SourceFile::isStringRT() const { return globalScope->lookupStrict(STROBJ_NAME) != nullptr; } - -bool SourceFile::isRttiRT() const { return globalScope->lookupStrict(TIOBJ_NAME) != nullptr; } +bool SourceFile::isRT(RuntimeModule runtimeModule) const { + assert(IDENTIFYING_TOP_LEVEL_NAMES.contains(runtimeModule)); + const char *topLevelName = IDENTIFYING_TOP_LEVEL_NAMES.at(runtimeModule); + if (!exportedNameRegistry.contains(topLevelName)) + return false; + return exportedNameRegistry.at(topLevelName).targetEntry->scope == globalScope.get(); +} bool SourceFile::haveAllDependantsBeenTypeChecked() const { return std::ranges::all_of(dependants, [](const SourceFile *dependant) { return dependant->totalTypeCheckerRuns >= 1; }); diff --git a/src/SourceFile.h b/src/SourceFile.h index 35c388502..81c9114c1 100644 --- a/src/SourceFile.h +++ b/src/SourceFile.h @@ -148,8 +148,9 @@ class SourceFile { [[nodiscard]] const NameRegistryEntry *getNameRegistryEntry(const std::string &symbolName) const; void checkForSoftErrors(); void collectAndPrintWarnings(); - bool isStringRT() const; - bool isRttiRT() const; + bool isRT(RuntimeModule runtimeModule) const; + ALWAYS_INLINE bool isStringRT() const { return isRT(STRING_RT); } + ALWAYS_INLINE bool isRttiRT() const { return isRT(RTTI_RT); } // Public fields std::string name; diff --git a/src/exception/SemanticError.cpp b/src/exception/SemanticError.cpp index 4b55cd698..7de7f7072 100644 --- a/src/exception/SemanticError.cpp +++ b/src/exception/SemanticError.cpp @@ -180,8 +180,6 @@ std::string SemanticError::getMessagePrefix(SemanticErrorType type) { return "Temporary bound to non-const reference"; case GENERIC_TYPE_NOT_IN_TEMPLATE: return "Generic type not contained in template"; - case GENERIC_TYPE_NOT_USED: - return "Template types not used"; case SPECIFIER_AT_ILLEGAL_CONTEXT: return "Specifier at illegal context"; case INSUFFICIENT_VISIBILITY: diff --git a/src/exception/SemanticError.h b/src/exception/SemanticError.h index 34a6ddf85..d7ead15cc 100644 --- a/src/exception/SemanticError.h +++ b/src/exception/SemanticError.h @@ -89,7 +89,6 @@ enum SemanticErrorType : uint8_t { REFERENCE_WITHOUT_INITIALIZER, TEMP_TO_NON_CONST_REF, GENERIC_TYPE_NOT_IN_TEMPLATE, - GENERIC_TYPE_NOT_USED, SPECIFIER_AT_ILLEGAL_CONTEXT, INSUFFICIENT_VISIBILITY, JOIN_ARG_MUST_BE_TID, diff --git a/src/global/RuntimeModuleManager.h b/src/global/RuntimeModuleManager.h index db158f07a..17e347aad 100644 --- a/src/global/RuntimeModuleManager.h +++ b/src/global/RuntimeModuleManager.h @@ -5,6 +5,8 @@ #include #include +#include + namespace spice::compiler { // Forward declaration @@ -22,6 +24,22 @@ enum RuntimeModule : uint8_t { RTTI_RT = 1 << 2, }; +const std::unordered_map TYPE_NAME_TO_RT_MODULE_MAPPING = { + {STROBJ_NAME, STRING_RT}, +}; + +const std::unordered_map FCT_NAME_TO_RT_MODULE_MAPPING = { + {"sAlloc", MEMORY_RT}, {"sRealloc", MEMORY_RT}, {"sCopy", MEMORY_RT}, {"sDealloc", MEMORY_RT}, + {"sNew", MEMORY_RT}, {"sPlacementNew", MEMORY_RT}, {"sDelete", MEMORY_RT}, +}; + +// This serves for the compiler to detect if a source file is a specific runtime module +const std::unordered_map IDENTIFYING_TOP_LEVEL_NAMES = { + {STRING_RT, STROBJ_NAME}, // String struct + {MEMORY_RT, "sAlloc"}, // sAlloc function + {RTTI_RT, TIOBJ_NAME}, // TypeInfo struct +}; + struct ModuleNamePair { const char *const importName; const char *const fileName; diff --git a/src/irgenerator/DebugInfoGenerator.cpp b/src/irgenerator/DebugInfoGenerator.cpp index e33000c23..f2d3e7e61 100644 --- a/src/irgenerator/DebugInfoGenerator.cpp +++ b/src/irgenerator/DebugInfoGenerator.cpp @@ -27,7 +27,7 @@ void DebugInfoGenerator::initialize(const std::string &sourceFileName, std::file sourceFileDir.make_preferred(); llvm::DIFile *cuDiFile = diBuilder->createFile(absolutePath.string(), sourceFileDir.string()); compileUnit = diBuilder->createCompileUnit( - llvm::dwarf::DW_LANG_C_plus_plus_20, cuDiFile, producerString, irGenerator->cliOptions.optLevel > OptLevel::O0, "", 0, "", + llvm::dwarf::DW_LANG_C_plus_plus_14, cuDiFile, producerString, irGenerator->cliOptions.optLevel > OptLevel::O0, "", 0, "", llvm::DICompileUnit::FullDebug, 0, false, false, llvm::DICompileUnit::DebugNameTableKind::None); module->addModuleFlag(llvm::Module::Max, "Dwarf Version", llvm::dwarf::DWARF_VERSION); diff --git a/src/irgenerator/GenControlStructures.cpp b/src/irgenerator/GenControlStructures.cpp index ac5c55a7f..da7515edc 100644 --- a/src/irgenerator/GenControlStructures.cpp +++ b/src/irgenerator/GenControlStructures.cpp @@ -109,6 +109,11 @@ std::any IRGenerator::visitForeachLoop(const ForeachLoopNode *node) { // Resolve address of iterator LLVMExprResult callResult = {.value = iterator, .node = iteratorAssignNode}; iteratorPtr = resolveAddress(callResult); + + // Attach address to anonymous symbol to keep track of deallocation + SymbolTableEntry *returnSymbol = currentScope->symbolTable.lookupAnonymous(iteratorAssignNode->codeLoc); + assert(returnSymbol != nullptr); + returnSymbol->updateAddress(iteratorPtr); } else { // The iteratorAssignExpr is of type Iterator iteratorPtr = resolveAddress(iteratorAssignNode); } diff --git a/src/irgenerator/GenImplicit.cpp b/src/irgenerator/GenImplicit.cpp index 5eb7799e2..37593371f 100644 --- a/src/irgenerator/GenImplicit.cpp +++ b/src/irgenerator/GenImplicit.cpp @@ -106,7 +106,7 @@ void IRGenerator::generateCtorOrDtorCall(SymbolTableEntry *entry, const Function void IRGenerator::generateDeallocCall(llvm::Value *variableAddress) const { // In case of string runtime, call free manually. Otherwise, use the memory_rt implementation of sDealloc() if (sourceFile->isStringRT()) { - llvm::Function *freeFct = stdFunctionManager.getFreeFctPtr(); + llvm::Function *freeFct = stdFunctionManager.getFreeFct(); builder.CreateCall(freeFct, variableAddress); } else { llvm::Function *deallocFct = stdFunctionManager.getDeallocBytePtrRefFct(); diff --git a/src/irgenerator/IRGenerator.cpp b/src/irgenerator/IRGenerator.cpp index 176ee6924..d5642d30f 100644 --- a/src/irgenerator/IRGenerator.cpp +++ b/src/irgenerator/IRGenerator.cpp @@ -301,6 +301,9 @@ llvm::Constant *IRGenerator::getConst(const CompileTimeValue &compileTimeValue, if (type.is(TY_BOOL)) return builder.getInt1(compileTimeValue.boolValue); + if (type.is(TY_PTR)) + return llvm::Constant::getNullValue(builder.getPtrTy()); + throw CompilerError(UNHANDLED_BRANCH, "Constant fall-through"); // GCOV_EXCL_LINE } diff --git a/src/irgenerator/NameMangling.cpp b/src/irgenerator/NameMangling.cpp index f15031c27..468d6f55b 100644 --- a/src/irgenerator/NameMangling.cpp +++ b/src/irgenerator/NameMangling.cpp @@ -1,12 +1,14 @@ // Copyright (c) 2021-2024 ChilliBits. All rights reserved. #include "NameMangling.h" +#include "typechecker/TypeMatcher.h" #include #include #include #include #include +#include namespace spice::compiler { @@ -26,15 +28,13 @@ std::string NameMangling::mangleFunction(const Function &spiceFunc) { if (!spiceFunc.mangleFunctionName) return spiceFunc.name; - bool needsEndMarker = false; std::stringstream mangledName; mangledName << "_Z"; // This type if (spiceFunc.isMethod()) { mangledName << "N"; - mangleType(mangledName, spiceFunc.thisType); - needsEndMarker = true; + mangleType(mangledName, spiceFunc.thisType, spiceFunc.typeMapping); } // Function name @@ -42,33 +42,54 @@ std::string NameMangling::mangleFunction(const Function &spiceFunc) { mangledName << name.length() << name; // Template types - if (!spiceFunc.templateTypes.empty()) { + bool isSelfGeneric = !spiceFunc.templateTypes.empty(); + if (spiceFunc.isMethod()) + isSelfGeneric = spiceFunc.templateTypes.size() > spiceFunc.thisType.getTemplateTypes().size(); + if (isSelfGeneric) { mangledName << "I"; // Template types themselves for (const GenericType &genericTemplateType : spiceFunc.templateTypes) { assert(spiceFunc.typeMapping.contains(genericTemplateType.getSubType())); const SymbolType &actualType = spiceFunc.typeMapping.at(genericTemplateType.getSubType()); - mangleType(mangledName, actualType); + mangleType(mangledName, actualType, spiceFunc.typeMapping); } mangledName << "E"; + // Insert second end marker to end the nested type + if (spiceFunc.isMethod()) + mangledName << "E"; + // Return type if (spiceFunc.isFunction()) - mangleType(mangledName, spiceFunc.returnType); + mangleType(mangledName, spiceFunc.returnType, spiceFunc.typeMapping); else mangledName << "v"; - } else if (needsEndMarker) { + + } else if (spiceFunc.isMethod()) { mangledName << "E"; } // Parameter types for (const Param ¶m : spiceFunc.paramList) { assert(!param.isOptional); - mangleType(mangledName, param.type); + mangleType(mangledName, param.type, spiceFunc.typeMapping); } if (spiceFunc.paramList.empty()) mangledName << "v"; +#ifndef NDEBUG + const std::unordered_map &typeMapping = spiceFunc.typeMapping; + const bool returnTypeIsFctOrProc = spiceFunc.returnType.getBaseType().isOneOf({TY_FUNCTION, TY_PROCEDURE}); + const auto paramPredicate = [](const Param &p) { return p.type.getBaseType().isOneOf({TY_FUNCTION, TY_PROCEDURE}); }; + const bool paramTypeIsFctOrProc = std::ranges::any_of(spiceFunc.paramList, paramPredicate); + const auto templateTypePredicate = [&](const GenericType &t) { + return typeMapping.at(t.getSubType()).getBaseType().isOneOf({TY_FUNCTION, TY_PROCEDURE}); + }; + const bool templateTypeIsFctOrProc = std::ranges::any_of(spiceFunc.templateTypes, templateTypePredicate); + if (!returnTypeIsFctOrProc && !paramTypeIsFctOrProc && !templateTypeIsFctOrProc) + assert(CommonUtil::isValidMangledName(mangledName.str())); +#endif + return mangledName.str(); } @@ -132,11 +153,15 @@ void NameMangling::mangleName(std::stringstream &out, const std::string &name, b * @param type Input symbol type * @return Mangled name */ -void NameMangling::mangleType(std::stringstream &out, const SymbolType &type) { // NOLINT(*-no-recursion) +void NameMangling::mangleType(std::stringstream &out, SymbolType type, const TypeMapping &typeMapping) { // NOLINT(*-no-recursion) + // Replace generic type with concrete type + if (type.hasAnyGenericParts() && !typeMapping.empty()) + TypeMatcher::substantiateTypeWithTypeMapping(type, typeMapping); + // Unwrap type chain assert(!type.typeChain.empty()); for (size_t i = type.typeChain.size() - 1; i >= 1; i--) - mangleTypeChainElement(out, type.typeChain.at(i), false); + mangleTypeChainElement(out, type.typeChain.at(i), typeMapping, false); // Specifiers assert(type.specifiers.isSigned == !type.specifiers.isUnsigned); @@ -145,7 +170,7 @@ void NameMangling::mangleType(std::stringstream &out, const SymbolType &type) { out << "K"; // Base chain element - mangleTypeChainElement(out, type.typeChain.front(), signedness); + mangleTypeChainElement(out, type.typeChain.front(), typeMapping, signedness); } /** @@ -156,16 +181,12 @@ void NameMangling::mangleType(std::stringstream &out, const SymbolType &type) { * @param signedness Signedness of the type * @return Mangled name */ -void NameMangling::mangleTypeChainElement(std::stringstream &out, const TypeChainElement &chainElement, bool signedness) { +void NameMangling::mangleTypeChainElement(std::stringstream &out, const TypeChainElement &chainElement, + const TypeMapping &typeMapping, bool signedness) { switch (chainElement.superType) { - case TY_PTR: - out << "P"; - break; + case TY_PTR: // fall-through case TY_ARRAY: - if (chainElement.data.arraySize == 0) - out << "P"; - else - out << "A" << chainElement.data.arraySize; + out << "P"; break; case TY_REF: out << "R"; @@ -190,7 +211,7 @@ void NameMangling::mangleTypeChainElement(std::stringstream &out, const TypeChai out << (signedness ? "c" : "h"); break; case TY_STRING: - out << "Pc"; + out << "PKc"; break; case TY_BOOL: assert(!signedness && "Signed bool types are forbidden"); @@ -203,7 +224,7 @@ void NameMangling::mangleTypeChainElement(std::stringstream &out, const TypeChai if (!chainElement.templateTypes.empty()) { out << "I"; for (const SymbolType &templateType : chainElement.templateTypes) - mangleType(out, templateType); + mangleType(out, templateType, typeMapping); out << "E"; } if (nestedType) @@ -213,19 +234,21 @@ void NameMangling::mangleTypeChainElement(std::stringstream &out, const TypeChai case TY_ENUM: { bool nestedType = false; mangleName(out, chainElement.subType, nestedType); + if (nestedType) + out << "E"; break; } case TY_FUNCTION: { out << (chainElement.data.hasCaptures ? "PFC" : "PF"); for (const SymbolType ¶mType : chainElement.paramTypes) - mangleType(out, paramType); + mangleType(out, paramType, typeMapping); out << "E"; break; } case TY_PROCEDURE: { out << (chainElement.data.hasCaptures ? "PFCv" : "PFv"); for (size_t i = 1; i < chainElement.paramTypes.size(); i++) - mangleType(out, chainElement.paramTypes.at(i)); + mangleType(out, chainElement.paramTypes.at(i), typeMapping); out << "E"; break; } @@ -240,7 +263,7 @@ void NameMangling::mangleTypeChainElement(std::stringstream &out, const TypeChai std::string NameMangling::mangleTypeInfoName(const StructBase *structBase) { std::stringstream out; out << "_ZTS"; - mangleType(out, structBase->entry->getType()); + mangleType(out, structBase->entry->getType(), {}); return out.str(); } @@ -249,14 +272,14 @@ std::string NameMangling::mangleTypeInfoValue(const std::string &value) { return std::string NameMangling::mangleTypeInfo(const StructBase *structBase) { std::stringstream out; out << "_ZTI"; - mangleType(out, structBase->entry->getType()); + mangleType(out, structBase->entry->getType(), {}); return out.str(); } std::string NameMangling::mangleVTable(const StructBase *structBase) { std::stringstream out; out << "_ZTV"; - mangleType(out, structBase->entry->getType()); + mangleType(out, structBase->entry->getType(), {}); return out.str(); } diff --git a/src/irgenerator/NameMangling.h b/src/irgenerator/NameMangling.h index 6e3a46a01..6b4779bc6 100644 --- a/src/irgenerator/NameMangling.h +++ b/src/irgenerator/NameMangling.h @@ -4,6 +4,7 @@ #include +#include #include namespace spice::compiler { @@ -32,7 +33,7 @@ class Interface; * - a: byte * - h: unsigned byte / unsigned char * - c: char - * - Pc: string (char*) + * - PKc: string (const char*) * - b: bool * - v: void * - K: const @@ -60,8 +61,9 @@ class NameMangling { // Private methods static void mangleName(std::stringstream &out, const std::string &name, bool &nestedType); - static void mangleType(std::stringstream &out, const SymbolType &type); - static void mangleTypeChainElement(std::stringstream &out, const TypeChainElement &chainElement, bool signedness); + static void mangleType(std::stringstream &out, SymbolType type, const TypeMapping &typeMapping); + static void mangleTypeChainElement(std::stringstream &out, const TypeChainElement &chainElement, const TypeMapping &typeMapping, + bool signedness); }; } // namespace spice::compiler \ No newline at end of file diff --git a/src/irgenerator/OpRuleConversionManager.cpp b/src/irgenerator/OpRuleConversionManager.cpp index d63c4569b..076ea437e 100644 --- a/src/irgenerator/OpRuleConversionManager.cpp +++ b/src/irgenerator/OpRuleConversionManager.cpp @@ -611,7 +611,7 @@ LLVMExprResult OpRuleConversionManager::getEqualInst(const ASTNode *node, LLVMEx case COMB(TY_FUNCTION, TY_FUNCTION): // fallthrough case COMB(TY_PROCEDURE, TY_PROCEDURE): { const uint64_t typeSize = irGenerator->module->getDataLayout().getTypeSizeInBits(lhsT) / 8; - llvm::Function *memcmpFct = stdFunctionManager.getMemcmpIntrinsic(); + llvm::Function *memcmpFct = stdFunctionManager.getMemcmpFct(); llvm::Value *memcmpResult = builder.CreateCall(memcmpFct, {lhsP(), rhsP(), builder.getInt64(typeSize)}); return {.value = builder.CreateICmpEQ(memcmpResult, llvm::ConstantInt::get(context, llvm::APInt(32, 0)))}; } @@ -747,7 +747,7 @@ LLVMExprResult OpRuleConversionManager::getNotEqualInst(const ASTNode *node, LLV case COMB(TY_FUNCTION, TY_FUNCTION): // fallthrough case COMB(TY_PROCEDURE, TY_PROCEDURE): { const uint64_t typeSize = irGenerator->module->getDataLayout().getTypeSizeInBits(lhsT) / 8; - llvm::Function *memcmpFct = stdFunctionManager.getMemcmpIntrinsic(); + llvm::Function *memcmpFct = stdFunctionManager.getMemcmpFct(); llvm::Value *memcmpResult = builder.CreateCall(memcmpFct, {lhsP(), rhsP(), builder.getInt64(typeSize)}); return {.value = builder.CreateICmpNE(memcmpResult, llvm::ConstantInt::get(context, llvm::APInt(32, 0)))}; } diff --git a/src/irgenerator/StdFunctionManager.cpp b/src/irgenerator/StdFunctionManager.cpp index 2557ead31..85ffff61b 100644 --- a/src/irgenerator/StdFunctionManager.cpp +++ b/src/irgenerator/StdFunctionManager.cpp @@ -19,7 +19,16 @@ llvm::Function *StdFunctionManager::getPrintfFct() const { return printfFct; } -llvm::Function *StdFunctionManager::getFreeFctPtr() const { +llvm::Function *StdFunctionManager::getExitFct() const { + llvm::Function *exitFct = getProcedure("exit", builder.getInt32Ty()); + // Set attributes + exitFct->addFnAttr(llvm::Attribute::Cold); + exitFct->addFnAttr(llvm::Attribute::NoReturn); + exitFct->addFnAttr(llvm::Attribute::NoUnwind); + return exitFct; +} + +llvm::Function *StdFunctionManager::getFreeFct() const { llvm::Function *freeFct = getProcedure("free", builder.getPtrTy()); // Set attributes freeFct->addFnAttr(llvm::Attribute::NoUnwind); @@ -29,13 +38,12 @@ llvm::Function *StdFunctionManager::getFreeFctPtr() const { return freeFct; } -llvm::Function *StdFunctionManager::getExitFct() const { - llvm::Function *exitFct = getProcedure("exit", builder.getInt32Ty()); +llvm::Function *StdFunctionManager::getMemcmpFct() const { + llvm::Type *ptrTy = builder.getPtrTy(); + llvm::Function *memcmpFct = getFunction("memcmp", builder.getInt32Ty(), {ptrTy, ptrTy, builder.getInt64Ty()}); // Set attributes - exitFct->addFnAttr(llvm::Attribute::Cold); - exitFct->addFnAttr(llvm::Attribute::NoReturn); - exitFct->addFnAttr(llvm::Attribute::NoUnwind); - return exitFct; + memcmpFct->addFnAttr(llvm::Attribute::NoUnwind); + return memcmpFct; } llvm::Function *StdFunctionManager::getMemcpyIntrinsic() const { @@ -49,14 +57,6 @@ llvm::Function *StdFunctionManager::getMemcpyIntrinsic() const { return memcpyFct; } -llvm::Function *StdFunctionManager::getMemcmpIntrinsic() const { - llvm::Type *ptrTy = builder.getPtrTy(); - llvm::Function *memcmpFct = getFunction("memcmp", builder.getInt32Ty(), {ptrTy, ptrTy, builder.getInt64Ty()}); - // Set attributes - memcmpFct->addFnAttr(llvm::Attribute::NoUnwind); - return memcmpFct; -} - llvm::Function *StdFunctionManager::getStringGetRawLengthStringFct() const { const ParamList paramLst = {{SymbolType(TY_STRING), false}}; const Function function("getRawLength", nullptr, SymbolType(TY_DYN), SymbolType(TY_LONG), paramLst, {}, nullptr); @@ -71,14 +71,6 @@ llvm::Function *StdFunctionManager::getStringIsRawEqualStringStringFct() const { return getFunction(mangledName.c_str(), builder.getInt1Ty(), {builder.getPtrTy(), builder.getPtrTy()}); } -llvm::Function *StdFunctionManager::getAllocLongFct() const { - const ParamList paramLst = {{SymbolType(TY_LONG), false}}; - const SymbolType bytePtrSTy = SymbolType(TY_BYTE).toPointer(nullptr); - const Function function("sAlloc", nullptr, SymbolType(TY_DYN), bytePtrSTy, paramLst, {}, nullptr); - const std::string mangledName = NameMangling::mangleFunction(function); - return getFunction(mangledName.c_str(), builder.getPtrTy(), {builder.getInt64Ty()}); -} - llvm::Function *StdFunctionManager::getDeallocBytePtrRefFct() const { const ParamList paramLst = {{SymbolType(TY_BYTE).toPointer(nullptr).toReference(nullptr), false}}; const Function function("sDealloc", nullptr, SymbolType(TY_DYN), SymbolType(TY_DYN), paramLst, {}, nullptr); diff --git a/src/irgenerator/StdFunctionManager.h b/src/irgenerator/StdFunctionManager.h index 561e8634b..1cb5156b2 100644 --- a/src/irgenerator/StdFunctionManager.h +++ b/src/irgenerator/StdFunctionManager.h @@ -21,13 +21,12 @@ class StdFunctionManager { // Public methods for function retrieval [[nodiscard]] llvm::Function *getPrintfFct() const; - [[nodiscard]] llvm::Function *getFreeFctPtr() const; [[nodiscard]] llvm::Function *getExitFct() const; + [[nodiscard]] llvm::Function *getFreeFct() const; + [[nodiscard]] llvm::Function *getMemcmpFct() const; [[nodiscard]] llvm::Function *getMemcpyIntrinsic() const; - [[nodiscard]] llvm::Function *getMemcmpIntrinsic() const; [[nodiscard]] llvm::Function *getStringGetRawLengthStringFct() const; [[nodiscard]] llvm::Function *getStringIsRawEqualStringStringFct() const; - [[nodiscard]] llvm::Function *getAllocLongFct() const; [[nodiscard]] llvm::Function *getDeallocBytePtrRefFct() const; [[nodiscard]] llvm::Function *getIteratorFct(const Function *spiceFunc) const; [[nodiscard]] llvm::Function *getIteratorGetFct(const Function *spiceFunc) const; diff --git a/src/model/Function.cpp b/src/model/Function.cpp index fdb06a236..1883a7c1d 100644 --- a/src/model/Function.cpp +++ b/src/model/Function.cpp @@ -33,8 +33,14 @@ std::vector Function::getParamTypes() const { std::string Function::getSignature(bool withThisType /*=true*/, bool ignorePublic /*=false*/) const { std::vector templateSymbolTypes; templateSymbolTypes.reserve(templateTypes.size()); - for (const GenericType &genericType : templateTypes) - templateSymbolTypes.push_back(genericType); + for (const GenericType &genericType : templateTypes) { + if (genericType.is(TY_GENERIC) && !typeMapping.empty()) { + assert(typeMapping.contains(genericType.getSubType())); + templateSymbolTypes.push_back(typeMapping.at(genericType.getSubType())); + } else { + templateSymbolTypes.push_back(genericType); + } + } return Function::getSignature(name, thisType, returnType, paramList, templateSymbolTypes, withThisType, ignorePublic); } @@ -134,10 +140,8 @@ bool Function::hasSubstantiatedParams() const { * @return Substantiated generics or not */ bool Function::hasSubstantiatedGenerics() const { - for (const SymbolType &templateType : thisType.getTemplateTypes()) - if (templateType.hasAnyGenericParts()) - return false; - return templateTypes.empty() && !thisType.hasAnyGenericParts() && !returnType.hasAnyGenericParts(); + const auto predicate = [this](const GenericType &genericType) { return typeMapping.contains(genericType.getSubType()); }; + return std::ranges::all_of(templateTypes, predicate); } /** diff --git a/src/model/StructBase.cpp b/src/model/StructBase.cpp index 11e420b77..b55853542 100644 --- a/src/model/StructBase.cpp +++ b/src/model/StructBase.cpp @@ -4,6 +4,7 @@ #include #include +#include #include namespace spice::compiler { @@ -15,8 +16,16 @@ namespace spice::compiler { */ std::string StructBase::getSignature() const { std::vector templateSymbolTypes; - for (const auto &templateType : templateTypes) - templateSymbolTypes.push_back(templateType); + templateSymbolTypes.reserve(templateTypes.size()); + for (const GenericType &genericType : templateTypes) { + if (genericType.is(TY_GENERIC) && !typeMapping.empty()) { + assert(typeMapping.contains(genericType.getSubType())); + templateSymbolTypes.push_back(typeMapping.at(genericType.getSubType())); + } else { + templateSymbolTypes.push_back(genericType); + } + } + return getSignature(name, templateSymbolTypes); } diff --git a/src/symboltablebuilder/SymbolType.cpp b/src/symboltablebuilder/SymbolType.cpp index c62ee8158..28b82e8c8 100644 --- a/src/symboltablebuilder/SymbolType.cpp +++ b/src/symboltablebuilder/SymbolType.cpp @@ -621,12 +621,6 @@ bool SymbolType::canBind(const SymbolType &inputType, bool isTemporary) const { * @param typeB Requested type */ void SymbolType::unwrapBoth(SymbolType &typeA, SymbolType &typeB) { - // Unwrap both types as far as possible - while (typeA.isSameContainerTypeAs(typeB)) { - typeB = typeB.getContainedTy(); - typeA = typeA.getContainedTy(); - } - // Remove reference wrapper of front type if required if (typeA.isRef() && !typeB.isRef()) typeA = typeA.removeReferenceWrapper(); @@ -634,6 +628,12 @@ void SymbolType::unwrapBoth(SymbolType &typeA, SymbolType &typeB) { // Remove reference wrapper of requested type if required if (!typeA.isRef() && typeB.isRef() && !typeA.getBaseType().is(TY_GENERIC)) typeB = typeB.removeReferenceWrapper(); + + // Unwrap both types as far as possible + while (typeA.isSameContainerTypeAs(typeB)) { + typeB = typeB.getContainedTy(); + typeA = typeA.getContainedTy(); + } } } // namespace spice::compiler \ No newline at end of file diff --git a/src/symboltablebuilder/SymbolType.h b/src/symboltablebuilder/SymbolType.h index 47b3de446..5f5e271ba 100644 --- a/src/symboltablebuilder/SymbolType.h +++ b/src/symboltablebuilder/SymbolType.h @@ -159,6 +159,11 @@ class SymbolType { return typeChain.back().subType; } [[nodiscard]] ALWAYS_INLINE SymbolType removeReferenceWrapper() const { return isRef() ? getContainedTy() : *this; } + [[nodiscard]] ALWAYS_INLINE SymbolType getNonConst() const { + SymbolType type = *this; + type.specifiers.isConst = false; + return type; + } [[nodiscard]] SymbolType getBaseType() const { assert(!typeChain.empty()); return SymbolType({typeChain.front()}, specifiers); diff --git a/src/symboltablebuilder/TypeSpecifiers.cpp b/src/symboltablebuilder/TypeSpecifiers.cpp index f4d8319ba..fb0c3fff6 100644 --- a/src/symboltablebuilder/TypeSpecifiers.cpp +++ b/src/symboltablebuilder/TypeSpecifiers.cpp @@ -94,8 +94,17 @@ bool TypeSpecifiers::match(TypeSpecifiers otherSpecifiers, bool allowConstify) c void TypeSpecifiers::eraseWithMask(const TypeSpecifiers &mask) { // Zero out all bits that are set in the mask for (uint8_t i = 0; i <= BIT_INDEX_MAX; i++) { - if (mask.getBit(i)) + if (mask.getBit(i)) { + // Zero out the bit setBit(i, false); + + // If we set the signed/unsigned bit to zero, we need to set the other to one + if (i == BIT_INDEX_SIGNED) { + setBit(BIT_INDEX_UNSIGNED, true); + } else if (i == BIT_INDEX_UNSIGNED) { + setBit(BIT_INDEX_SIGNED, true); + } + } } } diff --git a/src/typechecker/FunctionManager.cpp b/src/typechecker/FunctionManager.cpp index 23d9724c8..1e6a19287 100644 --- a/src/typechecker/FunctionManager.cpp +++ b/src/typechecker/FunctionManager.cpp @@ -122,16 +122,15 @@ Function *FunctionManager::insertSubstantiation(Scope *insertScope, const Functi * Checks if a function exists by matching it, but not setting it to used * * @param matchScope Scope to match against - * @param requestedName Function name requirement - * @param requestedThisType This type requirement - * @param requestedArgs Argument requirement + * @param reqName Function name requirement + * @param reqThisType This type requirement + * @param reqArgs Argument requirement * @param strictSpecifierMatching Match argument and this type specifiers strictly * @return Found function or nullptr */ -const Function *FunctionManager::lookupFunction(Scope *matchScope, const std::string &requestedName, - const SymbolType &requestedThisType, const ArgList &requestedArgs, - bool strictSpecifierMatching) { - assert(requestedThisType.isOneOf({TY_DYN, TY_STRUCT})); +const Function *FunctionManager::lookupFunction(Scope *matchScope, const std::string &reqName, const SymbolType &reqThisType, + const ArgList &reqArgs, bool strictSpecifierMatching) { + assert(reqThisType.isOneOf({TY_DYN, TY_STRUCT})); // Copy the registry to prevent iterating over items, that are created within the loop FunctionRegistry functionRegistry = matchScope->functions; @@ -151,11 +150,11 @@ const Function *FunctionManager::lookupFunction(Scope *matchScope, const std::st Function candidate = presetFunction; // Create empty type mapping - TypeMapping typeMapping; + TypeMapping &typeMapping = candidate.typeMapping; bool forceSubstantiation = false; - MatchResult matchResult = matchManifestation(candidate, matchScope, requestedName, requestedThisType, requestedArgs, - typeMapping, strictSpecifierMatching, forceSubstantiation, nullptr); + MatchResult matchResult = matchManifestation(candidate, matchScope, reqName, reqThisType, reqArgs, typeMapping, + strictSpecifierMatching, forceSubstantiation, nullptr); if (matchResult == MatchResult::SKIP_FUNCTION) break; // Leave the whole function if (matchResult == MatchResult::SKIP_MANIFESTATION) @@ -177,18 +176,18 @@ const Function *FunctionManager::lookupFunction(Scope *matchScope, const std::st * If more than one function matches the requirement, an error gets thrown. * * @param matchScope Scope to match against - * @param requestedName Function name requirement - * @param requestedThisType This type requirement - * @param requestedArgs Argument requirement - * @param requestedTemplateTypes Template type requirement + * @param reqName Function name requirement + * @param reqThisType This type requirement + * @param reqArgs Argument requirement + * @param templateTypeHints Template type requirement * @param strictSpecifierMatching Match argument and this type specifiers strictly * @param callNode Call AST node for printing error messages * @return Matched function or nullptr */ -Function *FunctionManager::matchFunction(Scope *matchScope, const std::string &requestedName, const SymbolType &requestedThisType, - const ArgList &requestedArgs, const std::vector &requestedTemplateTypes, +Function *FunctionManager::matchFunction(Scope *matchScope, const std::string &reqName, const SymbolType &reqThisType, + const ArgList &reqArgs, const std::vector &templateTypeHints, bool strictSpecifierMatching, const ASTNode *callNode) { - assert(requestedThisType.isOneOf({TY_DYN, TY_STRUCT, TY_INTERFACE})); + assert(reqThisType.isOneOf({TY_DYN, TY_STRUCT, TY_INTERFACE})); // Copy the registry to prevent iterating over items, that are created within the loop FunctionRegistry functionRegistry = matchScope->functions; @@ -210,15 +209,15 @@ Function *FunctionManager::matchFunction(Scope *matchScope, const std::string &r // Prepare type mapping, based on the given initial type mapping TypeMapping &typeMapping = candidate.typeMapping; typeMapping.clear(); - for (size_t i = 0; i < std::min(requestedTemplateTypes.size(), candidate.templateTypes.size()); i++) { + for (size_t i = 0; i < std::min(templateTypeHints.size(), candidate.templateTypes.size()); i++) { const std::string &typeName = candidate.templateTypes.at(i).getSubType(); - const SymbolType &templateType = requestedTemplateTypes.at(i); + const SymbolType &templateType = templateTypeHints.at(i); typeMapping.insert({typeName, templateType}); } bool forceSubstantiation = false; - MatchResult matchResult = matchManifestation(candidate, matchScope, requestedName, requestedThisType, requestedArgs, - typeMapping, strictSpecifierMatching, forceSubstantiation, callNode); + MatchResult matchResult = matchManifestation(candidate, matchScope, reqName, reqThisType, reqArgs, typeMapping, + strictSpecifierMatching, forceSubstantiation, callNode); if (matchResult == MatchResult::SKIP_FUNCTION) break; // Leave the whole function if (matchResult == MatchResult::SKIP_MANIFESTATION) @@ -247,7 +246,7 @@ Function *FunctionManager::matchFunction(Scope *matchScope, const std::string &r Function *substantiatedFunction = insertSubstantiation(matchScope, candidate, presetFunction.declNode); substantiatedFunction->genericSubstantiation = true; substantiatedFunction->alreadyTypeChecked = false; - substantiatedFunction->declNode->getFctManifestations(requestedName)->push_back(substantiatedFunction); + substantiatedFunction->declNode->getFctManifestations(reqName)->push_back(substantiatedFunction); // Copy function entry const std::string newSignature = substantiatedFunction->getSignature(false); @@ -293,20 +292,20 @@ Function *FunctionManager::matchFunction(Scope *matchScope, const std::string &r return matches.front(); } -MatchResult FunctionManager::matchManifestation(Function &candidate, Scope *&matchScope, const std::string &requestedName, - const SymbolType &requestedThisType, const ArgList &requestedArgs, - TypeMapping &typeMapping, bool strictSpecifierMatching, bool &forceSubstantiation, +MatchResult FunctionManager::matchManifestation(Function &candidate, Scope *&matchScope, const std::string &reqName, + const SymbolType &reqThisType, const ArgList &reqArgs, TypeMapping &typeMapping, + bool strictSpecifierMatching, bool &forceSubstantiation, const ASTNode *callNode) { // Check name requirement - if (!matchName(candidate, requestedName)) + if (!matchName(candidate, reqName)) return MatchResult::SKIP_FUNCTION; // Leave the whole manifestation list, because all have the same name // Check 'this' type requirement - if (!matchThisType(candidate, requestedThisType, typeMapping, strictSpecifierMatching)) + if (!matchThisType(candidate, reqThisType, typeMapping, strictSpecifierMatching)) return MatchResult::SKIP_MANIFESTATION; // Leave this manifestation and try the next one // Check arg types requirement - if (!matchArgTypes(candidate, requestedArgs, typeMapping, strictSpecifierMatching, forceSubstantiation, callNode)) + if (!matchArgTypes(candidate, reqArgs, typeMapping, strictSpecifierMatching, forceSubstantiation, callNode)) return MatchResult::SKIP_MANIFESTATION; // Leave this manifestation and try the next one // Check if there are unresolved generic types @@ -329,9 +328,6 @@ MatchResult FunctionManager::matchManifestation(Function &candidate, Scope *&mat candidate.thisType.setBodyScope(matchScope); } - // Clear template types of candidate, since they are not needed anymore - candidate.templateTypes.clear(); - return MatchResult::MATCHED; } @@ -339,28 +335,26 @@ MatchResult FunctionManager::matchManifestation(Function &candidate, Scope *&mat * Checks if the matching candidate fulfills the name requirement * * @param candidate Matching candidate function - * @param requestedName Requested function name + * @param reqName Requested function name * @return Fulfilled or not */ -bool FunctionManager::matchName(const Function &candidate, const std::string &requestedName) { - return candidate.name == requestedName; -} +bool FunctionManager::matchName(const Function &candidate, const std::string &reqName) { return candidate.name == reqName; } /** * Checks if the matching candidate fulfills the 'this' type requirement * * @param candidate Matching candidate function - * @param requestedThisType Requested 'this' type + * @param reqThisType Requested 'this' type * @param typeMapping Concrete template type mapping * @param strictSpecifierMatching Match specifiers strictly * @return Fulfilled or not */ -bool FunctionManager::matchThisType(Function &candidate, const SymbolType &requestedThisType, TypeMapping &typeMapping, +bool FunctionManager::matchThisType(Function &candidate, const SymbolType &reqThisType, TypeMapping &typeMapping, bool strictSpecifierMatching) { SymbolType &candidateThisType = candidate.thisType; // Shortcut for procedures - if (candidateThisType.is(TY_DYN) && requestedThisType.is(TY_DYN)) + if (candidateThisType.is(TY_DYN) && reqThisType.is(TY_DYN)) return true; // Give the type matcher a way to retrieve instances of GenericType by their name @@ -369,7 +363,7 @@ bool FunctionManager::matchThisType(Function &candidate, const SymbolType &reque }; // Check if the requested 'this' type matches the candidate 'this' type. The type mapping may be extended - if (!TypeMatcher::matchRequestedToCandidateType(candidateThisType, requestedThisType, typeMapping, genericTypeResolver, + if (!TypeMatcher::matchRequestedToCandidateType(candidateThisType, reqThisType, typeMapping, genericTypeResolver, strictSpecifierMatching)) return false; @@ -384,18 +378,18 @@ bool FunctionManager::matchThisType(Function &candidate, const SymbolType &reque * Checks if the matching candidate fulfills the argument types requirement * * @param candidate Matching candidate function - * @param requestedArgs Requested argument types + * @param reqArgs Requested argument types * @param typeMapping Concrete template type mapping * @param strictSpecifierMatching Match specifiers strictly * @param callNode Call AST node for printing error messages * @return Fulfilled or not */ -bool FunctionManager::matchArgTypes(Function &candidate, const ArgList &requestedArgs, TypeMapping &typeMapping, +bool FunctionManager::matchArgTypes(Function &candidate, const ArgList &reqArgs, TypeMapping &typeMapping, bool strictSpecifierMatching, bool &needsSubstantiation, const ASTNode *callNode) { std::vector &candidateParamList = candidate.paramList; // If the number of arguments does not match with the number of params, the matching fails - if (requestedArgs.size() != candidateParamList.size()) + if (reqArgs.size() != candidateParamList.size()) return false; // Give the type matcher a way to retrieve instances of GenericType by their name @@ -404,11 +398,11 @@ bool FunctionManager::matchArgTypes(Function &candidate, const ArgList &requeste }; // Loop over all parameters - for (size_t i = 0; i < requestedArgs.size(); i++) { + for (size_t i = 0; i < reqArgs.size(); i++) { // Retrieve actual and requested types assert(!candidateParamList.at(i).isOptional); SymbolType &candidateParamType = candidateParamList.at(i).type; - const Arg &requestedParamType = requestedArgs.at(i); + const Arg &requestedParamType = reqArgs.at(i); const SymbolType &requestedType = requestedParamType.first; const bool isArgTemporary = requestedParamType.second; diff --git a/src/typechecker/FunctionManager.h b/src/typechecker/FunctionManager.h index 6d4ed12b0..4fb7fb4a9 100644 --- a/src/typechecker/FunctionManager.h +++ b/src/typechecker/FunctionManager.h @@ -44,25 +44,25 @@ class FunctionManager { static void substantiateOptionalParams(const Function &baseFunction, std::vector &manifestations); [[nodiscard]] static Function createMainFunction(SymbolTableEntry *entry, const std::vector ¶mTypes, ASTNode *declNode); - [[nodiscard]] static const Function *lookupFunction(Scope *matchScope, const std::string &requestedName, - const SymbolType &requestedThisType, const ArgList &requestedArgs, + [[nodiscard]] static const Function *lookupFunction(Scope *matchScope, const std::string &reqName, + const SymbolType &reqThisType, const ArgList &reqArgs, bool strictSpecifierMatching); - static Function *matchFunction(Scope *matchScope, const std::string &requestedName, const SymbolType &requestedThisType, - const ArgList &requestedArgs, const std::vector &requestedTemplateTypes, + static Function *matchFunction(Scope *matchScope, const std::string &reqName, const SymbolType &reqThisType, + const ArgList &reqArgs, const std::vector &templateTypeHints, bool strictSpecifierMatching, const ASTNode *callNode); private: // Private methods [[nodiscard]] static Function *insertSubstantiation(Scope *insertScope, const Function &newManifestation, const ASTNode *declNode); - [[nodiscard]] static MatchResult matchManifestation(Function &candidate, Scope *&matchScope, const std::string &requestedName, - const SymbolType &requestedThisType, const ArgList &requestedArgs, + [[nodiscard]] static MatchResult matchManifestation(Function &candidate, Scope *&matchScope, const std::string &reqName, + const SymbolType &reqThisType, const ArgList &reqArgs, TypeMapping &typeMapping, bool strictSpecifierMatching, bool &forceSubstantiation, const ASTNode *callNode); - [[nodiscard]] static bool matchName(const Function &candidate, const std::string &requestedName); - [[nodiscard]] static bool matchThisType(Function &candidate, const SymbolType &requestedThisType, TypeMapping &typeMapping, + [[nodiscard]] static bool matchName(const Function &candidate, const std::string &reqName); + [[nodiscard]] static bool matchThisType(Function &candidate, const SymbolType &reqThisType, TypeMapping &typeMapping, bool strictSpecifierMatching); - [[nodiscard]] static bool matchArgTypes(Function &candidate, const ArgList &requestedArgTypes, TypeMapping &typeMapping, + [[nodiscard]] static bool matchArgTypes(Function &candidate, const ArgList &reqArgs, TypeMapping &typeMapping, bool strictSpecifierMatching, bool &needsSubstantiation, const ASTNode *callNode); static void substantiateReturnType(Function &candidate, TypeMapping &typeMapping); [[nodiscard]] static const GenericType *getGenericTypeOfCandidateByName(const Function &candidate, diff --git a/src/typechecker/InterfaceManager.cpp b/src/typechecker/InterfaceManager.cpp index e6599840f..7caf17fad 100644 --- a/src/typechecker/InterfaceManager.cpp +++ b/src/typechecker/InterfaceManager.cpp @@ -44,13 +44,13 @@ Interface *InterfaceManager::insertSubstantiation(Scope *insertScope, Interface * If more than one interface matches the requirement, an error gets thrown * * @param matchScope Scope to match against - * @param requestedName Interface name requirement - * @param requestedTemplateTypes Template types to substantiate generic types + * @param reqName Interface name requirement + * @param reqTemplateTypes Template types to substantiate generic types * @param node Instantiation AST node for printing error messages * @return Matched interface or nullptr */ -Interface *InterfaceManager::matchInterface(Scope *matchScope, const std::string &requestedName, - const std::vector &requestedTemplateTypes, const ASTNode *node) { +Interface *InterfaceManager::matchInterface(Scope *matchScope, const std::string &reqName, + const std::vector &reqTemplateTypes, const ASTNode *node) { // Copy the registry to prevent iterating over items, that are created within the loop InterfaceRegistry interfaceRegistry = matchScope->interfaces; // Loop over interface registry to find interfaces, that match the requirements of the instantiation @@ -67,7 +67,7 @@ Interface *InterfaceManager::matchInterface(Scope *matchScope, const std::string continue; // Check name requirement - if (!matchName(candidate, requestedName)) + if (!matchName(candidate, reqName)) break; // Leave the whole manifestation list, because all manifestations in this list have the same name // Prepare mapping table from generic type name to concrete type @@ -76,7 +76,7 @@ Interface *InterfaceManager::matchInterface(Scope *matchScope, const std::string typeMapping.reserve(candidate.templateTypes.size()); // Check template types requirement - if (!matchTemplateTypes(candidate, requestedTemplateTypes, typeMapping)) + if (!matchTemplateTypes(candidate, reqTemplateTypes, typeMapping)) continue; // Leave this manifestation and continue with the next one // Map signatures from generic to concrete @@ -154,24 +154,22 @@ Interface *InterfaceManager::matchInterface(Scope *matchScope, const std::string * Checks if the matching candidate fulfills the name requirement * * @param candidate Matching candidate interface - * @param requestedName Requested interface name + * @param reqName Requested interface name * @return Fulfilled or not */ -bool InterfaceManager::matchName(const Interface &candidate, const std::string &requestedName) { - return candidate.name == requestedName; -} +bool InterfaceManager::matchName(const Interface &candidate, const std::string &reqName) { return candidate.name == reqName; } /** * Checks if the matching candidate fulfills the template types requirement * * @param candidate Matching candidate interface - * @param requestedTemplateTypes Requested interface template types + * @param reqTemplateTypes Requested interface template types * @return Fulfilled or not */ -bool InterfaceManager::matchTemplateTypes(Interface &candidate, const std::vector &requestedTemplateTypes, +bool InterfaceManager::matchTemplateTypes(Interface &candidate, const std::vector &reqTemplateTypes, TypeMapping &typeMapping) { // Check if the number of types match - const size_t typeCount = requestedTemplateTypes.size(); + const size_t typeCount = reqTemplateTypes.size(); if (typeCount != candidate.templateTypes.size()) return false; @@ -182,11 +180,11 @@ bool InterfaceManager::matchTemplateTypes(Interface &candidate, const std::vecto // Loop over all template types for (size_t i = 0; i < typeCount; i++) { - const SymbolType &requestedType = requestedTemplateTypes.at(i); + const SymbolType &reqType = reqTemplateTypes.at(i); SymbolType &candidateType = candidate.templateTypes.at(i); // Check if the requested template type matches the candidate template type. The type mapping may be extended - if (!TypeMatcher::matchRequestedToCandidateType(candidateType, requestedType, typeMapping, genericTypeResolver, false)) + if (!TypeMatcher::matchRequestedToCandidateType(candidateType, reqType, typeMapping, genericTypeResolver, false)) return false; // Substantiate the candidate param type, based on the type mapping diff --git a/src/typechecker/InterfaceManager.h b/src/typechecker/InterfaceManager.h index e5ef40fbe..c016edeae 100644 --- a/src/typechecker/InterfaceManager.h +++ b/src/typechecker/InterfaceManager.h @@ -24,14 +24,14 @@ class InterfaceManager { public: // Public methods static Interface *insertInterface(Scope *insertScope, Interface &spiceInterface, std::vector *nodeInterfaceList); - [[nodiscard]] static Interface *matchInterface(Scope *matchScope, const std::string &requestedName, - const std::vector &requestedTemplateTypes, const ASTNode *node); + [[nodiscard]] static Interface *matchInterface(Scope *matchScope, const std::string &reqName, + const std::vector &reqTemplateTypes, const ASTNode *node); private: // Private methods [[nodiscard]] static Interface *insertSubstantiation(Scope *insertScope, Interface &newManifestation, const ASTNode *declNode); - [[nodiscard]] static bool matchName(const Interface &candidate, const std::string &requestedName); - [[nodiscard]] static bool matchTemplateTypes(Interface &candidate, const std::vector &requestedTemplateTypes, + [[nodiscard]] static bool matchName(const Interface &candidate, const std::string &reqName); + [[nodiscard]] static bool matchTemplateTypes(Interface &candidate, const std::vector &reqTemplateTypes, TypeMapping &typeMapping); static void substantiateSignatures(Interface &candidate, TypeMapping &typeMapping); [[nodiscard]] static const GenericType *getGenericTypeOfCandidateByName(const Interface &candidate, diff --git a/src/typechecker/OpRuleManager.cpp b/src/typechecker/OpRuleManager.cpp index e8f898dc1..12b0ffc78 100644 --- a/src/typechecker/OpRuleManager.cpp +++ b/src/typechecker/OpRuleManager.cpp @@ -100,6 +100,9 @@ SymbolType OpRuleManager::getFieldAssignResultType(const ASTNode *node, const Ex // Allow ref type to type of the same contained type straight away if (rhsType.isRef() && lhsType.matches(rhsType.getContainedTy(), false, false, true)) return lhsType; + // Allow const ref type to type of the same contained type straight away + if (rhsType.isConstRef() && lhsType.matches(rhsType.getContainedTy().getNonConst(), false, false, true)) + return lhsType; // Allow immediate value to const ref of the same contained type straight away if (lhsType.isRef() && lhsType.getContainedTy().isConst() && imm) return rhsType; diff --git a/src/typechecker/StructManager.cpp b/src/typechecker/StructManager.cpp index bafc2d8ea..c01a9beed 100644 --- a/src/typechecker/StructManager.cpp +++ b/src/typechecker/StructManager.cpp @@ -43,13 +43,13 @@ Struct *StructManager::insertSubstantiation(Scope *insertScope, Struct &newManif * If more than one struct matches the requirement, an error gets thrown * * @param matchScope Scope to match against - * @param requestedName Struct name requirement - * @param requestedTemplateTypes Template types to substantiate generic types + * @param reqName Struct name requirement + * @param reqTemplateTypes Template types to substantiate generic types * @param node Instantiation AST node for printing error messages * @return Matched struct or nullptr */ -Struct *StructManager::matchStruct(Scope *matchScope, const std::string &requestedName, - const std::vector &requestedTemplateTypes, const ASTNode *node) { +Struct *StructManager::matchStruct(Scope *matchScope, const std::string &reqName, const std::vector &reqTemplateTypes, + const ASTNode *node) { // Copy the registry to prevent iterating over items, that are created within the loop StructRegistry structRegistry = matchScope->structs; // Loop over struct registry to find structs, that match the requirements of the instantiation @@ -66,7 +66,7 @@ Struct *StructManager::matchStruct(Scope *matchScope, const std::string &request continue; // Check name requirement - if (!matchName(candidate, requestedName)) + if (!matchName(candidate, reqName)) break; // Leave the whole manifestation list, because all manifestations in this list have the same name // Prepare mapping table from generic type name to concrete type @@ -75,7 +75,7 @@ Struct *StructManager::matchStruct(Scope *matchScope, const std::string &request typeMapping.reserve(candidate.templateTypes.size()); // Check template types requirement - if (!matchTemplateTypes(candidate, requestedTemplateTypes, typeMapping)) + if (!matchTemplateTypes(candidate, reqTemplateTypes, typeMapping)) continue; // Leave this manifestation and continue with the next one // Map field types from generic to concrete @@ -132,7 +132,16 @@ Struct *StructManager::matchStruct(Scope *matchScope, const std::string &request // Replace field type with concrete template type SymbolTableEntry *fieldEntry = substantiatedStruct->scope->symbolTable.lookupStrictByIndex(explicitFieldsStartIdx + i); assert(fieldEntry != nullptr && fieldEntry->isField()); - fieldEntry->updateType(substantiatedStruct->fieldTypes.at(i), /*overwriteExistingType=*/true); + SymbolType &fieldType = substantiatedStruct->fieldTypes.at(i); + SymbolType baseType = fieldType.getBaseType(); + + // Set the body scope of fields that are of type * + if (baseType.matches(substantiatedStruct->entry->getType(), false, true, true)) { + baseType.setBodyScope(substantiatedStruct->scope); + fieldType = fieldType.replaceBaseType(baseType); + } + + fieldEntry->updateType(fieldType, /*overwriteExistingType=*/true); } // Instantiate implemented interfaces if required @@ -174,24 +183,22 @@ Struct *StructManager::matchStruct(Scope *matchScope, const std::string &request * Checks if the matching candidate fulfills the name requirement * * @param candidate Matching candidate struct - * @param requestedName Requested struct name + * @param reqName Requested struct name * @return Fulfilled or not */ -bool StructManager::matchName(const Struct &candidate, const std::string &requestedName) { - return candidate.name == requestedName; -} +bool StructManager::matchName(const Struct &candidate, const std::string &reqName) { return candidate.name == reqName; } /** * Checks if the matching candidate fulfills the template types requirement * * @param candidate Matching candidate struct - * @param requestedTemplateTypes Requested struct template types + * @param reqTemplateTypes Requested struct template types * @return Fulfilled or not */ -bool StructManager::matchTemplateTypes(Struct &candidate, const std::vector &requestedTemplateTypes, +bool StructManager::matchTemplateTypes(Struct &candidate, const std::vector &reqTemplateTypes, TypeMapping &typeMapping) { // Check if the number of types match - const size_t typeCount = requestedTemplateTypes.size(); + const size_t typeCount = reqTemplateTypes.size(); if (typeCount != candidate.templateTypes.size()) return false; @@ -202,11 +209,11 @@ bool StructManager::matchTemplateTypes(Struct &candidate, const std::vector *nodeStructList); - [[nodiscard]] static Struct *matchStruct(Scope *matchScope, const std::string &requestedName, - const std::vector &requestedTemplateTypes, const ASTNode *node); + [[nodiscard]] static Struct *matchStruct(Scope *matchScope, const std::string &reqName, + const std::vector &reqTemplateTypes, const ASTNode *node); private: // Private methods [[nodiscard]] static Struct *insertSubstantiation(Scope *insertScope, Struct &newManifestation, const ASTNode *declNode); - [[nodiscard]] static bool matchName(const Struct &candidate, const std::string &requestedName); - [[nodiscard]] static bool matchTemplateTypes(Struct &candidate, const std::vector &requestedTemplateTypes, + [[nodiscard]] static bool matchName(const Struct &candidate, const std::string &reqName); + [[nodiscard]] static bool matchTemplateTypes(Struct &candidate, const std::vector &reqTemplateTypes, TypeMapping &typeMapping); static void substantiateFieldTypes(Struct &candidate, TypeMapping &typeMapping); [[nodiscard]] static const GenericType *getGenericTypeOfCandidateByName(const Struct &candidate, diff --git a/src/typechecker/TypeChecker.cpp b/src/typechecker/TypeChecker.cpp index 6dbefa5b5..7967b0dca 100644 --- a/src/typechecker/TypeChecker.cpp +++ b/src/typechecker/TypeChecker.cpp @@ -150,7 +150,8 @@ std::any TypeChecker::visitForeachLoop(ForeachLoopNode *node) { ScopeHandle scopeHandle(this, node->getScopeId(), ScopeType::FOREACH_BODY); // Visit iterator assignment - SymbolType iteratorOrIterableType = std::any_cast(visit(node->iteratorAssign())).type; + AssignExprNode *iteratorNode = node->iteratorAssign(); + SymbolType iteratorOrIterableType = std::any_cast(visit(iteratorNode)).type; HANDLE_UNRESOLVED_TYPE_PTR(iteratorOrIterableType) // Retrieve iterator type @@ -158,9 +159,11 @@ std::any TypeChecker::visitForeachLoop(ForeachLoopNode *node) { if (iteratorOrIterableType.isIterable(node)) { const SymbolType &iterableType = iteratorOrIterableType; Scope *matchScope = iterableType.getBodyScope(); - node->getIteratorFct = FunctionManager::matchFunction(matchScope, "getIterator", iterableType, {}, {}, true, node); + node->getIteratorFct = FunctionManager::matchFunction(matchScope, "getIterator", iterableType, {}, {}, true, iteratorNode); assert(node->getIteratorFct != nullptr); // At this point we are sure to implement IIterable, so we also have getIterator() iteratorType = node->getIteratorFct->returnType; + // Create anonymous entry for the iterator + currentScope->symbolTable.insertAnonymous(iteratorType, iteratorNode); } // Check iterator type @@ -422,6 +425,7 @@ std::any TypeChecker::visitField(FieldNode *node) { if (TernaryExprNode *defaultValueNode = node->defaultValue()) { const SymbolType defaultValueType = std::any_cast(visit(defaultValueNode)).type; + HANDLE_UNRESOLVED_TYPE_ST(defaultValueType) if (!fieldType.matches(defaultValueType, false, true, true)) SOFT_ERROR_ST(node, FIELD_TYPE_NOT_MATCHING, "Type of the default values does not match the field type") } @@ -486,12 +490,6 @@ std::any TypeChecker::visitSignature(SignatureNode *node) { } } - // Check if all template types were used in the function parameters or in the return type - if (std::ranges::any_of(usedGenericTypes, [](const GenericType &genericType) { return !genericType.used; })) { - softError(node->templateTypeLst(), GENERIC_TYPE_NOT_USED, "Generic type was not used by the function parameters"); - return static_cast *>(nullptr); - } - // Build signature object Function signature(node->methodName, nullptr, SymbolType(TY_DYN), returnType, paramList, usedGenericTypes, node); @@ -1749,8 +1747,14 @@ bool TypeChecker::visitOrdinaryFctCall(FctCallNode *node, const std::vectordata.at(manIdx); // Check if this is a ctor call to the String type - if (node->functionNameFragments.size() == 1 && node->fqFunctionName == STROBJ_NAME && !sourceFile->isStringRT()) - sourceFile->requestRuntimeModule(STRING_RT); + if (node->functionNameFragments.size() == 1) { + for (const auto &[typeName, runtimeModule] : TYPE_NAME_TO_RT_MODULE_MAPPING) + if (fqFunctionName == typeName && !sourceFile->isRT(runtimeModule)) + sourceFile->requestRuntimeModule(runtimeModule); + for (const auto &[fctName, runtimeModule] : FCT_NAME_TO_RT_MODULE_MAPPING) + if (fqFunctionName == fctName && !sourceFile->isRT(runtimeModule)) + sourceFile->requestRuntimeModule(runtimeModule); + } // Check if the exported name registry contains that function name const NameRegistryEntry *functionRegistryEntry = sourceFile->getNameRegistryEntry(fqFunctionName); @@ -2302,14 +2306,16 @@ std::any TypeChecker::visitCustomDataType(CustomDataTypeNode *node) { // It is a struct type -> get the access scope Scope *localAccessScope = accessScope ? accessScope : currentScope; - const bool isImported = node->typeNameFragments.size() > 1; const std::string firstFragment = node->typeNameFragments.front(); - // Check if it is a String type - if (!isImported && firstFragment == STROBJ_NAME && !sourceFile->isStringRT()) - sourceFile->requestRuntimeModule(STRING_RT); + // Check this type requires a runtime module + if (node->typeNameFragments.size() == 1) + for (const auto &[typeName, runtimeModule] : TYPE_NAME_TO_RT_MODULE_MAPPING) + if (firstFragment == typeName && !sourceFile->isRT(runtimeModule)) + sourceFile->requestRuntimeModule(runtimeModule); // Check if it is a generic type + const bool isImported = node->typeNameFragments.size() > 1; const SymbolType *genericType = rootScope->lookupGenericType(firstFragment); if (!isImported && genericType) { // Take the concrete replacement type for the name of this generic type if available @@ -2355,7 +2361,6 @@ std::any TypeChecker::visitCustomDataType(CustomDataTypeNode *node) { if (entryType.isOneOf({TY_STRUCT, TY_INTERFACE})) { const DataTypeNode *dataTypeNode = dynamic_cast(node->parent->parent); assert(dataTypeNode != nullptr); - const bool isParamOrFieldOrReturnType = dataTypeNode->isParamType || dataTypeNode->isFieldType || dataTypeNode->isReturnType; // Collect the concrete template types bool allTemplateTypesConcrete = true; @@ -2365,9 +2370,6 @@ std::any TypeChecker::visitCustomDataType(CustomDataTypeNode *node) { for (DataTypeNode *dataType : node->templateTypeLst()->dataTypes()) { auto templateType = std::any_cast(visit(dataType)); HANDLE_UNRESOLVED_TYPE_ST(templateType) - // Generic types are only allowed for parameters and fields at this point - if (entryType.is(TY_STRUCT) && templateType.is(TY_GENERIC) && !isParamOrFieldOrReturnType) - SOFT_ERROR_ST(dataType, EXPECTED_NON_GENERIC_TYPE, "Only concrete template types are allowed here") if (entryType.is(TY_GENERIC)) allTemplateTypesConcrete = false; templateTypes.push_back(templateType); @@ -2382,7 +2384,7 @@ std::any TypeChecker::visitCustomDataType(CustomDataTypeNode *node) { if (declCodeLoc.sourceFile->filePath == codeLoc.sourceFile->filePath && declCodeLoc > codeLoc) SOFT_ERROR_ST(node, REFERENCED_UNDEFINED_STRUCT, "Structs must be defined before usage") - if (allTemplateTypesConcrete || !isParamOrFieldOrReturnType) { // Only do the next step, if we have concrete template types + if (allTemplateTypesConcrete) { // Only do the next step, if we have concrete template types // Set the struct instance to used, if found // Here, it is allowed to accept, that the struct cannot be found, because there are self-referencing structs const std::string structName = node->typeNameFragments.back(); diff --git a/src/typechecker/TypeCheckerImplicit.cpp b/src/typechecker/TypeCheckerImplicit.cpp index df2af483b..9944af524 100644 --- a/src/typechecker/TypeCheckerImplicit.cpp +++ b/src/typechecker/TypeCheckerImplicit.cpp @@ -28,7 +28,7 @@ void TypeChecker::createDefaultStructMethod(const Struct &spiceStruct, const std // Procedure type SymbolType procedureType(TY_PROCEDURE); - procedureType.specifiers.isPublic = structEntry->getType().specifiers.isPublic; + procedureType.specifiers.isPublic = true; // Always public // Insert symbol for function into the symbol table const std::string entryName = Function::getSymbolTableEntryName(methodName, node->codeLoc); diff --git a/src/typechecker/TypeCheckerPrepare.cpp b/src/typechecker/TypeCheckerPrepare.cpp index 631d842a5..5a7b17a8c 100644 --- a/src/typechecker/TypeCheckerPrepare.cpp +++ b/src/typechecker/TypeCheckerPrepare.cpp @@ -134,11 +134,6 @@ std::any TypeChecker::visitFctDefPrepare(FctDefNode *node) { SOFT_ERROR_BOOL(node->returnType(), GENERIC_TYPE_NOT_IN_TEMPLATE, "Generic return type not included in the template type list of the function") - // Check if all template types were used by at least one parameter or the return type - if (std::ranges::any_of(usedGenericTypes, [](const GenericType &genericType) { return !genericType.used; })) - SOFT_ERROR_BOOL(node->templateTypeLst(), GENERIC_TYPE_NOT_USED, - "Generic type was not used by the function parameters or the return type") - // Leave function body scope currentScope = node->scope->parent; assert(currentScope->type == ScopeType::GLOBAL || currentScope->type == ScopeType::STRUCT); @@ -270,10 +265,6 @@ std::any TypeChecker::visitProcDefPrepare(ProcDefNode *node) { } } - // Check if all template types were used by at least one parameter - if (std::ranges::any_of(usedGenericTypes, [](const GenericType &genericType) { return !genericType.used; })) - SOFT_ERROR_BOOL(node->templateTypeLst(), GENERIC_TYPE_NOT_USED, "Generic type was not used by the procedure parameters") - // Leave procedure body scope currentScope = node->scope->parent; assert(currentScope->type == ScopeType::GLOBAL || currentScope->type == ScopeType::STRUCT); @@ -405,10 +396,6 @@ std::any TypeChecker::visitStructDefPrepare(StructDefNode *node) { throw SemanticError(field->dataType(), GENERIC_TYPE_NOT_IN_TEMPLATE, "Generic field type not included in struct template"); } - // Check if all template types were used by at least one field - if (std::ranges::any_of(templateTypesGeneric, [&](const GenericType &genericType) { return !genericType.used; })) - softError(node->templateTypeLst(), GENERIC_TYPE_NOT_USED, "Generic type was not used by the struct fields"); - // Change to the root scope currentScope = rootScope; assert(currentScope->type == ScopeType::GLOBAL); diff --git a/src/typechecker/TypeMatcher.cpp b/src/typechecker/TypeMatcher.cpp index 7013ba837..34ec0eadf 100644 --- a/src/typechecker/TypeMatcher.cpp +++ b/src/typechecker/TypeMatcher.cpp @@ -7,19 +7,19 @@ namespace spice::compiler { bool TypeMatcher::matchRequestedToCandidateTypes(const std::vector &candidateTypes, - const std::vector &requestedTypes, TypeMapping &typeMapping, + const std::vector &reqTypes, TypeMapping &typeMapping, ResolverFct &resolverFct, bool strictSpecifiers) { // Check if the size of template types matches - if (requestedTypes.size() != candidateTypes.size()) + if (reqTypes.size() != candidateTypes.size()) return false; // Loop through both lists at the same time and match each pair of template types individually for (size_t i = 0; i < candidateTypes.size(); i++) { - const SymbolType &requestedType = requestedTypes.at(i); + const SymbolType &reqType = reqTypes.at(i); const SymbolType &candidateType = candidateTypes.at(i); // Match the pair of template types - if (!matchRequestedToCandidateType(candidateType, requestedType, typeMapping, resolverFct, strictSpecifiers)) + if (!matchRequestedToCandidateType(candidateType, reqType, typeMapping, resolverFct, strictSpecifiers)) return false; } return true; @@ -67,6 +67,7 @@ bool TypeMatcher::matchRequestedToCandidateType(SymbolType candidateType, Symbol // Add to type mapping const SymbolType newMappingType = requestedType.hasAnyGenericParts() ? candidateType : requestedType; + assert(newMappingType.is(TY_GENERIC) || newMappingType.specifiers.isSigned != newMappingType.specifiers.isUnsigned); typeMapping.insert({genericTypeName, newMappingType}); return true; // The type was successfully matched, by enriching the type mapping diff --git a/src/typechecker/TypeMatcher.h b/src/typechecker/TypeMatcher.h index 6261a4876..64bfaed94 100644 --- a/src/typechecker/TypeMatcher.h +++ b/src/typechecker/TypeMatcher.h @@ -20,7 +20,7 @@ class TypeMatcher { // Public methods static bool matchRequestedToCandidateTypes(const std::vector &candidateType, - const std::vector &requestedType, TypeMapping &typeMapping, + const std::vector &reqTypes, TypeMapping &typeMapping, ResolverFct &resolverFct, bool strictSpecifiers); static bool matchRequestedToCandidateType(SymbolType candidateType, SymbolType requestedType, TypeMapping &typeMapping, ResolverFct &resolverFct, bool strictSpecifierMatching, diff --git a/src/util/CommonUtil.cpp b/src/util/CommonUtil.cpp index 49d33a728..fc8cd1b40 100644 --- a/src/util/CommonUtil.cpp +++ b/src/util/CommonUtil.cpp @@ -2,6 +2,8 @@ #include "CommonUtil.h" +#include + #ifdef OS_WINDOWS #include #elif OS_UNIX @@ -87,6 +89,18 @@ size_t CommonUtil::getSystemPageSize() { #endif } +/** + * Check if the given string is a valid mangled name + * + * @return + */ +bool CommonUtil::isValidMangledName(const std::string &mangledName) { + int status; + char *demangled = abi::__cxa_demangle(mangledName.c_str(), nullptr, nullptr, &status); + free(demangled); + return status == 0; +} + /** * Generate the version info string for the Spice driver * diff --git a/src/util/CommonUtil.h b/src/util/CommonUtil.h index 7d5cd29c1..53ed8415f 100644 --- a/src/util/CommonUtil.h +++ b/src/util/CommonUtil.h @@ -18,6 +18,7 @@ class CommonUtil { static std::string trim(const std::string &input); static std::vector split(const std::string &input); static size_t getSystemPageSize(); + static bool isValidMangledName(const std::string &mangledName); static std::string getVersionInfo(); }; diff --git a/src/util/FileUtil.cpp b/src/util/FileUtil.cpp index 808d9e393..964494216 100644 --- a/src/util/FileUtil.cpp +++ b/src/util/FileUtil.cpp @@ -3,6 +3,7 @@ #include "FileUtil.h" #include "exception/CompilerError.h" +#include #include #include @@ -47,17 +48,27 @@ std::string FileUtil::getFileContent(const std::filesystem::path &filePath) { * @param cmd Command to execute * @return Result struct */ -ExecResult FileUtil::exec(const std::string &cmd) { - FILE *pipe = popen(cmd.c_str(), "r"); - if (!pipe) // GCOV_EXCL_LINE - throw CompilerError(IO_ERROR, "Failed to execute command: " + cmd); // GCOV_EXCL_LINE - char buffer[128]; +ExecResult FileUtil::exec(const std::string &command) { +#ifdef _WIN32 + const std::string quotedCommand = "\"" + command + "\""; + FILE *pipe = _popen(quotedCommand.c_str(), "r"); +#else + FILE *pipe = popen(command.c_str(), "r"); +#endif + + if (!pipe) // GCOV_EXCL_LINE + throw CompilerError(IO_ERROR, "Failed to execute command: " + command); // GCOV_EXCL_LINE + + std::array buffer{}; std::stringstream result; - while (!feof(pipe)) { - if (fgets(buffer, 128, pipe) != nullptr) - result << buffer; - } - int exitCode = pclose(pipe) / 256; + while (fgets(buffer.data(), buffer.size(), pipe) != nullptr) + result << buffer.data(); + +#ifdef _WIN32 + const int exitCode = _pclose(pipe); +#else + const int exitCode = pclose(pipe) / 256; +#endif return {result.str(), exitCode}; } diff --git a/src/util/FileUtil.h b/src/util/FileUtil.h index 7c51cbc86..49aa3721f 100644 --- a/src/util/FileUtil.h +++ b/src/util/FileUtil.h @@ -19,7 +19,7 @@ class FileUtil { public: static void writeToFile(const std::filesystem::path &fileName, const std::string &fileContent); static std::string getFileContent(const std::filesystem::path &filePath); - static ExecResult exec(const std::string &cmd); + static ExecResult exec(const std::string &command); static bool isCommandAvailable(const std::string &cmd); static std::filesystem::path getStdDir(); static std::filesystem::path getSpiceBinDir(); diff --git a/std/data/binary-tree.spice b/std/data/binary-tree.spice index 99d10f13e..7c640491b 100644 --- a/std/data/binary-tree.spice +++ b/std/data/binary-tree.spice @@ -9,8 +9,8 @@ type T dyn; * Node of a BinaryTree */ public type Node struct { - heap Node* childLeft - heap Node* childRight + heap Node* childLeft = nil*> + heap Node* childRight = nil*> T value } @@ -24,31 +24,8 @@ public type Node struct { * Search: O(log n) */ public type BinaryTree struct { - heap Node* rootNode - bool isBalanced -} - -public p BinaryTree.ctor() { - this.rootNode = nil*>; - this.isBalanced = false; -} - -public p BinaryTree.dtor() { - if this.rootNode != nil*> { - this.rootNode.dtor(); - free((heap byte*) this.rootNode); - } -} - -public p Node.dtor() { - if this.childLeft != nil*> { - this.childLeft.dtor(); - free((heap byte*) this.childLeft); - } - if this.childRight != nil*> { - this.childRight.dtor(); - free((heap byte*) this.childRight); - } + heap Node* rootNode = nil*> + bool isBalanced = false } public p BinaryTree.insert(T newValue, heap Node* baseNode = nil*>) { diff --git a/std/data/doubly-linked-list.spice b/std/data/doubly-linked-list.spice index a46b41e89..1a2a17069 100644 --- a/std/data/doubly-linked-list.spice +++ b/std/data/doubly-linked-list.spice @@ -9,13 +9,12 @@ type T dyn; */ type Node struct { T value - heap Node* prev - heap Node* next + heap Node* prev = nil*> + heap Node* next = nil*> } p Node.ctor(const T& value) { this.value = value; - this.next = nil*>; } /** @@ -24,16 +23,11 @@ p Node.ctor(const T& value) { * to the previous one. */ public type DoublyLinkedList struct { - heap Node* head - heap Node* tail + heap Node* head = nil*> + heap Node* tail = nil*> unsigned long size = 0l } -public p DoublyLinkedList.ctor() { - this.tail = nil*>; - this.head = nil*>; -} - public p DoublyLinkedList.pushBack(const T& value) { heap Node* newNode = this.createNode(value); if this.isEmpty() { diff --git a/std/data/linked-list.spice b/std/data/linked-list.spice index 50bc83535..513de1758 100644 --- a/std/data/linked-list.spice +++ b/std/data/linked-list.spice @@ -13,12 +13,11 @@ type Numeric int|long|short; */ type Node struct { T value - heap Node* next + heap Node* next = nil*> } p Node.ctor(const T& value) { this.value = value; - this.next = nil*>; } /** @@ -37,16 +36,11 @@ p Node.ctor(const T& value) { * Beware that each add operation allocates memory and every remove operation frees memory. */ public type LinkedList struct : IIterable { - heap Node* tail - heap Node* head + heap Node* tail = nil*> + heap Node* head = nil*> unsigned long size = 0l } -public p LinkedList.ctor() { - this.tail = nil*>; - this.head = nil*>; -} - public p LinkedList.pushBack(const T& value) { // Create new node heap Node* newNode = this.createNode(value); diff --git a/std/data/map.spice b/std/data/map.spice index 5b4b56a9d..2dbf0fe39 100644 --- a/std/data/map.spice +++ b/std/data/map.spice @@ -1,6 +1,5 @@ -// Constants -const unsigned long INITIAL_ALLOC_COUNT = 5l; -const unsigned int RESIZE_FACTOR = 2; +import "std/data/red-black-tree"; +import "std/type/result"; // Add generic type definitions type K dyn; @@ -10,14 +9,85 @@ type V dyn; * A map in Spice is a commonly used data structure, which can be used to represent a list of key value pairs. * * Time complexity: - * Insert: O(1) - * Delete: - * Search: O(1) + * Insert: O(log n) + * Delete: O(log n) + * Lookup: O(log n) */ public type Map struct { + RedBlackTree tree +} + +/** + * Inserts a key value pair into the map. + * + * @param key The key to insert. + * @param value The value to insert. + */ +public p Map.insert(const K& key, const V& value) { + this.tree.insert(key, value); +} + +/** + * Removes a key value pair from the map. + * + * @param key The key to remove. + */ +public p Map.remove(const K& key) { + this.tree.remove(key); +} +/** + * Gets a value from the map. + * Note: If the key is not found in the map, this function will panic. To avoid this, use getSafe instead. + * + * @param key The key to get. + * @return The value associated with the key. + */ +public f Map.get(const K& key) { + return this.tree.find(key); } -public p Map.ctor() { +/** + * Gets a value from the map, returning a result. + * + * @param key The key to get. + * @return The value associated with the key, or an error if the key does not exist. + */ +public f> Map.getSafe(const K& key) { + return this.tree.findSafe(key); +} +/** + * Checks if the map contains a key. + * + * @param key The key to check. + * @return True if the map contains the key, false otherwise. + */ +public f Map.contains(const K& key) { + return this.tree.contains(key); +} + +/** + * Gets the number of elements in the map. + * + * @return The number of elements in the map. + */ +public f Map.getSize() { + return this.tree.getSize(); +} + +/** + * Checks if the map is empty. + * + * @return True if the map is empty, false otherwise. + */ +public f Map.isEmpty() { + return this.tree.getSize() == 0l; +} + +/** + * Removes all elements from the map. + */ +public p Map.clear() { + this.tree.clear(); } \ No newline at end of file diff --git a/std/data/optional.spice b/std/data/optional.spice index 0b0483051..b8d574b0a 100644 --- a/std/data/optional.spice +++ b/std/data/optional.spice @@ -9,15 +9,13 @@ type T dyn; */ public type Optional struct { T data - bool isPresent + bool isPresent = false } /** * Initialize optional without a value */ -public p Optional.ctor() { - this.isPresent = false; -} +public p Optional.ctor() {} /** * Initialize optional with an initial value diff --git a/std/data/red-black-tree.spice b/std/data/red-black-tree.spice index 580ee6f4d..75cca1f8b 100644 --- a/std/data/red-black-tree.spice +++ b/std/data/red-black-tree.spice @@ -1,9 +1,9 @@ -// Link external functions -ext f malloc(long); -ext p free(heap byte*); +import "std/type/result"; +import "std/type/error"; // Add generic type definitions -type T dyn; +type K dyn; +type V dyn; // Enums type NodeColor enum { RED, BLACK } @@ -11,61 +11,405 @@ type NodeColor enum { RED, BLACK } /** * Node of a Red-Black Tree */ -type Node struct { - T data - heap Node* parent - heap Node* childLeft - heap Node* childRight +type Node struct { + K key + V value NodeColor color + heap Node* parent + heap Node* childLeft + heap Node* childRight } inline f Node.isRoot() { - return this.parent == nil*>; + return this.parent == nil*>; } -p Node.dump(unsigned int indent = 0) { - // Dump right child - if this.childRight != nil*> { this.childRight.dump(indent + 4); } - // Dump node itself - printf("%s%d %s", String(' ') * indent, this.data, this.color == NodeColor::RED ? "R" : "B"); - // Dump left child - if this.childLeft != nil*> { this.childLeft.dump(indent + 4); } +inline f Node.hasLeftChild() { + return this.childLeft != nil*>; } -f*> createNode(T data) { - Result*> allocResult = sAlloc(sizeof(type Node)); - heap Node* newNode = allocResult.unwrap(); - newNode.data = data; - newNode.childLeft = nil*>; - newNode.childRight = nil*>; - newNode.color = NodeColor::RED; - return newNode; +inline f Node.hasRightChild() { + return this.childRight != nil*>; +} + +inline f Node.isRed() { + return this.color == NodeColor::RED; +} + +inline f Node.isBlack() { + return this.color == NodeColor::BLACK; } /** * A Red-Black Tree is a self-balancing search tree, which is used e.g. in the implementation of maps. * - * Insertion time: O(log n) - * Lookup time: O(log n) - * Deletion time: O(log n) + * Time complexity: + * Insert: O(log n) + * Delete: O(log n) + * Lookup: O(log n) */ -public type RedBlackTree struct { - heap Node* rootNode +public type RedBlackTree struct { + heap Node* rootNode = nil*> + unsigned long size = 0l } -public p RedBlackTree.ctor() { - this.rootNode = nil*>; +/** + * Insert a new key-value pair into the tree. + * + * @param key The key of the new element + * @param value The value of the new element + */ +public p RedBlackTree.insert(const K& key, const V& value) { + // Create the new node + heap Node* newNode = sNew>(Node{ + key, + value, + NodeColor::RED, + nil*>, + nil*>, + nil*> + }); + + // Search for the correct position + heap Node* y = nil*>; + heap Node* x = this.rootNode; + while x != nil*> { + y = x; + if newNode.key < x.key { + x = x.childLeft; + } else { + x = x.childRight; + } + } + + // Insert the new node at the correct position + newNode.parent = y; + if y == nil*> { + this.rootNode = newNode; + } else if newNode.key < y.key { + y.childLeft = newNode; + } else { + y.childRight = newNode; + } + + // Fixup the tree + this.insertFixup(newNode); + + this.size++; +} + +/** + * Remove an element from the tree. + * + * @param key The key of the element to remove + */ +public p RedBlackTree.remove(const K& key) { + // Search for the node to remove + heap Node* z = this.search(key); + if z == nil*> { + return; + } + + heap Node* y = z; + heap Node* x; + bool wasYBlack = y.isBlack(); + if !z.hasLeftChild() { + x = z.childRight; + this.transplant(z, z.childRight); + } else if !z.hasRightChild() { + x = z.childLeft; + this.transplant(z, z.childLeft); + } else { + y = this.minimum(z.childRight); + wasYBlack = y.isBlack(); + x = y.childRight; + if y.parent == z { + x.parent = y; + } else { + this.transplant(y, y.childRight); + y.childRight = z.childRight; + y.childRight.parent = y; + } + this.transplant(z, y); + y.childLeft = z.childLeft; + y.childLeft.parent = y; + y.color = z.color; + } + + // Use dealloc, because we don't want to call the destructor. + // The destructor would delete children and parent. + unsafe { + sDealloc((byte*) z); + } + + // Do a fixup if required + if wasYBlack && x != nil*> { + this.deleteFixup(x); + } + + this.size--; } -public p RedBlackTree.insert(T newItem) { - heap Node* newNode = createNode(newItem); +/** + * Find the value for a given key. + * Note: If the key is not found in the tree, this function will panic. To avoid this, use findSafe instead. + * + * @param key The key to search for + * @return The value for the given key + */ +public f RedBlackTree.find(const K& key) { + return this.search(key).value; +} +/** + * Find the value for a given key. + * + * @param key The key to search for + * @return The value for the given key, or an error if the key was not found + */ +public f> RedBlackTree.findSafe(const K& key) { + heap Node* node = this.search(key); + if node == nil*> { + return err(Error("The provided key was not found")); + } + return ok(node.value); } -public p RedBlackTree.insertFixup(heap Node* node) { +/** + * Check if the tree contains a given key. + * + * @param key The key to search for + * @return True if the key was found, false otherwise + */ +public f RedBlackTree.contains(const K& key) { + return this.search(key) != nil*>; +} +/** + * Get the number of elements in the tree. + * + * @return The number of elements in the tree + */ +public f RedBlackTree.getSize() { + return this.size; } -public p RedBlackTree.dump() { - if this.rootNode != nil*> { this.rootNode.dump(); } +public p RedBlackTree.clear() { + this.clearRecursive(this.rootNode); + this.rootNode = nil*>; + this.size = 0l; +} + +/** + * Rotate the tree left around the given node. + * + * @param x The node to rotate around + */ +p RedBlackTree.rotateLeft(heap Node* x) { + heap Node* y = x.childRight; + x.childRight = y.childLeft; + if y.hasLeftChild() { + y.childLeft.parent = x; + } + y.parent = x.parent; + if x.isRoot() { + this.rootNode = y; + } else if x == x.parent.childLeft { + x.parent.childLeft = y; + } else { + x.parent.childRight = y; + } + y.childLeft = x; + x.parent = y; +} + +/** + * Rotate the tree right around the given node. + * + * @param y The node to rotate around + */ +p RedBlackTree.rotateRight(heap Node* y) { + heap Node* x = y.childLeft; + y.childLeft = x.childRight; + if x.hasRightChild() { + x.childRight.parent = y; + } + x.parent = y.parent; + if y.isRoot() { + this.rootNode = x; + } else if y == y.parent.childRight { + y.parent.childRight = x; + } else { + y.parent.childLeft = x; + } + x.childRight = y; + y.parent = x; +} + +/** + * Replace the subtree rooted at node u with the subtree rooted at node v. + * + * @param u The node to replace + * @param v The node to replace with + */ +p RedBlackTree.transplant(heap Node* u, heap Node* v) { + // Set v to the correct pointer + if u.isRoot() { + this.rootNode = v; + } else if u == u.parent.childLeft { + u.parent.childLeft = v; + } else { + u.parent.childRight = v; + } + + // Update the parent + if v != nil*> { + v.parent = u.parent; + } +} + +p RedBlackTree.insertFixup(heap Node* z) { + while !z.isRoot() && z.parent.isRed() { + if z.parent == z.parent.parent.childLeft { + heap Node* y = z.parent.parent.childRight; + if y != nil*> && y.isRed() { + z.parent.color = NodeColor::BLACK; + y.color = NodeColor::BLACK; + z.parent.parent.color = NodeColor::RED; + z = z.parent.parent; + } else { + if z == z.parent.childRight { + z = z.parent; + this.rotateLeft(z); + } + z.parent.color = NodeColor::BLACK; + z.parent.parent.color = NodeColor::RED; + this.rotateRight(z.parent.parent); + } + } else { + heap Node* y = z.parent.parent.childLeft; + if y != nil*> && y.isRed() { + z.parent.color = NodeColor::BLACK; + y.color = NodeColor::BLACK; + z.parent.parent.color = NodeColor::RED; + z = z.parent.parent; + } else { + if z == z.parent.childLeft { + z = z.parent; + this.rotateRight(z); + } + z.parent.color = NodeColor::BLACK; + z.parent.parent.color = NodeColor::RED; + this.rotateLeft(z.parent.parent); + } + } + } + this.rootNode.color = NodeColor::BLACK; +} + +p RedBlackTree.deleteFixup(heap Node* x) { + while x != this.rootNode && (x == nil*> || x.isBlack()) { + if x == x.parent.childLeft { + heap Node* w = x.parent.childRight; + if w != nil*> && w.isRed() { + w.color = NodeColor::BLACK; + x.parent.color = NodeColor::RED; + this.rotateLeft(x.parent); + w = x.parent.childRight; + } + if (!w.hasLeftChild() || w.childLeft.isBlack()) && (!w.hasRightChild() || w.childRight.isBlack()) { + w.color = NodeColor::RED; + x = x.parent; + } else { + if !w.hasRightChild() || w.childRight.isBlack() { + if w.hasLeftChild() { + w.childLeft.color = NodeColor::BLACK; + } + w.color = NodeColor::RED; + this.rotateRight(w); + w = x.parent.childRight; + } + w.color = x.parent.color; + x.parent.color = NodeColor::BLACK; + if w.hasRightChild() { + w.childRight.color = NodeColor::BLACK; + } + this.rotateLeft(x.parent); + x = this.rootNode; + } + } else { + heap Node* w = x.parent.childLeft; + if w != nil*> && w.isRed() { + w.color = NodeColor::BLACK; + x.parent.color = NodeColor::RED; + this.rotateRight(x.parent); + w = x.parent.childLeft; + } + if (!w.hasRightChild() || w.childRight.isBlack()) && (!w.hasLeftChild() || w.childLeft.isBlack()) { + w.color = NodeColor::RED; + x = x.parent; + } else { + if !w.hasLeftChild() || w.childLeft.isBlack() { + if w.hasRightChild() { + w.childRight.color = NodeColor::BLACK; + } + w.color = NodeColor::RED; + this.rotateLeft(w); + w = x.parent.childLeft; + } + w.color = x.parent.color; + x.parent.color = NodeColor::BLACK; + if w.hasLeftChild() { + w.childLeft.color = NodeColor::BLACK; + } + this.rotateRight(x.parent); + x = this.rootNode; + } + } + } + if x != nil*> { + x.color = NodeColor::BLACK; + } +} + +/** + * Find the node with the given key. + * + * @param key The key to search for + * @return The node with the given key, or nil if the key was not found + */ +f*> RedBlackTree.search(const K& key) { + heap Node* currentNode = this.rootNode; + while currentNode != nil*> { + if key == currentNode.key { + return currentNode; + } else if key < currentNode.key { + currentNode = currentNode.childLeft; + } else { + currentNode = currentNode.childRight; + } + } + return nil*>; +} + +/** + * Find the node with the minimum key in the subtree rooted at x. + */ +f*> RedBlackTree.minimum(heap Node* x) { + while x.hasLeftChild() { + x = x.childLeft; + } + return x; +} + +/** + * Clear the subtree rooted at the input node recursively. + */ +p RedBlackTree.clearRecursive(heap Node* node) { + // Skip if node is nil + if node == nil*> { return; } + // Otherwise, clear children and delete node + this.clearRecursive(node.childLeft); + this.clearRecursive(node.childRight); + sDelete(node); } \ No newline at end of file diff --git a/std/data/unordered-map.spice b/std/data/unordered-map.spice new file mode 100644 index 000000000..d43cb25b9 --- /dev/null +++ b/std/data/unordered-map.spice @@ -0,0 +1,19 @@ +// Add generic type definitions +type K dyn; +type V dyn; + +/** + * A map in Spice is a commonly used data structure, which can be used to represent a list of key value pairs. + * + * Time complexity: + * Insert: O(1) (average case), O(n) (worst case) + * Delete: O(1) (average case), O(n) (worst case) + * Lookup: O(1) (average case), O(n) (worst case) + */ +public type UnorderedMap struct { + +} + +public p UnorderedMap.ctor() { + +} \ No newline at end of file diff --git a/std/io/file.spice b/std/io/file.spice index 2f3a63e65..84c02438a 100644 --- a/std/io/file.spice +++ b/std/io/file.spice @@ -214,7 +214,7 @@ public f deleteFile(string path) { public f> openFile(string path, string mode = MODE_READ) { FilePtr fp = fopen(path, mode); File file = File{fp, false}; - return fp != nil ? ok(file) : err(file, Error("Failed to open file")); + return fp != nil ? ok(file) : err(Error("Failed to open file")); } /** @@ -227,7 +227,7 @@ public f> readFile(string path) { Result fileResult = openFile(path, MODE_READ); // Check for errors if !fileResult.isOk() { - return err(String(), fileResult.getErr()); + return err(fileResult.getErr()); } File file = fileResult.unwrap(); // Read from the file char by char @@ -251,7 +251,7 @@ public f> writeFile(string path, string content) { Result fileResult = openFile(path, MODE_WRITE); // Check for errors if !fileResult.isOk() { - return err(false, fileResult.getErr()); + return err(fileResult.getErr()); } File file = fileResult.unwrap(); // Write the string to the file @@ -271,7 +271,7 @@ public f> getFileSize(string path) { Result fileResult = openFile(path, MODE_READ); // Check for errors if !fileResult.isOk() { - return err((unsigned long) 0l, fileResult.getErr()); + return err(fileResult.getErr()); } File file = fileResult.unwrap(); // Get the file file diff --git a/std/iterator/number-iterator.spice b/std/iterator/number-iterator.spice index 249fb1062..971406969 100644 --- a/std/iterator/number-iterator.spice +++ b/std/iterator/number-iterator.spice @@ -104,11 +104,4 @@ public inline p operator-=(NumberIterator& it, N offset) { */ public inline f> range(N begin, N end) { return NumberIterator(begin, end); -} - -/** - * Convenience wrapper for creating a simple number iterator - */ -public inline f> iterate(N lowerBound, N upperBound) { - return NumberIterator(lowerBound, upperBound); } \ No newline at end of file diff --git a/std/runtime/memory_rt.spice b/std/runtime/memory_rt.spice index 845155845..637c3a8ec 100644 --- a/std/runtime/memory_rt.spice +++ b/std/runtime/memory_rt.spice @@ -8,6 +8,9 @@ ext f realloc(heap byte*, unsigned long); ext p free(heap byte*); ext p memcpy(heap byte*, heap byte*, unsigned long); +// Generic type defs +type T dyn; + /** * Allocates a new block of memory of the given size. * @@ -16,7 +19,7 @@ ext p memcpy(heap byte*, heap byte*, unsigned long); */ public f> sAlloc(unsigned long size) { heap byte* ptr = malloc(size); - return ptr != nil ? ok(ptr) : err(nil, "Out of memory occurred!"); + return ptr != nil ? ok(ptr) : err("Out of memory occurred!"); } /** @@ -28,7 +31,7 @@ public f> sAlloc(unsigned long size) { */ public f> sRealloc(heap byte* ptr, unsigned long size) { heap byte* newPtr = realloc(ptr, size); - return newPtr != nil ? ok(newPtr) : err(nil, "Out of memory occurred!"); + return newPtr != nil ? ok(newPtr) : err("Out of memory occurred!"); } /** @@ -41,7 +44,7 @@ public f> sRealloc(heap byte* ptr, unsigned long size) { */ public f> sCopy(heap byte* oldPtr, heap byte* newPtr, unsigned long size) { if oldPtr == nil | newPtr == nil { - return err(nil, "Cannot copy from or to nil pointer!"); + return err("Cannot copy from or to nil pointer!"); } memcpy(newPtr, oldPtr, size); return ok(newPtr); @@ -57,4 +60,64 @@ public p sDealloc(heap byte*& ptr) { if ptr == nil { return; } free(ptr); ptr = nil; // Zero out to prevent accidental double frees +} + +/** + * Allocates memory for a new instance of the given type on the heap. + * Note: This function panics if the allocation fails. + * + * @return A pointer to the heap-allocated instance + */ +public f sNew() { + unsafe { + // Allocate memory for the instance + Result res = sAlloc(sizeof(type T)); + return (heap T*) res.unwrap(); + } +} + +/** + * Allocates memory for a new instance of the given type on the heap. + * Note: This function panics if the allocation fails. + * + * @param val The value to put into the heap-allocated memory + * @return A pointer to the heap-allocated instance + */ +public f sNew(const T& val) { + unsafe { + // Allocate memory for the instance + Result res = sAlloc(sizeof(type T)); + result = (heap T*) res.unwrap(); + // Copy the value into the heap-allocated memory + sCopy((heap byte*) &val, (heap byte*) result, sizeof(type T)); + } +} + +/** + * Allocates memory for a new instance of the given type on the heap. + * + * @param ptr The pointer to the heap-allocated memory + * @param val The value to put into the heap-allocated memory + * @return A pointer to the heap-allocated instance + */ +public f sPlacementNew(heap byte* ptr, const T& val) { + unsafe { + // Copy the value into the heap-allocated memory + sCopy((heap byte*) &val, (heap byte*) ptr, sizeof(type T)); + } + return ptr; +} + +/** + * Destroys the given heap-allocated instance and frees the memory. + * + * @param ptr The pointer to the heap-allocated instance + */ +public p sDelete(heap T*& ptr) { + unsafe { + // Destruct the object + ptr.dtor(); + // Deallocate the memory + sDealloc((heap byte*&) ptr); + } } \ No newline at end of file diff --git a/std/type/result.spice b/std/type/result.spice index d9dd54778..0ad618aa6 100644 --- a/std/type/result.spice +++ b/std/type/result.spice @@ -44,6 +44,13 @@ public inline f Result.isOk() { return this.error.code == 0; } +/** + * Checks if the result contains an error. + */ +public inline f Result.isErr() { + return this.error.code != 0; +} + /** * Returns a result object with a value and no error. */ @@ -54,20 +61,20 @@ public inline f> ok(const T& data) { /** * Returns a result object with an error and no value. */ -public inline f> err(const T& data, const Error& error) { +public inline f> err(const Error& error) { return Result(error); } /** * Returns a result object with an error and no value. */ -public inline f> err(const T& data, int code, string message) { +public inline f> err(int code, string message) { return Result(Error(code, message)); } /** * Returns a result object with an error and no value. */ -public inline f> err(const T& data, string message) { +public inline f> err(string message) { return Result(Error(message)); } \ No newline at end of file diff --git a/test/TestRunner.cpp b/test/TestRunner.cpp index 4eae65ce0..62af3fb28 100644 --- a/test/TestRunner.cpp +++ b/test/TestRunner.cpp @@ -260,6 +260,10 @@ void execTestCase(const TestCase &testCase) { TestUtil::handleError(testCase, error); } catch (CompilerError &error) { TestUtil::handleError(testCase, error); + } catch (LinkerError &error) { + TestUtil::handleError(testCase, error); + } catch (std::exception &error) { + TestUtil::handleError(testCase, error); } SUCCEED(); diff --git a/test/test-files/irgenerator/debug-info/success-dbg-info-complex/debug.out b/test/test-files/irgenerator/debug-info/success-dbg-info-complex/debug.out index d8bdb4752..9d791de6a 100644 --- a/test/test-files/irgenerator/debug-info/success-dbg-info-complex/debug.out +++ b/test/test-files/irgenerator/debug-info/success-dbg-info-complex/debug.out @@ -16,7 +16,7 @@ Type "apropos word" to search for commands related to "word"... Reading symbols from .\source.exe... Breakpoint 1: file source.spice, line 42. -Thread 1 hit Breakpoint 1, _Z4mainiPPc (_argc=1, _argv=...) at source.spice:42 +Thread 1 hit Breakpoint 1, main (_argc=1, _argv=...) at source.spice:42 42 it.next(); result = 0 vi = {contents = , capacity = 5, size = 5} @@ -25,4 +25,4 @@ pair = {first = 2, second = } $1 = {contents = , capacity = 5, size = 5} $2 = 5 All assertions passed! -[Inferior 1 (process 28044) exited normally] +[Inferior 1 (process 23144) exited normally] diff --git a/test/test-files/irgenerator/debug-info/success-dbg-info-complex/ir-code.ll b/test/test-files/irgenerator/debug-info/success-dbg-info-complex/ir-code.ll index 937703a2b..ea6efc63e 100644 --- a/test/test-files/irgenerator/debug-info/success-dbg-info-complex/ir-code.ll +++ b/test/test-files/irgenerator/debug-info/success-dbg-info-complex/ir-code.ll @@ -191,7 +191,7 @@ assert.then.L30: ; preds = %assert.exit.L25 unreachable, !dbg !79 assert.exit.L30: ; preds = %assert.exit.L25 - call void @_Z13op.minusequalR14VectorIteratorIiEi(ptr %it, i32 3), !dbg !80 + call void @_Z13op.minusequalIiiEvR14VectorIteratorIiEi(ptr %it, i32 3), !dbg !80 %49 = call ptr @_ZN14VectorIteratorIiE3getEv(ptr noundef nonnull align 8 dereferenceable(24) %it), !dbg !81 %50 = load i32, ptr %49, align 4, !dbg !82 %51 = icmp eq i32 %50, 123, !dbg !82 @@ -213,7 +213,7 @@ assert.then.L35: ; preds = %assert.exit.L34 assert.exit.L35: ; preds = %assert.exit.L34 %55 = load %struct.VectorIterator, ptr %it, align 8, !dbg !84 - call void @_Z16op.plusplus.postR14VectorIteratorIiE(ptr %it), !dbg !84 + call void @_Z16op.plusplus.postIiEvR14VectorIteratorIiE(ptr %it), !dbg !84 %56 = call ptr @_ZN14VectorIteratorIiE3getEv(ptr noundef nonnull align 8 dereferenceable(24) %it), !dbg !85 %57 = load i32, ptr %56, align 4, !dbg !86 %58 = icmp eq i32 %57, 4321, !dbg !86 @@ -226,7 +226,7 @@ assert.then.L37: ; preds = %assert.exit.L35 assert.exit.L37: ; preds = %assert.exit.L35 %60 = load %struct.VectorIterator, ptr %it, align 8, !dbg !87 - call void @_Z18op.minusminus.postR14VectorIteratorIiE(ptr %it), !dbg !87 + call void @_Z18op.minusminus.postIiEvR14VectorIteratorIiE(ptr %it), !dbg !87 %61 = call ptr @_ZN14VectorIteratorIiE3getEv(ptr noundef nonnull align 8 dereferenceable(24) %it), !dbg !88 %62 = load i32, ptr %61, align 4, !dbg !89 %63 = icmp eq i32 %62, 123, !dbg !89 @@ -238,7 +238,7 @@ assert.then.L39: ; preds = %assert.exit.L37 unreachable, !dbg !89 assert.exit.L39: ; preds = %assert.exit.L37 - call void @_Z12op.plusequalR14VectorIteratorIiEi(ptr %it, i32 4), !dbg !90 + call void @_Z12op.plusequalIiiEvR14VectorIteratorIiEi(ptr %it, i32 4), !dbg !90 %65 = call ptr @_ZN14VectorIteratorIiE3getEv(ptr noundef nonnull align 8 dereferenceable(24) %it), !dbg !91 %66 = load i32, ptr %65, align 4, !dbg !92 %67 = icmp eq i32 %66, -99, !dbg !92 @@ -474,13 +474,13 @@ declare ptr @_ZN4PairImRiE8getFirstEv(ptr) declare ptr @_ZN4PairImRiE9getSecondEv(ptr) -declare void @_Z13op.minusequalR14VectorIteratorIiEi(ptr, i32) +declare void @_Z13op.minusequalIiiEvR14VectorIteratorIiEi(ptr, i32) -declare void @_Z16op.plusplus.postR14VectorIteratorIiE(ptr) +declare void @_Z16op.plusplus.postIiEvR14VectorIteratorIiE(ptr) -declare void @_Z18op.minusminus.postR14VectorIteratorIiE(ptr) +declare void @_Z18op.minusminus.postIiEvR14VectorIteratorIiE(ptr) -declare void @_Z12op.plusequalR14VectorIteratorIiEi(ptr, i32) +declare void @_Z12op.plusequalIiiEvR14VectorIteratorIiEi(ptr, i32) declare ptr @_ZN6VectorIiE3getEj(ptr, i32) @@ -497,7 +497,7 @@ attributes #3 = { cold noreturn nounwind } !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = distinct !DIGlobalVariable(name: "printf.str.0", linkageName: "printf.str.0", scope: !2, file: !5, line: 68, type: !6, isLocal: true, isDefinition: true) -!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_20, file: !3, producer: "spice version dev (https://github.com/spicelang/spice)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "spice version dev (https://github.com/spicelang/spice)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) !3 = !DIFile(filename: "C:\\Users\\Marc\\Documents\\JustForFunGitHubClonesFast\\spice\\cmake-build-debug\\test\\test-files\\irgenerator\\debug-info\\success-dbg-info-complex\\source.spice", directory: ".\\test-files\\irgenerator\\debug-info\\success-dbg-info-complex") !4 = !{!0} !5 = !DIFile(filename: "source.spice", directory: ".\\test-files\\irgenerator\\debug-info\\success-dbg-info-complex") @@ -510,7 +510,7 @@ attributes #3 = { cold noreturn nounwind } !12 = !{i32 7, !"uwtable", i32 2} !13 = !{i32 7, !"frame-pointer", i32 2} !14 = !{!"spice version dev (https://github.com/spicelang/spice)"} -!15 = distinct !DISubprogram(name: "main", linkageName: "_Z4mainiPPc", scope: !5, file: !5, line: 4, type: !16, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !22) +!15 = distinct !DISubprogram(name: "main", linkageName: "_Z4mainiPPKc", scope: !5, file: !5, line: 4, type: !16, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !22) !16 = !DISubroutineType(types: !17) !17 = !{!18, !18, !19} !18 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) diff --git a/test/test-files/irgenerator/debug-info/success-dbg-info-simple/ir-code.ll b/test/test-files/irgenerator/debug-info/success-dbg-info-simple/ir-code.ll index 6827a0222..96f4cd10f 100644 --- a/test/test-files/irgenerator/debug-info/success-dbg-info-simple/ir-code.ll +++ b/test/test-files/irgenerator/debug-info/success-dbg-info-simple/ir-code.ll @@ -12,7 +12,7 @@ target triple = "x86_64-w64-windows-gnu" @printf.str.2 = private unnamed_addr constant [9 x i8] c"Int: %d\0A\00", align 1, !dbg !12 ; Function Attrs: norecurse -define private void @_ZN10TestStruct4dtorEv(ptr noundef nonnull align 8 dereferenceable(40) %0) #0 !dbg !24 { +define void @_ZN10TestStruct4dtorEv(ptr noundef nonnull align 8 dereferenceable(40) %0) #0 !dbg !24 { %this = alloca ptr, align 8 call void @llvm.dbg.declare(metadata ptr %this, metadata !45, metadata !DIExpression()), !dbg !47 store ptr %0, ptr %this, align 8, !dbg !47 @@ -35,7 +35,7 @@ define private %struct.TestStruct @_Z3fctRi(ptr %0) !dbg !48 { call void @llvm.dbg.declare(metadata ptr %result, metadata !52, metadata !DIExpression()), !dbg !53 call void @llvm.dbg.declare(metadata ptr %ref, metadata !54, metadata !DIExpression()), !dbg !55 store ptr %0, ptr %ref, align 8, !dbg !55 - call void @_ZN6String4ctorEPc(ptr noundef nonnull align 8 dereferenceable(24) %2, ptr @anon.string.0), !dbg !56 + call void @_ZN6String4ctorEPKc(ptr noundef nonnull align 8 dereferenceable(24) %2, ptr @anon.string.0), !dbg !56 store i64 6, ptr %ts, align 8, !dbg !57 %3 = load %struct.String, ptr %2, align 8, !dbg !57 %4 = getelementptr inbounds %struct.TestStruct, ptr %ts, i32 0, i32 1, !dbg !57 @@ -49,7 +49,7 @@ define private %struct.TestStruct @_Z3fctRi(ptr %0) !dbg !48 { ret %struct.TestStruct %8, !dbg !60 } -declare void @_ZN6String4ctorEPc(ptr, ptr) +declare void @_ZN6String4ctorEPKc(ptr, ptr) ; Function Attrs: noinline nounwind optnone uwtable define dso_local i32 @main() #2 !dbg !61 { @@ -93,7 +93,7 @@ attributes #3 = { nofree nounwind } !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = distinct !DIGlobalVariable(name: "anon.string.0", linkageName: "anon.string.0", scope: !2, file: !7, line: 8, type: !15, isLocal: true, isDefinition: true) -!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_20, file: !3, producer: "spice version dev (https://github.com/spicelang/spice)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "spice version dev (https://github.com/spicelang/spice)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) !3 = !DIFile(filename: "C:\\Users\\Marc\\Documents\\JustForFunGitHubClonesFast\\spice\\cmake-build-debug\\test\\test-files\\irgenerator\\debug-info\\success-dbg-info-simple\\source.spice", directory: ".\\test-files\\irgenerator\\debug-info\\success-dbg-info-simple") !4 = !{!0, !5, !9, !12} !5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression()) @@ -115,7 +115,7 @@ attributes #3 = { nofree nounwind } !21 = !{i32 7, !"uwtable", i32 2} !22 = !{i32 7, !"frame-pointer", i32 2} !23 = !{!"spice version dev (https://github.com/spicelang/spice)"} -!24 = distinct !DISubprogram(name: "dtor", linkageName: "_ZN10TestStruct4dtorEv", scope: !7, file: !7, line: 1, type: !25, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !44) +!24 = distinct !DISubprogram(name: "dtor", linkageName: "_ZN10TestStruct4dtorEv", scope: !7, file: !7, line: 1, type: !25, scopeLine: 1, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !44) !25 = !DISubroutineType(types: !26) !26 = !{!27, !28} !27 = !DIBasicType(name: "void", encoding: DW_ATE_unsigned) diff --git a/test/test-files/irgenerator/foreach-loops/success-foreach-loop-break/ir-code-O2.ll b/test/test-files/irgenerator/foreach-loops/success-foreach-loop-break/ir-code-O2.ll index db7b61e52..310e6bb58 100644 --- a/test/test-files/irgenerator/foreach-loops/success-foreach-loop-break/ir-code-O2.ll +++ b/test/test-files/irgenerator/foreach-loops/success-foreach-loop-break/ir-code-O2.ll @@ -15,7 +15,7 @@ target triple = "x86_64-w64-windows-gnu" define dso_local i32 @main() local_unnamed_addr #0 { %shortIterator = alloca %struct.NumberIterator, align 8 %1 = alloca %struct.NumberIterator.1, align 8 - %2 = tail call %struct.NumberIterator @_Z5rangess(i16 3, i16 8) #2 + %2 = tail call %struct.NumberIterator @_Z5rangeIsE14NumberIteratorIsEss(i16 3, i16 8) #2 %.fca.0.0.extract2 = extractvalue %struct.NumberIterator %2, 0, 0 store ptr %.fca.0.0.extract2, ptr %shortIterator, align 8 %.fca.1.extract4 = extractvalue %struct.NumberIterator %2, 1 @@ -46,7 +46,7 @@ foreach.body.L5: ; preds = %foreach.body.L5.lr. br i1 %.not, label %foreach.tail.L5, label %if.then.L7 if.then.L7: ; preds = %foreach.body.L5 - %9 = call %struct.NumberIterator.1 @_Z5rangell(i64 1, i64 2) #2 + %9 = call %struct.NumberIterator.1 @_Z5rangeIlE14NumberIteratorIlEll(i64 1, i64 2) #2 %.fca.0.0.extract = extractvalue %struct.NumberIterator.1 %9, 0, 0 store ptr %.fca.0.0.extract, ptr %1, align 8 %.fca.1.extract = extractvalue %struct.NumberIterator.1 %9, 1 @@ -74,7 +74,7 @@ foreach.exit.L5: ; preds = %foreach.tail.L5, %0 ret i32 0 } -declare %struct.NumberIterator @_Z5rangess(i16, i16) local_unnamed_addr +declare %struct.NumberIterator @_Z5rangeIsE14NumberIteratorIsEss(i16, i16) local_unnamed_addr declare i1 @_ZN14NumberIteratorIsE7isValidEv(ptr) local_unnamed_addr @@ -83,7 +83,7 @@ declare ptr @_ZN14NumberIteratorIsE3getEv(ptr) local_unnamed_addr ; Function Attrs: nofree nounwind declare noundef i32 @printf(ptr nocapture noundef readonly, ...) local_unnamed_addr #1 -declare %struct.NumberIterator.1 @_Z5rangell(i64, i64) local_unnamed_addr +declare %struct.NumberIterator.1 @_Z5rangeIlE14NumberIteratorIlEll(i64, i64) local_unnamed_addr declare i1 @_ZN14NumberIteratorIlE7isValidEv(ptr) local_unnamed_addr diff --git a/test/test-files/irgenerator/foreach-loops/success-foreach-loop-break/ir-code.ll b/test/test-files/irgenerator/foreach-loops/success-foreach-loop-break/ir-code.ll index 389a90e27..26da35219 100644 --- a/test/test-files/irgenerator/foreach-loops/success-foreach-loop-break/ir-code.ll +++ b/test/test-files/irgenerator/foreach-loops/success-foreach-loop-break/ir-code.ll @@ -20,7 +20,7 @@ define dso_local i32 @main() #0 { %l = alloca ptr, align 8 %2 = alloca ptr, align 8 store i32 0, ptr %result, align 4 - %3 = call %struct.NumberIterator @_Z5rangess(i16 3, i16 8) + %3 = call %struct.NumberIterator @_Z5rangeIsE14NumberIteratorIsEss(i16 3, i16 8) store %struct.NumberIterator %3, ptr %shortIterator, align 8 br label %foreach.head.L5 @@ -42,7 +42,7 @@ foreach.body.L5: ; preds = %foreach.head.L5 br i1 %13, label %if.then.L7, label %if.exit.L7 if.then.L7: ; preds = %foreach.body.L5 - %14 = call %struct.NumberIterator.1 @_Z5rangell(i64 1, i64 2) + %14 = call %struct.NumberIterator.1 @_Z5rangeIlE14NumberIteratorIlEll(i64 1, i64 2) store %struct.NumberIterator.1 %14, ptr %1, align 8 br label %foreach.head.L8 @@ -78,7 +78,7 @@ foreach.exit.L5: ; preds = %foreach.body.L8, %f ret i32 %21 } -declare %struct.NumberIterator @_Z5rangess(i16, i16) +declare %struct.NumberIterator @_Z5rangeIsE14NumberIteratorIsEss(i16, i16) declare i1 @_ZN14NumberIteratorIsE7isValidEv(ptr) @@ -87,7 +87,7 @@ declare ptr @_ZN14NumberIteratorIsE3getEv(ptr) ; Function Attrs: nofree nounwind declare noundef i32 @printf(ptr nocapture noundef readonly, ...) #1 -declare %struct.NumberIterator.1 @_Z5rangell(i64, i64) +declare %struct.NumberIterator.1 @_Z5rangeIlE14NumberIteratorIlEll(i64, i64) declare i1 @_ZN14NumberIteratorIlE7isValidEv(ptr) diff --git a/test/test-files/irgenerator/foreach-loops/success-foreach-loop-continue/ir-code-O2.ll b/test/test-files/irgenerator/foreach-loops/success-foreach-loop-continue/ir-code-O2.ll index b5dccc030..a642f596b 100644 --- a/test/test-files/irgenerator/foreach-loops/success-foreach-loop-continue/ir-code-O2.ll +++ b/test/test-files/irgenerator/foreach-loops/success-foreach-loop-continue/ir-code-O2.ll @@ -15,7 +15,7 @@ target triple = "x86_64-w64-windows-gnu" define dso_local i32 @main() local_unnamed_addr #0 { %shortIterator = alloca %struct.NumberIterator, align 8 %1 = alloca %struct.NumberIterator.1, align 8 - %2 = tail call %struct.NumberIterator @_Z5rangess(i16 3, i16 8) #2 + %2 = tail call %struct.NumberIterator @_Z5rangeIsE14NumberIteratorIsEss(i16 3, i16 8) #2 %.fca.0.0.extract2 = extractvalue %struct.NumberIterator %2, 0, 0 store ptr %.fca.0.0.extract2, ptr %shortIterator, align 8 %.fca.1.extract4 = extractvalue %struct.NumberIterator %2, 1 @@ -46,7 +46,7 @@ foreach.body.L5: ; preds = %foreach.body.L5.lr. br i1 %.not, label %foreach.tail.L5, label %if.then.L7 if.then.L7: ; preds = %foreach.body.L5 - %9 = call %struct.NumberIterator.1 @_Z5rangell(i64 1, i64 2) #2 + %9 = call %struct.NumberIterator.1 @_Z5rangeIlE14NumberIteratorIlEll(i64 1, i64 2) #2 %.fca.0.0.extract = extractvalue %struct.NumberIterator.1 %9, 0, 0 store ptr %.fca.0.0.extract, ptr %1, align 8 %.fca.1.extract = extractvalue %struct.NumberIterator.1 %9, 1 @@ -74,7 +74,7 @@ foreach.exit.L5: ; preds = %foreach.tail.L5, %0 ret i32 0 } -declare %struct.NumberIterator @_Z5rangess(i16, i16) local_unnamed_addr +declare %struct.NumberIterator @_Z5rangeIsE14NumberIteratorIsEss(i16, i16) local_unnamed_addr declare i1 @_ZN14NumberIteratorIsE7isValidEv(ptr) local_unnamed_addr @@ -83,7 +83,7 @@ declare ptr @_ZN14NumberIteratorIsE3getEv(ptr) local_unnamed_addr ; Function Attrs: nofree nounwind declare noundef i32 @printf(ptr nocapture noundef readonly, ...) local_unnamed_addr #1 -declare %struct.NumberIterator.1 @_Z5rangell(i64, i64) local_unnamed_addr +declare %struct.NumberIterator.1 @_Z5rangeIlE14NumberIteratorIlEll(i64, i64) local_unnamed_addr declare i1 @_ZN14NumberIteratorIlE7isValidEv(ptr) local_unnamed_addr diff --git a/test/test-files/irgenerator/foreach-loops/success-foreach-loop-continue/ir-code.ll b/test/test-files/irgenerator/foreach-loops/success-foreach-loop-continue/ir-code.ll index 3d5bffdff..637ae9c78 100644 --- a/test/test-files/irgenerator/foreach-loops/success-foreach-loop-continue/ir-code.ll +++ b/test/test-files/irgenerator/foreach-loops/success-foreach-loop-continue/ir-code.ll @@ -20,7 +20,7 @@ define dso_local i32 @main() #0 { %l = alloca ptr, align 8 %2 = alloca ptr, align 8 store i32 0, ptr %result, align 4 - %3 = call %struct.NumberIterator @_Z5rangess(i16 3, i16 8) + %3 = call %struct.NumberIterator @_Z5rangeIsE14NumberIteratorIsEss(i16 3, i16 8) store %struct.NumberIterator %3, ptr %shortIterator, align 8 br label %foreach.head.L5 @@ -42,7 +42,7 @@ foreach.body.L5: ; preds = %foreach.head.L5 br i1 %13, label %if.then.L7, label %if.exit.L7 if.then.L7: ; preds = %foreach.body.L5 - %14 = call %struct.NumberIterator.1 @_Z5rangell(i64 1, i64 2) + %14 = call %struct.NumberIterator.1 @_Z5rangeIlE14NumberIteratorIlEll(i64 1, i64 2) store %struct.NumberIterator.1 %14, ptr %1, align 8 br label %foreach.head.L8 @@ -78,7 +78,7 @@ foreach.exit.L5: ; preds = %foreach.head.L5 ret i32 %21 } -declare %struct.NumberIterator @_Z5rangess(i16, i16) +declare %struct.NumberIterator @_Z5rangeIsE14NumberIteratorIsEss(i16, i16) declare i1 @_ZN14NumberIteratorIsE7isValidEv(ptr) @@ -87,7 +87,7 @@ declare ptr @_ZN14NumberIteratorIsE3getEv(ptr) ; Function Attrs: nofree nounwind declare noundef i32 @printf(ptr nocapture noundef readonly, ...) #1 -declare %struct.NumberIterator.1 @_Z5rangell(i64, i64) +declare %struct.NumberIterator.1 @_Z5rangeIlE14NumberIteratorIlEll(i64, i64) declare i1 @_ZN14NumberIteratorIlE7isValidEv(ptr) diff --git a/test/test-files/irgenerator/foreach-loops/success-foreach-loop-indexed/ir-code.ll b/test/test-files/irgenerator/foreach-loops/success-foreach-loop-indexed/ir-code.ll index 1a0fdef51..66ff092dd 100644 --- a/test/test-files/irgenerator/foreach-loops/success-foreach-loop-indexed/ir-code.ll +++ b/test/test-files/irgenerator/foreach-loops/success-foreach-loop-indexed/ir-code.ll @@ -21,7 +21,7 @@ define dso_local i32 @main() #0 { store i32 0, ptr %result, align 4 store [7 x i32] [i32 1, i32 5, i32 4, i32 0, i32 12, i32 12345, i32 9], ptr %intArray, align 4 %2 = getelementptr inbounds [7 x i32], ptr %intArray, i32 0, i32 0 - %3 = call %struct.ArrayIterator @_Z7iteratePim(ptr %2, i64 7) + %3 = call %struct.ArrayIterator @_Z7iterateIiE13ArrayIteratorIiEPim(ptr %2, i64 7) store %struct.ArrayIterator %3, ptr %1, align 8 store i64 0, ptr %index, align 8 br label %foreach.head.L5 @@ -53,7 +53,7 @@ foreach.exit.L5: ; preds = %foreach.head.L5 ret i32 %11 } -declare %struct.ArrayIterator @_Z7iteratePim(ptr, i64) +declare %struct.ArrayIterator @_Z7iterateIiE13ArrayIteratorIiEPim(ptr, i64) declare i1 @_ZN13ArrayIteratorIiE7isValidEv(ptr) diff --git a/test/test-files/irgenerator/foreach-loops/success-foreach-loop-normal/ir-code.ll b/test/test-files/irgenerator/foreach-loops/success-foreach-loop-normal/ir-code.ll index df39133b9..dee27658b 100644 --- a/test/test-files/irgenerator/foreach-loops/success-foreach-loop-normal/ir-code.ll +++ b/test/test-files/irgenerator/foreach-loops/success-foreach-loop-normal/ir-code.ll @@ -18,7 +18,7 @@ define dso_local i32 @main() #0 { store i32 0, ptr %result, align 4 store [7 x i32] [i32 1, i32 5, i32 4, i32 0, i32 12, i32 12345, i32 9], ptr %intArray, align 4 %2 = getelementptr inbounds [7 x i32], ptr %intArray, i32 0, i32 0 - %3 = call %struct.ArrayIterator @_Z7iteratePim(ptr %2, i64 7) + %3 = call %struct.ArrayIterator @_Z7iterateIiE13ArrayIteratorIiEPim(ptr %2, i64 7) store %struct.ArrayIterator %3, ptr %1, align 8 br label %foreach.head.L5 @@ -43,7 +43,7 @@ foreach.exit.L5: ; preds = %foreach.head.L5 ret i32 %9 } -declare %struct.ArrayIterator @_Z7iteratePim(ptr, i64) +declare %struct.ArrayIterator @_Z7iterateIiE13ArrayIteratorIiEPim(ptr, i64) declare i1 @_ZN13ArrayIteratorIiE7isValidEv(ptr) diff --git a/test/test-files/irgenerator/function-pointers/success-indirect/ir-code.ll b/test/test-files/irgenerator/function-pointers/success-indirect/ir-code.ll index 073143d08..a83fe5816 100644 --- a/test/test-files/irgenerator/function-pointers/success-indirect/ir-code.ll +++ b/test/test-files/irgenerator/function-pointers/success-indirect/ir-code.ll @@ -6,14 +6,14 @@ target triple = "x86_64-w64-windows-gnu" @anon.string.0 = private unnamed_addr constant [7 x i8] c"string\00", align 1 @printf.str.0 = private unnamed_addr constant [3 x i8] c"%d\00", align 1 -define private i32 @_Z4testPc(ptr %0) { +define private i32 @_Z4testPKc(ptr %0) { %result = alloca i32, align 4 %_input = alloca ptr, align 8 store ptr %0, ptr %_input, align 8 ret i32 12 } -define private i32 @_Z6invokePFiPcE({ ptr, ptr } %0) { +define private i32 @_Z6invokePFiPKcE({ ptr, ptr } %0) { %result = alloca i32, align 4 %fctPtr = alloca { ptr, ptr }, align 8 store { ptr, ptr } %0, ptr %fctPtr, align 8 @@ -29,13 +29,13 @@ define dso_local i32 @main() #0 { %testFct = alloca { ptr, ptr }, align 8 %i = alloca i32, align 4 store i32 0, ptr %result, align 4 - store ptr @_Z4testPc, ptr %fat.ptr, align 8 + store ptr @_Z4testPKc, ptr %fat.ptr, align 8 %1 = getelementptr inbounds { ptr, ptr }, ptr %fat.ptr, i32 0, i32 1 store ptr poison, ptr %1, align 8 %2 = load { ptr, ptr }, ptr %fat.ptr, align 8 store { ptr, ptr } %2, ptr %testFct, align 8 %3 = load { ptr, ptr }, ptr %testFct, align 8 - %4 = call i32 @_Z6invokePFiPcE({ ptr, ptr } %3) + %4 = call i32 @_Z6invokePFiPKcE({ ptr, ptr } %3) store i32 %4, ptr %i, align 4 %5 = load i32, ptr %i, align 4 %6 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.0, i32 %5) diff --git a/test/test-files/irgenerator/function-pointers/success-pass-by-non-value/ir-code.ll b/test/test-files/irgenerator/function-pointers/success-pass-by-non-value/ir-code.ll index 3003f12a0..0e1ef58b0 100644 --- a/test/test-files/irgenerator/function-pointers/success-pass-by-non-value/ir-code.ll +++ b/test/test-files/irgenerator/function-pointers/success-pass-by-non-value/ir-code.ll @@ -8,14 +8,14 @@ target triple = "x86_64-w64-windows-gnu" @printf.str.0 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 @printf.str.1 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 -define private i32 @_Z4testPc(ptr %0) { +define private i32 @_Z4testPKc(ptr %0) { %result = alloca i32, align 4 %_input = alloca ptr, align 8 store ptr %0, ptr %_input, align 8 ret i32 12 } -define private i32 @_Z6invokePPPFiPcE(ptr %0) { +define private i32 @_Z6invokePPPFiPKcE(ptr %0) { %result = alloca i32, align 4 %fctPtr = alloca ptr, align 8 store ptr %0, ptr %fctPtr, align 8 @@ -26,7 +26,7 @@ define private i32 @_Z6invokePPPFiPcE(ptr %0) { ret i32 %4 } -define private i32 @_Z6invokeRPFiPcE(ptr %0) { +define private i32 @_Z6invokeRPFiPKcE(ptr %0) { %result = alloca i32, align 4 %fctPtr = alloca ptr, align 8 store ptr %0, ptr %fctPtr, align 8 @@ -43,15 +43,15 @@ define dso_local i32 @main() #0 { %testFct = alloca { ptr, ptr }, align 8 %testFctPtr = alloca ptr, align 8 store i32 0, ptr %result, align 4 - store ptr @_Z4testPc, ptr %fat.ptr, align 8 + store ptr @_Z4testPKc, ptr %fat.ptr, align 8 %1 = getelementptr inbounds { ptr, ptr }, ptr %fat.ptr, i32 0, i32 1 store ptr poison, ptr %1, align 8 %2 = load { ptr, ptr }, ptr %fat.ptr, align 8 store { ptr, ptr } %2, ptr %testFct, align 8 store ptr %testFct, ptr %testFctPtr, align 8 - %3 = call i32 @_Z6invokePPPFiPcE(ptr %testFctPtr) + %3 = call i32 @_Z6invokePPPFiPKcE(ptr %testFctPtr) %4 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.0, i32 %3) - %5 = call i32 @_Z6invokeRPFiPcE(ptr %testFct) + %5 = call i32 @_Z6invokeRPFiPKcE(ptr %testFct) %6 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.1, i32 %5) %7 = load i32, ptr %result, align 4 ret i32 %7 diff --git a/test/test-files/irgenerator/functions/success-overloading/ir-code.ll b/test/test-files/irgenerator/functions/success-overloading/ir-code.ll index 09504097e..65bc85a91 100644 --- a/test/test-files/irgenerator/functions/success-overloading/ir-code.ll +++ b/test/test-files/irgenerator/functions/success-overloading/ir-code.ll @@ -17,7 +17,7 @@ define private i32 @_Z8testFuncv() { ; Function Attrs: nofree nounwind declare noundef i32 @printf(ptr nocapture noundef readonly, ...) #0 -define private i32 @_Z8testFuncPc(ptr %0) { +define private i32 @_Z8testFuncPKc(ptr %0) { %result = alloca i32, align 4 %param = alloca ptr, align 8 store ptr %0, ptr %param, align 8 @@ -35,7 +35,7 @@ define dso_local i32 @main() #1 { store i32 %1, ptr %res, align 4 %2 = load i32, ptr %res, align 4 %3 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.2, i32 %2) - %4 = call i32 @_Z8testFuncPc(ptr @anon.string.0) + %4 = call i32 @_Z8testFuncPKc(ptr @anon.string.0) store i32 %4, ptr %res, align 4 %5 = load i32, ptr %result, align 4 ret i32 %5 diff --git a/test/test-files/irgenerator/generics/success-external-generic-functions/ir-code.ll b/test/test-files/irgenerator/generics/success-external-generic-functions/ir-code.ll index a8207ec9e..8af3fac49 100644 --- a/test/test-files/irgenerator/generics/success-external-generic-functions/ir-code.ll +++ b/test/test-files/irgenerator/generics/success-external-generic-functions/ir-code.ll @@ -15,13 +15,13 @@ define dso_local i32 @main() #0 { %i = alloca i32, align 4 %iPtr = alloca ptr, align 8 store i32 0, ptr %result, align 4 - call void @_Z11printFormatd(double 1.123000e+00) - call void @_Z11printFormati(i32 543) - call void @_Z11printFormatA2Pc([2 x ptr] [ptr @anon.string.0, ptr @anon.string.1]) + call void @_Z11printFormatIdEvd(double 1.123000e+00) + call void @_Z11printFormatIiEvi(i32 543) + call void @_Z11printFormatIPPKcEvPPKc([2 x ptr] [ptr @anon.string.0, ptr @anon.string.1]) store i32 1234, ptr %test, align 4 - call void @_Z11printFormatPi(ptr %test) + call void @_Z11printFormatIPiEvPi(ptr %test) store i32 12, ptr %i, align 4 - %1 = call ptr @_Z7getAIncPi(ptr %i) + %1 = call ptr @_Z7getAIncIiEPiPi(ptr %i) store ptr %1, ptr %iPtr, align 8 %2 = load ptr, ptr %iPtr, align 8 %3 = load i32, ptr %2, align 4 @@ -38,15 +38,15 @@ assert.exit.L12: ; preds = %0 ret i32 %6 } -declare void @_Z11printFormatd(double) +declare void @_Z11printFormatIdEvd(double) -declare void @_Z11printFormati(i32) +declare void @_Z11printFormatIiEvi(i32) -declare void @_Z11printFormatA2Pc([2 x ptr]) +declare void @_Z11printFormatIPPKcEvPPKc([2 x ptr]) -declare void @_Z11printFormatPi(ptr) +declare void @_Z11printFormatIPiEvPi(ptr) -declare ptr @_Z7getAIncPi(ptr) +declare ptr @_Z7getAIncIiEPiPi(ptr) ; Function Attrs: nofree nounwind declare noundef i32 @printf(ptr nocapture noundef readonly, ...) #1 diff --git a/test/test-files/irgenerator/generics/success-generic-functions/ir-code.ll b/test/test-files/irgenerator/generics/success-generic-functions/ir-code.ll index cbeb65b40..1b86f7baf 100644 --- a/test/test-files/irgenerator/generics/success-generic-functions/ir-code.ll +++ b/test/test-files/irgenerator/generics/success-generic-functions/ir-code.ll @@ -7,7 +7,7 @@ target triple = "x86_64-w64-windows-gnu" @printf.str.1 = private unnamed_addr constant [4 x i8] c"%f\0A\00", align 1 @printf.str.2 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 -define private double @_Z15genericFunctionid(i32 %0, double %1) { +define private double @_Z15genericFunctionIidEdid(i32 %0, double %1) { %result = alloca double, align 8 %arg1 = alloca i32, align 4 %arg2 = alloca double, align 8 @@ -25,7 +25,7 @@ define private double @_Z15genericFunctionid(i32 %0, double %1) { ret double %9 } -define private double @_Z15genericFunctionld(i64 %0, double %1) { +define private double @_Z15genericFunctionIldEdld(i64 %0, double %1) { %result = alloca double, align 8 %arg1 = alloca i64, align 8 %arg2 = alloca double, align 8 @@ -43,7 +43,7 @@ define private double @_Z15genericFunctionld(i64 %0, double %1) { ret double %9 } -define private i64 @_Z15genericFunctionlsl(i64 %0, i16 %1, i64 %2) { +define private i64 @_Z15genericFunctionIlsEllsl(i64 %0, i16 %1, i64 %2) { %result = alloca i64, align 8 %arg1 = alloca i64, align 8 %arg2 = alloca i16, align 2 @@ -64,11 +64,11 @@ define private i64 @_Z15genericFunctionlsl(i64 %0, i16 %1, i64 %2) { define dso_local i32 @main() #0 { %result = alloca i32, align 4 store i32 0, ptr %result, align 4 - %1 = call double @_Z15genericFunctionid(i32 1, double 2.400000e+00) + %1 = call double @_Z15genericFunctionIidEdid(i32 1, double 2.400000e+00) %2 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.0, double %1) - %3 = call double @_Z15genericFunctionld(i64 12, double 2.000000e+00) + %3 = call double @_Z15genericFunctionIldEdld(i64 12, double 2.000000e+00) %4 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.1, double %3) - %5 = call i64 @_Z15genericFunctionlsl(i64 12, i16 1, i64 11) + %5 = call i64 @_Z15genericFunctionIlsEllsl(i64 12, i16 1, i64 11) %6 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.2, i64 %5) %7 = load i32, ptr %result, align 4 ret i32 %7 diff --git a/test/test-files/irgenerator/generics/success-generic-functions2/ir-code.ll b/test/test-files/irgenerator/generics/success-generic-functions2/ir-code.ll index d7ca375c2..fbdebf15c 100644 --- a/test/test-files/irgenerator/generics/success-generic-functions2/ir-code.ll +++ b/test/test-files/irgenerator/generics/success-generic-functions2/ir-code.ll @@ -8,7 +8,7 @@ target triple = "x86_64-w64-windows-gnu" @anon.array.1 = private unnamed_addr constant [4 x i64] [i64 10, i64 12, i64 14, i64 16] @printf.str.1 = private unnamed_addr constant [17 x i8] c"Results: %d, %d\0A\00", align 1 -define private i32 @_Z10sumNumbersPsl(ptr %0, i64 %1) { +define private i32 @_Z10sumNumbersIsEiPsl(ptr %0, i64 %1) { %result = alloca i32, align 4 %numberArray = alloca ptr, align 8 %arrayLength = alloca i64, align 8 @@ -47,7 +47,7 @@ for.exit.L6: ; preds = %for.head.L6 ret i32 %15 } -define private i32 @_Z10sumNumbersPll(ptr %0, i64 %1) { +define private i32 @_Z10sumNumbersIlEiPll(ptr %0, i64 %1) { %result = alloca i32, align 4 %numberArray = alloca ptr, align 8 %arrayLength = alloca i64, align 8 @@ -86,7 +86,7 @@ for.exit.L6: ; preds = %for.head.L6 ret i32 %15 } -define private void @_Z9printDatalA2i(i64 %0, [2 x i32] %1) { +define private void @_Z9printDataIPiEvlPi(i64 %0, [2 x i32] %1) { %arrayLength = alloca i64, align 8 %list = alloca [2 x i32], align 4 %i = alloca i64, align 8 @@ -133,11 +133,11 @@ define dso_local i32 @main() #1 { store i32 0, ptr %result, align 4 store [7 x i16] [i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7], ptr %numberList1, align 2 %2 = getelementptr inbounds [7 x i16], ptr %numberList1, i32 0, i32 0 - %3 = call i32 @_Z10sumNumbersPsl(ptr %2, i64 7) + %3 = call i32 @_Z10sumNumbersIsEiPsl(ptr %2, i64 7) store i32 %3, ptr %result1, align 4 store [4 x i64] [i64 10, i64 12, i64 14, i64 16], ptr %numberList2, align 8 %4 = getelementptr inbounds [4 x i64], ptr %numberList2, i32 0, i32 0 - %5 = call i32 @_Z10sumNumbersPll(ptr %4, i64 4) + %5 = call i32 @_Z10sumNumbersIlEiPll(ptr %4, i64 4) store i32 %5, ptr %result2, align 4 %6 = getelementptr inbounds [2 x i32], ptr %1, i32 0 %7 = load i32, ptr %result1, align 4 @@ -148,7 +148,7 @@ define dso_local i32 @main() #1 { %10 = load [2 x i32], ptr %1, align 4 store [2 x i32] %10, ptr %resultList, align 4 %11 = load [2 x i32], ptr %resultList, align 4 - call void @_Z9printDatalA2i(i64 2, [2 x i32] %11) + call void @_Z9printDataIPiEvlPi(i64 2, [2 x i32] %11) %12 = load i32, ptr %result1, align 4 %13 = load i32, ptr %result2, align 4 %14 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.1, i32 %12, i32 %13) diff --git a/test/test-files/irgenerator/generics/success-type-hints/ir-code.ll b/test/test-files/irgenerator/generics/success-type-hints/ir-code.ll index d624fcb52..e34057c2a 100644 --- a/test/test-files/irgenerator/generics/success-type-hints/ir-code.ll +++ b/test/test-files/irgenerator/generics/success-type-hints/ir-code.ll @@ -5,7 +5,7 @@ target triple = "x86_64-w64-windows-gnu" @printf.str.0 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 -define private i32 @_Z4testv() { +define private i32 @_Z4testIiEiv() { %result = alloca i32, align 4 ret i32 0 } @@ -15,7 +15,7 @@ define dso_local i32 @main() #0 { %result = alloca i32, align 4 %t = alloca i32, align 4 store i32 0, ptr %result, align 4 - %1 = call i32 @_Z4testv() + %1 = call i32 @_Z4testIiEiv() store i32 %1, ptr %t, align 4 %2 = load i32, ptr %t, align 4 %3 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.0, i32 %2) diff --git a/test/test-files/irgenerator/lambdas/success-expression-lambda/ir-code.ll b/test/test-files/irgenerator/lambdas/success-expression-lambda/ir-code.ll index 2b23b0e62..958d45537 100644 --- a/test/test-files/irgenerator/lambdas/success-expression-lambda/ir-code.ll +++ b/test/test-files/irgenerator/lambdas/success-expression-lambda/ir-code.ll @@ -26,7 +26,7 @@ define private void @_Z4swapRiRi(ptr %0, ptr %1) { ret void } -define private void @_Z4sortRA10iPFbiiE(ptr %0, { ptr, ptr } %1) { +define private void @_Z4sortRPiPFbiiE(ptr %0, { ptr, ptr } %1) { %array = alloca ptr, align 8 %sortFct = alloca { ptr, ptr }, align 8 %i = alloca i32, align 4 @@ -114,8 +114,8 @@ define dso_local i32 @main() #0 { %1 = getelementptr inbounds { ptr, ptr }, ptr %fat.ptr, i32 0, i32 1 store ptr poison, ptr %1, align 8 %2 = load { ptr, ptr }, ptr %fat.ptr, align 8 - call void @_Z4sortRA10iPFbiiE(ptr %array, { ptr, ptr } %2) - call void @_Z10printArrayRA10i(ptr %array) + call void @_Z4sortRPiPFbiiE(ptr %array, { ptr, ptr } %2) + call void @_Z10printArrayRPi(ptr %array) %3 = load i32, ptr %result, align 4 ret i32 %3 } @@ -131,7 +131,7 @@ define private i1 @_Z15lambda.L19C17.0ii(i32 %0, i32 %1) { ret i1 %5 } -define private void @_Z10printArrayRA10i(ptr %0) { +define private void @_Z10printArrayRPi(ptr %0) { %array = alloca ptr, align 8 %i = alloca i32, align 4 store ptr %0, ptr %array, align 8 diff --git a/test/test-files/irgenerator/lambdas/success-function-lambda/ir-code.ll b/test/test-files/irgenerator/lambdas/success-function-lambda/ir-code.ll index db3e94bc6..9d98b59b5 100644 --- a/test/test-files/irgenerator/lambdas/success-function-lambda/ir-code.ll +++ b/test/test-files/irgenerator/lambdas/success-function-lambda/ir-code.ll @@ -40,7 +40,7 @@ define dso_local i32 @main() #0 { store ptr poison, ptr %7, align 8 %8 = load { ptr, ptr }, ptr %fat.ptr1, align 8 store { ptr, ptr } %8, ptr %callbackWithArgs1, align 8 - call void @_ZN6String4ctorEPc(ptr noundef nonnull align 8 dereferenceable(24) %1, ptr @anon.string.2) + call void @_ZN6String4ctorEPKc(ptr noundef nonnull align 8 dereferenceable(24) %1, ptr @anon.string.2) %fct2 = load ptr, ptr %callbackWithArgs1, align 8 %9 = call i1 %fct2(ptr %1, double 3.140000e+00) %10 = zext i1 %9 to i32 @@ -50,7 +50,7 @@ define dso_local i32 @main() #0 { store ptr poison, ptr %12, align 8 %13 = load { ptr, ptr }, ptr %fat.ptr3, align 8 store { ptr, ptr } %13, ptr %callbackWithArgs2, align 8 - call void @_ZN6String4ctorEPc(ptr noundef nonnull align 8 dereferenceable(24) %2, ptr @anon.string.3) + call void @_ZN6String4ctorEPKc(ptr noundef nonnull align 8 dereferenceable(24) %2, ptr @anon.string.3) %14 = load %struct.String, ptr %2, align 8 %fct4 = load ptr, ptr %callbackWithArgs2, align 8 %15 = call i16 %fct4(%struct.String %14, i16 321) @@ -85,7 +85,7 @@ define private i1 @_Z14lambda.L7C50.0R6Stringd(ptr %0, double %1) { %6 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.1, ptr %4, double %5) %7 = load ptr, ptr %str, align 8 %8 = call ptr @_ZN6String6getRawEv(ptr noundef nonnull align 8 dereferenceable(8) %7) - %9 = call i1 @_Z10isRawEqualPcPc(ptr %8, ptr @anon.string.1) + %9 = call i1 @_Z10isRawEqualPKcPKc(ptr %8, ptr @anon.string.1) br i1 %9, label %land.1.L9C16, label %land.exit.L9C16 land.1.L9C16: ; preds = %2 @@ -100,9 +100,9 @@ land.exit.L9C16: ; preds = %land.1.L9C16, %2 declare ptr @_ZN6String6getRawEv(ptr) -declare i1 @_Z10isRawEqualPcPc(ptr, ptr) +declare i1 @_Z10isRawEqualPKcPKc(ptr, ptr) -declare void @_ZN6String4ctorEPc(ptr, ptr) +declare void @_ZN6String4ctorEPKc(ptr, ptr) define private i16 @_Z15lambda.L13C49.06Strings(%struct.String %0, i16 %1) { %result = alloca i16, align 2 diff --git a/test/test-files/irgenerator/lambdas/success-procedure-lambda/ir-code.ll b/test/test-files/irgenerator/lambdas/success-procedure-lambda/ir-code.ll index 00ac85726..1ec173ca2 100644 --- a/test/test-files/irgenerator/lambdas/success-procedure-lambda/ir-code.ll +++ b/test/test-files/irgenerator/lambdas/success-procedure-lambda/ir-code.ll @@ -35,7 +35,7 @@ define dso_local i32 @main() #0 { store ptr poison, ptr %5, align 8 %6 = load { ptr, ptr }, ptr %fat.ptr1, align 8 store { ptr, ptr } %6, ptr %callbackWithArgs1, align 8 - call void @_ZN6String4ctorEPc(ptr noundef nonnull align 8 dereferenceable(24) %1, ptr @anon.string.0) + call void @_ZN6String4ctorEPKc(ptr noundef nonnull align 8 dereferenceable(24) %1, ptr @anon.string.0) %fct2 = load ptr, ptr %callbackWithArgs1, align 8 call void %fct2(ptr %1, double 3.140000e+00) store ptr @_Z15lambda.L12C41.06Stringb, ptr %fat.ptr3, align 8 @@ -43,7 +43,7 @@ define dso_local i32 @main() #0 { store ptr poison, ptr %7, align 8 %8 = load { ptr, ptr }, ptr %fat.ptr3, align 8 store { ptr, ptr } %8, ptr %callbackWithArgs2, align 8 - call void @_ZN6String4ctorEPc(ptr noundef nonnull align 8 dereferenceable(24) %2, ptr @anon.string.1) + call void @_ZN6String4ctorEPKc(ptr noundef nonnull align 8 dereferenceable(24) %2, ptr @anon.string.1) %9 = load %struct.String, ptr %2, align 8 %fct4 = load ptr, ptr %callbackWithArgs2, align 8 call void %fct4(%struct.String %9, i1 false) @@ -73,7 +73,7 @@ define private void @_Z14lambda.L7C44.0R6Stringd(ptr %0, double %1) { ret void } -declare void @_ZN6String4ctorEPc(ptr, ptr) +declare void @_ZN6String4ctorEPKc(ptr, ptr) define private void @_Z15lambda.L12C41.06Stringb(%struct.String %0, i1 %1) { %str = alloca %struct.String, align 8 diff --git a/test/test-files/irgenerator/methods/success-methods/ir-code.ll b/test/test-files/irgenerator/methods/success-methods/ir-code.ll index 8a0b9bad3..3951c1550 100644 --- a/test/test-files/irgenerator/methods/success-methods/ir-code.ll +++ b/test/test-files/irgenerator/methods/success-methods/ir-code.ll @@ -19,7 +19,7 @@ define private ptr @_ZN6Letter10getContentEv(ptr noundef nonnull align 8 derefer ret ptr %3 } -define private void @_ZN6Letter10setContentEPc(ptr noundef nonnull align 8 dereferenceable(8) %0, ptr %1) { +define private void @_ZN6Letter10setContentEPKc(ptr noundef nonnull align 8 dereferenceable(8) %0, ptr %1) { %this = alloca ptr, align 8 %text = alloca ptr, align 8 store ptr %0, ptr %this, align 8 @@ -37,7 +37,7 @@ define dso_local i32 @main() #0 { %letter = alloca %struct.Letter, align 8 store i32 0, ptr %result, align 4 store %struct.Letter { ptr @anon.string.0 }, ptr %letter, align 8 - call void @_ZN6Letter10setContentEPc(ptr noundef nonnull align 8 dereferenceable(8) %letter, ptr @anon.string.1) + call void @_ZN6Letter10setContentEPKc(ptr noundef nonnull align 8 dereferenceable(8) %letter, ptr @anon.string.1) %1 = call ptr @_ZN6Letter10getContentEv(ptr noundef nonnull align 8 dereferenceable(8) %letter) %2 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.0, ptr %1) %3 = load i32, ptr %result, align 4 diff --git a/test/test-files/irgenerator/pointers/success-nested-pointers/ir-code.ll b/test/test-files/irgenerator/pointers/success-nested-pointers/ir-code.ll index be039fc4b..3bb81e14b 100644 --- a/test/test-files/irgenerator/pointers/success-nested-pointers/ir-code.ll +++ b/test/test-files/irgenerator/pointers/success-nested-pointers/ir-code.ll @@ -10,7 +10,7 @@ target triple = "x86_64-w64-windows-gnu" @anon.array.0 = private unnamed_addr constant [4 x i32] [i32 1, i32 2, i32 3, i32 4] @printf.str.4 = private unnamed_addr constant [7 x i8] c"1: %d\0A\00", align 1 -define private void @_Z8testProcPPPA4i(ptr %0) { +define private void @_Z8testProcPPPPi(ptr %0) { %nums = alloca ptr, align 8 %nums1 = alloca ptr, align 8 %nums2 = alloca [4 x i32], align 4 @@ -55,7 +55,7 @@ define dso_local i32 @main() #1 { %3 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.4, i32 %2) store ptr %intArray, ptr %intArray1, align 8 store ptr %intArray1, ptr %intArray2, align 8 - call void @_Z8testProcPPPA4i(ptr %intArray2) + call void @_Z8testProcPPPPi(ptr %intArray2) %4 = load i32, ptr %result, align 4 ret i32 %4 } diff --git a/test/test-files/irgenerator/structs/success-constructors/ir-code.ll b/test/test-files/irgenerator/structs/success-constructors/ir-code.ll index ba0740410..8ad0776db 100644 --- a/test/test-files/irgenerator/structs/success-constructors/ir-code.ll +++ b/test/test-files/irgenerator/structs/success-constructors/ir-code.ll @@ -34,7 +34,7 @@ define private void @_ZN6Vector4ctorEv(ptr noundef nonnull align 8 dereferenceab ret void } -define private void @_ZN6Vector4ctorEPc(ptr noundef nonnull align 8 dereferenceable(16) %0, ptr %1) { +define private void @_ZN6Vector4ctorEPKc(ptr noundef nonnull align 8 dereferenceable(16) %0, ptr %1) { %this = alloca ptr, align 8 %msg = alloca ptr, align 8 store ptr %0, ptr %this, align 8 @@ -74,7 +74,7 @@ define dso_local i32 @main() #0 { %field2_addr = getelementptr inbounds %struct.Vector, ptr %vec, i32 0, i32 1 %4 = load ptr, ptr %field2_addr, align 8 %5 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.0, i32 %3, ptr %4) - call void @_ZN6Vector4ctorEPc(ptr noundef nonnull align 8 dereferenceable(16) %1, ptr @anon.string.2) + call void @_ZN6Vector4ctorEPKc(ptr noundef nonnull align 8 dereferenceable(16) %1, ptr @anon.string.2) %6 = load %struct.Vector, ptr %1, align 8 store %struct.Vector %6, ptr %vec, align 8 %field1_addr1 = getelementptr inbounds %struct.Vector, ptr %vec, i32 0, i32 0 diff --git a/test/test-files/irgenerator/structs/success-default-copy-ctor-nested/ir-code.ll b/test/test-files/irgenerator/structs/success-default-copy-ctor-nested/ir-code.ll index 428f37274..0d5ed7646 100644 --- a/test/test-files/irgenerator/structs/success-default-copy-ctor-nested/ir-code.ll +++ b/test/test-files/irgenerator/structs/success-default-copy-ctor-nested/ir-code.ll @@ -29,7 +29,7 @@ define private void @_ZN5Inner4ctorERK5Inner(ptr noundef nonnull align 2 derefer } ; Function Attrs: norecurse -define private void @_ZN6Middle4ctorERK6Middle(ptr noundef nonnull align 2 dereferenceable(2) %0, ptr %1) #0 { +define void @_ZN6Middle4ctorERK6Middle(ptr noundef nonnull align 2 dereferenceable(2) %0, ptr %1) #0 { %this = alloca ptr, align 8 store ptr %0, ptr %this, align 8 %3 = load ptr, ptr %this, align 8 @@ -41,7 +41,7 @@ define private void @_ZN6Middle4ctorERK6Middle(ptr noundef nonnull align 2 deref } ; Function Attrs: norecurse -define private void @_ZN5Outer4ctorERK5Outer(ptr noundef nonnull align 2 dereferenceable(2) %0, ptr %1) #0 { +define void @_ZN5Outer4ctorERK5Outer(ptr noundef nonnull align 2 dereferenceable(2) %0, ptr %1) #0 { %this = alloca ptr, align 8 store ptr %0, ptr %this, align 8 %3 = load ptr, ptr %this, align 8 diff --git a/test/test-files/irgenerator/structs/success-default-copy-ctor/ir-code.ll b/test/test-files/irgenerator/structs/success-default-copy-ctor/ir-code.ll index 2b5f4b1f4..f0cd645e1 100644 --- a/test/test-files/irgenerator/structs/success-default-copy-ctor/ir-code.ll +++ b/test/test-files/irgenerator/structs/success-default-copy-ctor/ir-code.ll @@ -9,7 +9,7 @@ target triple = "x86_64-w64-windows-gnu" @printf.str.1 = private unnamed_addr constant [7 x i8] c"%d %d\0A\00", align 1 ; Function Attrs: norecurse -define private void @_ZN12StructToCopy4ctorEv(ptr noundef nonnull align 4 dereferenceable(8) %0) #0 { +define void @_ZN12StructToCopy4ctorEv(ptr noundef nonnull align 4 dereferenceable(8) %0) #0 { %this = alloca ptr, align 8 store ptr %0, ptr %this, align 8 %2 = load ptr, ptr %this, align 8 diff --git a/test/test-files/irgenerator/structs/success-default-ctor-nested/ir-code.ll b/test/test-files/irgenerator/structs/success-default-ctor-nested/ir-code.ll index a8591ce77..9869d74ad 100644 --- a/test/test-files/irgenerator/structs/success-default-ctor-nested/ir-code.ll +++ b/test/test-files/irgenerator/structs/success-default-ctor-nested/ir-code.ll @@ -11,7 +11,7 @@ target triple = "x86_64-w64-windows-gnu" @printf.str.0 = private unnamed_addr constant [13 x i8] c"Message: %s\0A\00", align 1 ; Function Attrs: norecurse -define private void @_ZN5Inner4ctorEv(ptr noundef nonnull align 8 dereferenceable(8) %0) #0 { +define void @_ZN5Inner4ctorEv(ptr noundef nonnull align 8 dereferenceable(8) %0) #0 { %this = alloca ptr, align 8 store ptr %0, ptr %this, align 8 %2 = load ptr, ptr %this, align 8 @@ -21,7 +21,7 @@ define private void @_ZN5Inner4ctorEv(ptr noundef nonnull align 8 dereferenceabl } ; Function Attrs: norecurse -define private void @_ZN6Middle4ctorEv(ptr noundef nonnull align 8 dereferenceable(8) %0) #0 { +define void @_ZN6Middle4ctorEv(ptr noundef nonnull align 8 dereferenceable(8) %0) #0 { %this = alloca ptr, align 8 store ptr %0, ptr %this, align 8 %2 = load ptr, ptr %this, align 8 @@ -31,7 +31,7 @@ define private void @_ZN6Middle4ctorEv(ptr noundef nonnull align 8 dereferenceab } ; Function Attrs: norecurse -define private void @_ZN5Outer4ctorEv(ptr noundef nonnull align 8 dereferenceable(8) %0) #0 { +define void @_ZN5Outer4ctorEv(ptr noundef nonnull align 8 dereferenceable(8) %0) #0 { %this = alloca ptr, align 8 store ptr %0, ptr %this, align 8 %2 = load ptr, ptr %this, align 8 diff --git a/test/test-files/irgenerator/structs/success-default-ctor/ir-code.ll b/test/test-files/irgenerator/structs/success-default-ctor/ir-code.ll index a5cc00d75..7016bd488 100644 --- a/test/test-files/irgenerator/structs/success-default-ctor/ir-code.ll +++ b/test/test-files/irgenerator/structs/success-default-ctor/ir-code.ll @@ -12,7 +12,7 @@ target triple = "x86_64-w64-windows-gnu" @printf.str.3 = private unnamed_addr constant [27 x i8] c"Default value of bool: %d\0A\00", align 1 ; Function Attrs: norecurse -define private void @_ZN10TestStruct4ctorEv(ptr noundef nonnull align 8 dereferenceable(32) %0) #0 { +define void @_ZN10TestStruct4ctorEv(ptr noundef nonnull align 8 dereferenceable(32) %0) #0 { %this = alloca ptr, align 8 store ptr %0, ptr %this, align 8 %2 = load ptr, ptr %this, align 8 diff --git a/test/test-files/irgenerator/structs/success-default-dtor-nested/ir-code.ll b/test/test-files/irgenerator/structs/success-default-dtor-nested/ir-code.ll index 2d2de3ac2..a046a08f5 100644 --- a/test/test-files/irgenerator/structs/success-default-dtor-nested/ir-code.ll +++ b/test/test-files/irgenerator/structs/success-default-dtor-nested/ir-code.ll @@ -45,7 +45,7 @@ define private void @_ZN5Inner4dtorEv(ptr noundef nonnull align 8 dereferenceabl declare noundef i32 @printf(ptr nocapture noundef readonly, ...) #0 ; Function Attrs: norecurse -define private void @_ZN6Middle4dtorEv(ptr noundef nonnull align 8 dereferenceable(16) %0) #1 { +define void @_ZN6Middle4dtorEv(ptr noundef nonnull align 8 dereferenceable(16) %0) #1 { %this = alloca ptr, align 8 store ptr %0, ptr %this, align 8 %2 = load ptr, ptr %this, align 8 @@ -55,7 +55,7 @@ define private void @_ZN6Middle4dtorEv(ptr noundef nonnull align 8 dereferenceab } ; Function Attrs: norecurse -define private void @_ZN5Outer4dtorEv(ptr noundef nonnull align 8 dereferenceable(16) %0) #1 { +define void @_ZN5Outer4dtorEv(ptr noundef nonnull align 8 dereferenceable(16) %0) #1 { %this = alloca ptr, align 8 store ptr %0, ptr %this, align 8 %2 = load ptr, ptr %this, align 8 diff --git a/test/test-files/irgenerator/structs/success-default-dtor/ir-code.ll b/test/test-files/irgenerator/structs/success-default-dtor/ir-code.ll index 57512e2f7..e9c95d93a 100644 --- a/test/test-files/irgenerator/structs/success-default-dtor/ir-code.ll +++ b/test/test-files/irgenerator/structs/success-default-dtor/ir-code.ll @@ -11,7 +11,7 @@ target triple = "x86_64-w64-windows-gnu" @printf.str.1 = private unnamed_addr constant [16 x i8] c"Is nullptr: %d\0A\00", align 1 ; Function Attrs: norecurse -define private void @_ZN20StructWithHeapFields4dtorEv(ptr noundef nonnull align 8 dereferenceable(8) %0) #0 { +define void @_ZN20StructWithHeapFields4dtorEv(ptr noundef nonnull align 8 dereferenceable(8) %0) #0 { %this = alloca ptr, align 8 store ptr %0, ptr %this, align 8 %2 = load ptr, ptr %this, align 8 diff --git a/test/test-files/irgenerator/structs/success-default-field-values1/ir-code.ll b/test/test-files/irgenerator/structs/success-default-field-values1/ir-code.ll index 6f8cde046..c57df537b 100644 --- a/test/test-files/irgenerator/structs/success-default-field-values1/ir-code.ll +++ b/test/test-files/irgenerator/structs/success-default-field-values1/ir-code.ll @@ -10,7 +10,7 @@ target triple = "x86_64-w64-windows-gnu" @printf.str.1 = private unnamed_addr constant [12 x i8] c"String: %s\0A\00", align 1 ; Function Attrs: norecurse -define private void @_ZN4Test4ctorEv(ptr noundef nonnull align 8 dereferenceable(16) %0) #0 { +define void @_ZN4Test4ctorEv(ptr noundef nonnull align 8 dereferenceable(16) %0) #0 { %this = alloca ptr, align 8 store ptr %0, ptr %this, align 8 %2 = load ptr, ptr %this, align 8 diff --git a/test/test-files/irgenerator/structs/success-default-field-values3/ir-code.ll b/test/test-files/irgenerator/structs/success-default-field-values3/ir-code.ll index bdff12cfa..1dedeb384 100644 --- a/test/test-files/irgenerator/structs/success-default-field-values3/ir-code.ll +++ b/test/test-files/irgenerator/structs/success-default-field-values3/ir-code.ll @@ -10,7 +10,7 @@ target triple = "x86_64-w64-windows-gnu" @printf.str.1 = private unnamed_addr constant [12 x i8] c"String: %s\0A\00", align 1 ; Function Attrs: norecurse -define private void @_ZN4Test4ctorEv(ptr noundef nonnull align 8 dereferenceable(16) %0) #0 { +define void @_ZN4Test4ctorEv(ptr noundef nonnull align 8 dereferenceable(16) %0) #0 { %this = alloca ptr, align 8 store ptr %0, ptr %this, align 8 %2 = load ptr, ptr %this, align 8 diff --git a/test/test-files/irgenerator/structs/success-destructors1/ir-code.ll b/test/test-files/irgenerator/structs/success-destructors1/ir-code.ll index e1d20b6f9..3b8a3220b 100644 --- a/test/test-files/irgenerator/structs/success-destructors1/ir-code.ll +++ b/test/test-files/irgenerator/structs/success-destructors1/ir-code.ll @@ -33,7 +33,7 @@ assert.exit.L8: ; preds = %1 %8 = load ptr, ptr %this, align 8 %field2_addr = getelementptr inbounds %struct.Vector, ptr %8, i32 0, i32 1 %9 = load ptr, ptr %field2_addr, align 8 - %10 = call i1 @_Z10isRawEqualPcPc(ptr %9, ptr @anon.string.1) + %10 = call i1 @_Z10isRawEqualPKcPKc(ptr %9, ptr @anon.string.1) br i1 %10, label %assert.exit.L9, label %assert.then.L9, !prof !0 assert.then.L9: ; preds = %assert.exit.L8 @@ -54,7 +54,7 @@ declare i32 @memcmp(ptr, ptr, i64) #1 ; Function Attrs: cold noreturn nounwind declare void @exit(i32) #2 -declare i1 @_Z10isRawEqualPcPc(ptr, ptr) +declare i1 @_Z10isRawEqualPKcPKc(ptr, ptr) ; Function Attrs: noinline nounwind optnone uwtable define dso_local i32 @main() #3 { diff --git a/test/test-files/irgenerator/structs/success-destructors2/ir-code.ll b/test/test-files/irgenerator/structs/success-destructors2/ir-code.ll index cbce024ff..fd9d9d64f 100644 --- a/test/test-files/irgenerator/structs/success-destructors2/ir-code.ll +++ b/test/test-files/irgenerator/structs/success-destructors2/ir-code.ll @@ -53,7 +53,7 @@ assert.exit.L13: ; preds = %1 %8 = load ptr, ptr %this, align 8 %field2_addr = getelementptr inbounds %struct.Vector, ptr %8, i32 0, i32 1 %9 = load ptr, ptr %field2_addr, align 8 - %10 = call i1 @_Z10isRawEqualPcPc(ptr %9, ptr @anon.string.2) + %10 = call i1 @_Z10isRawEqualPKcPKc(ptr %9, ptr @anon.string.2) br i1 %10, label %assert.exit.L14, label %assert.then.L14, !prof !0 assert.then.L14: ; preds = %assert.exit.L13 @@ -71,7 +71,7 @@ declare i32 @memcmp(ptr, ptr, i64) #2 ; Function Attrs: cold noreturn nounwind declare void @exit(i32) #3 -declare i1 @_Z10isRawEqualPcPc(ptr, ptr) +declare i1 @_Z10isRawEqualPKcPKc(ptr, ptr) attributes #0 = { noinline nounwind optnone uwtable } attributes #1 = { nofree nounwind } diff --git a/test/test-files/irgenerator/structs/success-field-default-value-folding/ir-code.ll b/test/test-files/irgenerator/structs/success-field-default-value-folding/ir-code.ll index 0981142b4..9672ee739 100644 --- a/test/test-files/irgenerator/structs/success-field-default-value-folding/ir-code.ll +++ b/test/test-files/irgenerator/structs/success-field-default-value-folding/ir-code.ll @@ -28,7 +28,7 @@ target triple = "x86_64-w64-windows-gnu" @printf.str.0 = private unnamed_addr constant [24 x i8] c"All assertions passed!\0A\00", align 1 ; Function Attrs: norecurse -define private void @_ZN4Test4ctorEv(ptr noundef nonnull align 8 dereferenceable(72) %0) #0 { +define void @_ZN4Test4ctorEv(ptr noundef nonnull align 8 dereferenceable(72) %0) #0 { %this = alloca ptr, align 8 %2 = alloca i32, align 4 %3 = alloca i32, align 4 diff --git a/test/test-files/std/data/map-normal-usecase/cout.out b/test/test-files/std/data/map-normal-usecase/cout.out new file mode 100644 index 000000000..d8347e3cc --- /dev/null +++ b/test/test-files/std/data/map-normal-usecase/cout.out @@ -0,0 +1 @@ +All assertions passed! diff --git a/test/test-files/std/data/map-normal-usecase/source.spice b/test/test-files/std/data/map-normal-usecase/source.spice new file mode 100644 index 000000000..7285e39ff --- /dev/null +++ b/test/test-files/std/data/map-normal-usecase/source.spice @@ -0,0 +1,50 @@ +import "std/data/map"; + +f main() { + Map map; + assert map.getSize() == 0l; + assert map.isEmpty(); + map.insert(1, "Hello"); + assert map.getSize() == 1l; + assert !map.isEmpty(); + map.insert(2, "World"); + assert map.getSize() == 2l; + map.insert(3, "Foo"); + assert map.getSize() == 3l; + map.insert(4, "Bar"); + assert map.getSize() == 4l; + assert map.contains(1); + assert map.contains(2); + assert map.contains(3); + assert map.contains(4); + assert map.get(1) == "Hello"; + assert map.get(2) == "World"; + assert map.get(3) == "Foo"; + assert map.get(4) == "Bar"; + map.remove(2); + assert map.getSize() == 3l; + assert !map.contains(2); + assert !map.isEmpty(); + map.remove(1); + assert map.getSize() == 2l; + assert !map.contains(1); + assert !map.isEmpty(); + string& foo = map.get(3); + assert foo == "Foo"; + foo = "Baz"; + assert map.get(3) == "Baz"; + Result bar = map.getSafe(4); + assert bar.isOk(); + assert bar.unwrap() == "Bar"; + Result baz = map.getSafe(5); + assert baz.isErr(); + map.remove(3); + assert map.getSize() == 1l; + assert !map.contains(3); + assert !map.isEmpty(); + map.remove(4); + assert map.getSize() == 0l; + assert !map.contains(4); + assert map.isEmpty(); + printf("All assertions passed!\n"); +} \ No newline at end of file diff --git a/test/test-files/typechecker/aliases/success-complex-alias/symbol-table.json b/test/test-files/typechecker/aliases/success-complex-alias/symbol-table.json index 058d7f3bb..8cb1239fd 100644 --- a/test/test-files/typechecker/aliases/success-complex-alias/symbol-table.json +++ b/test/test-files/typechecker/aliases/success-complex-alias/symbol-table.json @@ -7,19 +7,10 @@ { "captures": [], "children": [], - "name": "ctor(const unsigned long)", + "name": "printLength()", "symbols": [ { - "codeLoc": "L8C19", - "isGlobal": false, - "isVolatile": false, - "name": "initialLength", - "orderIndex": 1, - "state": "initialized", - "type": "const unsigned long" - }, - { - "codeLoc": "L8C1", + "codeLoc": "L12C1", "isGlobal": false, "isVolatile": false, "name": "this", @@ -32,10 +23,19 @@ { "captures": [], "children": [], - "name": "printLength()", + "name": "ctor(const unsigned long)", "symbols": [ { - "codeLoc": "L12C1", + "codeLoc": "L8C19", + "isGlobal": false, + "isVolatile": false, + "name": "initialLength", + "orderIndex": 1, + "state": "initialized", + "type": "const unsigned long" + }, + { + "codeLoc": "L8C1", "isGlobal": false, "isVolatile": false, "name": "this", diff --git a/test/test-files/typechecker/foreach-loops/success-foreach-item-type-inference/symbol-table.json b/test/test-files/typechecker/foreach-loops/success-foreach-item-type-inference/symbol-table.json index b6bdcb7a9..0426482ca 100644 --- a/test/test-files/typechecker/foreach-loops/success-foreach-item-type-inference/symbol-table.json +++ b/test/test-files/typechecker/foreach-loops/success-foreach-item-type-inference/symbol-table.json @@ -7,32 +7,7 @@ { "captures": [], "children": [], - "name": "bool isValid()", - "symbols": [ - { - "codeLoc": "L23C1", - "isGlobal": false, - "isVolatile": false, - "name": "result", - "orderIndex": 1, - "state": "declared", - "type": "bool" - }, - { - "codeLoc": "L23C1", - "isGlobal": false, - "isVolatile": false, - "name": "this", - "orderIndex": 0, - "state": "declared", - "type": "MockIterator*" - } - ] - }, - { - "captures": [], - "children": [], - "name": "next()", + "name": "next()", "symbols": [ { "codeLoc": "L27C1", @@ -48,7 +23,7 @@ { "captures": [], "children": [], - "name": "short& get()", + "name": "short& get()", "symbols": [ { "codeLoc": "L15C1", @@ -73,7 +48,7 @@ { "captures": [], "children": [], - "name": "ctor()", + "name": "ctor()", "symbols": [ { "codeLoc": "L11C1", @@ -105,7 +80,32 @@ { "captures": [], "children": [], - "name": "bool isValid()", + "name": "Pair getIdx()", + "symbols": [ + { + "codeLoc": "L19C1", + "isGlobal": false, + "isVolatile": false, + "name": "result", + "orderIndex": 1, + "state": "declared", + "type": "public Pair" + }, + { + "codeLoc": "L19C1", + "isGlobal": false, + "isVolatile": false, + "name": "this", + "orderIndex": 0, + "state": "declared", + "type": "MockIterator*" + } + ] + }, + { + "captures": [], + "children": [], + "name": "bool isValid()", "symbols": [ { "codeLoc": "L23C1", @@ -114,7 +114,7 @@ "name": "result", "orderIndex": 1, "state": "declared", - "type": "invalid" + "type": "bool" }, { "codeLoc": "L23C1", @@ -123,17 +123,17 @@ "name": "this", "orderIndex": 0, "state": "declared", - "type": "MockIterator*" + "type": "MockIterator*" } ] }, { "captures": [], "children": [], - "name": "Pair getIdx()", + "name": "bool isValid()", "symbols": [ { - "codeLoc": "L19C1", + "codeLoc": "L23C1", "isGlobal": false, "isVolatile": false, "name": "result", @@ -142,7 +142,7 @@ "type": "invalid" }, { - "codeLoc": "L19C1", + "codeLoc": "L23C1", "isGlobal": false, "isVolatile": false, "name": "this", @@ -155,10 +155,10 @@ { "captures": [], "children": [], - "name": "T& get()", + "name": "Pair getIdx()", "symbols": [ { - "codeLoc": "L15C1", + "codeLoc": "L19C1", "isGlobal": false, "isVolatile": false, "name": "result", @@ -167,7 +167,7 @@ "type": "invalid" }, { - "codeLoc": "L15C1", + "codeLoc": "L19C1", "isGlobal": false, "isVolatile": false, "name": "this", @@ -180,25 +180,25 @@ { "captures": [], "children": [], - "name": "Pair getIdx()", + "name": "T& get()", "symbols": [ { - "codeLoc": "L19C1", + "codeLoc": "L15C1", "isGlobal": false, "isVolatile": false, "name": "result", "orderIndex": 1, "state": "declared", - "type": "public Pair" + "type": "invalid" }, { - "codeLoc": "L19C1", + "codeLoc": "L15C1", "isGlobal": false, "isVolatile": false, "name": "this", "orderIndex": 0, "state": "declared", - "type": "MockIterator*" + "type": "MockIterator*" } ] }, @@ -239,6 +239,24 @@ "state": "declared", "type": "f()" }, + { + "codeLoc": "L27C1", + "isGlobal": false, + "isVolatile": false, + "name": "next:L27C1", + "orderIndex": 7, + "state": "declared", + "type": "p()" + }, + { + "codeLoc": "L15C1", + "isGlobal": false, + "isVolatile": false, + "name": "get:L15C1", + "orderIndex": 4, + "state": "declared", + "type": "f()" + }, { "codeLoc": "L11C1", "isGlobal": false, @@ -284,24 +302,6 @@ "state": "initialized", "type": "unsigned long" }, - { - "codeLoc": "L27C1", - "isGlobal": false, - "isVolatile": false, - "name": "next:L27C1", - "orderIndex": 7, - "state": "declared", - "type": "p()" - }, - { - "codeLoc": "L15C1", - "isGlobal": false, - "isVolatile": false, - "name": "get:L15C1", - "orderIndex": 4, - "state": "declared", - "type": "f()" - }, { "codeLoc": "L23C1", "isGlobal": false, diff --git a/test/test-files/typechecker/generics/error-unused-template-type/exception.out b/test/test-files/typechecker/generics/error-unused-template-type/exception.out deleted file mode 100644 index 24c20da9c..000000000 --- a/test/test-files/typechecker/generics/error-unused-template-type/exception.out +++ /dev/null @@ -1,14 +0,0 @@ -[Error|Compiler]: -Unresolved soft errors: There are unresolved errors. Please fix them and recompile. - -[Error|Semantic] ./test-files/typechecker/generics/error-unused-template-type/source.spice:3:13: -Template types not used: Generic type was not used by the function parameters or the return type - -3 f test(int test) { - ^ - -[Error|Semantic] ./test-files/typechecker/generics/error-unused-template-type/source.spice:8:5: -Referenced undefined function: Function/procedure 'test(int)' could not be found - -8 test(0); - ^^^^^^^ \ No newline at end of file diff --git a/test/test-files/typechecker/generics/error-unused-template-type/source.spice b/test/test-files/typechecker/generics/error-unused-template-type/source.spice deleted file mode 100644 index 7dde72ceb..000000000 --- a/test/test-files/typechecker/generics/error-unused-template-type/source.spice +++ /dev/null @@ -1,9 +0,0 @@ -type T dyn; - -f test(int test) { - return 1 + test; -} - -f main() { - test(0); -} \ No newline at end of file