diff --git a/.github/workflows/ci-cpp.yml b/.github/workflows/ci-cpp.yml index 6dc896926..f9e6b62f4 100644 --- a/.github/workflows/ci-cpp.yml +++ b/.github/workflows/ci-cpp.yml @@ -52,14 +52,14 @@ jobs: uses: actions/cache@v3 with: path: /home/runner/work/spice/llvm - key: llvm-17.0.2 + key: llvm-17.0.4 - name: Setup LLVM if: steps.cache-llvm.outputs.cache-hit != 'true' run: | cd .. rm -rf llvm - git clone --depth 1 --branch llvmorg-17.0.2 https://github.com/llvm/llvm-project llvm + git clone --depth 1 --branch llvmorg-17.0.4 https://github.com/llvm/llvm-project llvm mkdir ./llvm/build cd ./llvm/build cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_CXX_FLAGS_RELEASE="-O2" -DLLVM_ENABLE_RTTI=ON -GNinja ../llvm diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 71ee9024d..e55c5b433 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -46,14 +46,14 @@ jobs: uses: actions/cache@v3 with: path: /home/runner/work/spice/llvm - key: llvm-17.0.2 + key: llvm-17.0.4 - name: Setup LLVM if: steps.cache-llvm.outputs.cache-hit != 'true' run: | echo "/usr/lib/ccache:/usr/local/opt/ccache/libexec" >> $GITHUB_PATH cd .. - git clone --depth 1 --branch llvmorg-17.0.2 https://github.com/llvm/llvm-project llvm + git clone --depth 1 --branch llvmorg-17.0.4 https://github.com/llvm/llvm-project llvm mkdir ./llvm/build cd ./llvm/build cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_CXX_FLAGS_RELEASE="-O2" -DLLVM_ENABLE_RTTI=ON -GNinja ../llvm diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index da9839fa7..fd8846c74 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -42,12 +42,12 @@ jobs: uses: actions/cache@v3 with: path: /home/runner/work/spice/spice/llvm - key: llvm-17.0.2-linux-x64 + key: llvm-17.0.4-linux-x64 - name: Setup LLVM if: steps.cache-llvm.outputs.cache-hit != 'true' run: | - git clone --depth 1 --branch llvmorg-17.0.2 https://github.com/llvm/llvm-project.git llvm + git clone --depth 1 --branch llvmorg-17.0.4 https://github.com/llvm/llvm-project.git llvm mkdir ./llvm/build cd ./llvm/build cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_CXX_FLAGS_RELEASE="-O2" -DLLVM_ENABLE_RTTI=ON -Wno-dev -Wattributes ../llvm @@ -107,12 +107,12 @@ jobs: uses: actions/cache@v3 with: path: /home/runner/work/spice/spice/llvm - key: llvm-17.0.2-linux-aarch64 + key: llvm-17.0.4-linux-aarch64 - name: Clone LLVM if: steps.cache-llvm.outputs.cache-hit != 'true' run: | - git clone --depth 1 --branch llvmorg-17.0.2 https://github.com/llvm/llvm-project.git llvm + git clone --depth 1 --branch llvmorg-17.0.4 https://github.com/llvm/llvm-project.git llvm mkdir ./llvm/build - name: Setup LLVM @@ -185,12 +185,12 @@ jobs: uses: actions/cache@v3 with: path: D:/a/spice/spice/llvm - key: llvm-17.0.2-win-x64 + key: llvm-17.0.4-win-x64 - name: Setup LLVM if: steps.cache-llvm.outputs.cache-hit != 'true' run: | - git clone --depth 1 --branch llvmorg-17.0.2 https://github.com/llvm/llvm-project.git llvm + git clone --depth 1 --branch llvmorg-17.0.4 https://github.com/llvm/llvm-project.git llvm setx /M PATH "%PATH%;C:\mingw64\mingw64\bin" $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") echo "Adding MinGW to path done." diff --git a/.run/spice.run.xml b/.run/spice.run.xml index b3d9d590c..e78fe3fb0 100644 --- a/.run/spice.run.xml +++ b/.run/spice.run.xml @@ -1,5 +1,5 @@ - + diff --git a/dev-setup.bat b/dev-setup.bat index cf4590a32..9517fa16d 100644 --- a/dev-setup.bat +++ b/dev-setup.bat @@ -27,7 +27,7 @@ echo done. REM - Clone LLVM echo [Step 2] Cloning LLVM (Could take a while) ... -git clone --depth 1 --branch llvmorg-17.0.2 https://github.com/llvm/llvm-project llvm +git clone --depth 1 --branch llvmorg-17.0.4 https://github.com/llvm/llvm-project llvm echo done. REM - Build LLVM diff --git a/dev-setup.sh b/dev-setup.sh index 0bc169343..5343f637e 100755 --- a/dev-setup.sh +++ b/dev-setup.sh @@ -15,7 +15,7 @@ colored_echo "done." # Clone LLVM colored_echo "[Step 2] Cloning LLVM (Could take a while) ... " -git clone --depth 1 --branch llvmorg-17.0.2 https://github.com/llvm/llvm-project llvm +git clone --depth 1 --branch llvmorg-17.0.4 https://github.com/llvm/llvm-project llvm colored_echo "done." # Build LLVM diff --git a/docs/docs/language/threads.md b/docs/docs/language/threads.md index d000b2746..62c6b94e3 100644 --- a/docs/docs/language/threads.md +++ b/docs/docs/language/threads.md @@ -14,6 +14,7 @@ f main() { Thread thread = Thread(p() { // Do something }); + thread.run(); } ``` @@ -26,17 +27,19 @@ f main() { Thread thread1 = Thread(p() { // Do something }); + thread1.run(); Thread thread2 = Thread(p() { // Do something }); + thread2.run(); // Do something thread1.join(); thread2.join(); } ``` -To get the ID of a thread, use the `getId()` method. To get the ID of the current thread (i.e. within the thread routine), you can -call the static `getThreadId()` function: +To get the ID of a thread, use the `getId()` method. This only works, if `run()` was already called on the thread object. +To get the ID of the current thread (i.e. within the thread routine), you can call the static `getThreadId()` function: ```spice import "std/os/thread"; @@ -48,6 +51,8 @@ f main() { Thread thread2 = Thread(p() { // Do something }); + thread2.run(); + thread1.run(); printf("Thread 1 ID: %d\n", thread1.getId()); printf("Thread 2 ID: %d\n", thread2.getId()); } diff --git a/media/test-project/test.spice b/media/test-project/test.spice index e0514849b..e008861b1 100644 --- a/media/test-project/test.spice +++ b/media/test-project/test.spice @@ -1,4 +1,64 @@ -type Iterable interface { +import "std/io/cli-parser"; + +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-2023"); + + 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"); + } +} + +/*import "std/io/cli-parser"; + +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-2023"); + + 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"); + } +}*/ + +/*type Iterable interface { p print(); } @@ -14,4 +74,4 @@ f main() { A a = A{5}; Iterable* i = &a; i.print(); -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/src/ast/ASTNodes.h b/src/ast/ASTNodes.h index b021a5678..f9f7e36e9 100644 --- a/src/ast/ASTNodes.h +++ b/src/ast/ASTNodes.h @@ -276,7 +276,7 @@ class FctDefBaseNode : public ASTNode { [[nodiscard]] std::string getSymbolTableEntryName() const { return Function::getSymbolTableEntryName(name->name, codeLoc); } std::vector *getFctManifestations(const std::string &_) override { return &manifestations; } [[nodiscard]] bool isFctOrProcDef() const override { return true; } - [[nodiscard]] bool returnsOnAllControlPaths(bool *overrideUnreachable) const override; + bool returnsOnAllControlPaths(bool *overrideUnreachable) const override; // Public members FctNameNode *name; @@ -1728,6 +1728,7 @@ class FctCallNode : public ASTNode { // Methods [[nodiscard]] bool isOrdinaryCall() const { return callType == TYPE_ORDINARY; } [[nodiscard]] bool isMethodCall() const { return callType == TYPE_METHOD; } + [[nodiscard]] bool isVirtualMethodCall() const { return isMethodCall() && thisType.isBaseType(TY_INTERFACE); } [[nodiscard]] bool isCtorCall() const { return callType == TYPE_CTOR; } [[nodiscard]] bool isFctPtrCall() const { return callType == TYPE_FCT_PTR; } }; diff --git a/src/irgenerator/DebugInfoGenerator.cpp b/src/irgenerator/DebugInfoGenerator.cpp index 3090b9b9f..a9372fe19 100644 --- a/src/irgenerator/DebugInfoGenerator.cpp +++ b/src/irgenerator/DebugInfoGenerator.cpp @@ -315,8 +315,8 @@ llvm::DIType *DebugInfoGenerator::getDITypeForSymbolType(const ASTNode *node, co assert(spiceStruct != nullptr); // Check if we already know the DI type - if (spiceStruct->structDIType != nullptr) { - baseDiType = spiceStruct->structDIType; + if (spiceStruct->diType != nullptr) { + baseDiType = spiceStruct->diType; break; } @@ -333,14 +333,17 @@ llvm::DIType *DebugInfoGenerator::getDITypeForSymbolType(const ASTNode *node, co llvm::DICompositeType *structDiType = diBuilder->createStructType( diFile, spiceStruct->name, diFile, lineNo, structLayout->getSizeInBits(), alignInBits, llvm::DINode::FlagTypePassByValue | llvm::DINode::FlagNonTrivial, nullptr, {}, 0, nullptr, mangledName); - spiceStruct->structDIType = structDiType; + baseDiType = spiceStruct->diType = structDiType; // Collect DI types for fields std::vector fieldTypes; - for (size_t i = 0; i < spiceStruct->fieldTypes.size(); i++) { + for (size_t i = 0; i < spiceStruct->scope->getFieldCount(); i++) { // Get field entry SymbolTableEntry *fieldEntry = spiceStruct->scope->symbolTable.lookupStrictByIndex(i); assert(fieldEntry != nullptr && fieldEntry->isField()); + if (fieldEntry->isImplicitField) + continue; + const SymbolType fieldType = fieldEntry->getType(); const size_t fieldLineNo = fieldEntry->declNode->codeLoc.line; const size_t offsetInBits = structLayout->getElementOffsetInBits(i); @@ -354,7 +357,32 @@ llvm::DIType *DebugInfoGenerator::getDITypeForSymbolType(const ASTNode *node, co } structDiType->replaceElements(llvm::MDTuple::get(irGenerator->context, fieldTypes)); - baseDiType = structDiType; + break; + } + case TY_INTERFACE: { + Interface *spiceInterface = symbolType.getInterface(node); + assert(spiceInterface != nullptr); + + // Check if we already know the DI type + if (spiceInterface->diType != nullptr) { + baseDiType = spiceInterface->diType; + break; + } + + // Retrieve information about the interface + const size_t lineNo = spiceInterface->getDeclCodeLoc().line; + llvm::Type *interfaceType = spiceInterface->entry->getType().toLLVMType(irGenerator->context, irGenerator->currentScope); + assert(interfaceType != nullptr); + const llvm::StructLayout *structLayout = + irGenerator->module->getDataLayout().getStructLayout(static_cast(interfaceType)); + const uint32_t alignInBits = irGenerator->module->getDataLayout().getABITypeAlign(interfaceType).value(); + + // Create interface type + const std::string mangledName = NameMangling::mangleInterface(*spiceInterface); + llvm::DICompositeType *interfaceDiType = diBuilder->createStructType( + diFile, spiceInterface->name, diFile, lineNo, structLayout->getSizeInBits(), alignInBits, + llvm::DINode::FlagTypePassByValue | llvm::DINode::FlagNonTrivial, nullptr, {}, 0, nullptr, mangledName); + baseDiType = spiceInterface->diType = interfaceDiType; break; } case TY_FUNCTION: // fall-through diff --git a/src/irgenerator/GenImplicit.cpp b/src/irgenerator/GenImplicit.cpp index d4441bc4f..438a5fd36 100644 --- a/src/irgenerator/GenImplicit.cpp +++ b/src/irgenerator/GenImplicit.cpp @@ -98,7 +98,7 @@ void IRGenerator::generateDeallocCall(llvm::Value *variableAddress) const { builder.CreateCall(deallocFct, variableAddress); } -llvm::Function *IRGenerator::generateImplicitProcedure(const std::function &generateBody, const Function *spiceFunc) { +llvm::Function *IRGenerator::generateImplicitProcedure(const std::function &generateBody, const Function *spiceFunc) { // Only focus on method procedures const ASTNode *node = spiceFunc->entry->declNode; assert(spiceFunc->isMethodProcedure()); @@ -195,154 +195,176 @@ llvm::Function *IRGenerator::generateImplicitProcedure(const std::functionimplicitDefault && ctorFunction->name == CTOR_FUNCTION_NAME); +void IRGenerator::generateCtorBodyPreamble(const Function *ctorFunction, Scope *bodyScope) { + // Retrieve struct scope + Scope *structScope = bodyScope->parent; + assert(structScope != nullptr); + + // Get struct address + SymbolTableEntry *thisEntry = bodyScope->lookupStrict(THIS_VARIABLE_NAME); + assert(thisEntry != nullptr); + llvm::Value *thisAddress = thisEntry->getAddress(); + assert(thisAddress != nullptr); + llvm::Value *thisAddressLoaded = nullptr; + SymbolType structSymbolType = thisEntry->getType().getBaseType(); + llvm::Type *structType = structSymbolType.toLLVMType(context, structScope); + + // Store VTable to first struct field if required + Struct *spiceStruct = structSymbolType.getStruct(nullptr); + assert(spiceStruct != nullptr); + if (spiceStruct->vtable != nullptr) { + assert(spiceStruct->vtableType != nullptr); + // Store VTable to field address at index 0 + thisAddressLoaded = builder.CreateLoad(builder.getPtrTy(), thisAddress); + llvm::Value *indices[3] = {builder.getInt32(0), builder.getInt32(0), builder.getInt32(2)}; + llvm::Value *gepResult = builder.CreateInBoundsGEP(spiceStruct->vtableType, spiceStruct->vtable, indices); + builder.CreateStore(gepResult, thisAddressLoaded); + } - const std::function generateBody = [&]() { - // Retrieve struct scope - Scope *structScope = ctorFunction->bodyScope->parent; - assert(structScope != nullptr); + const size_t fieldCount = structScope->getFieldCount(); + for (size_t i = 0; i < fieldCount; i++) { + SymbolTableEntry *fieldSymbol = structScope->symbolTable.lookupStrictByIndex(i); + assert(fieldSymbol != nullptr && fieldSymbol->isField()); + if (fieldSymbol->isImplicitField) + continue; + const SymbolType &fieldType = fieldSymbol->getType(); + auto fieldNode = spice_pointer_cast(fieldSymbol->declNode); + + // Call ctor for struct fields + if (fieldType.is(TY_STRUCT)) { + // Lookup ctor function and call if available + Scope *matchScope = fieldType.getBodyScope(); + const Function *ctorFunction = FunctionManager::lookupFunction(matchScope, CTOR_FUNCTION_NAME, fieldType, {}, false); + if (ctorFunction) + generateCtorOrDtorCall(fieldSymbol, ctorFunction, {}); + + continue; + } - // Get struct address - SymbolTableEntry *thisEntry = ctorFunction->bodyScope->lookupStrict(THIS_VARIABLE_NAME); - assert(thisEntry != nullptr); - llvm::Value *thisAddress = thisEntry->getAddress(); - assert(thisAddress != nullptr); - llvm::Value *thisAddressLoaded = nullptr; - llvm::Type *structType = thisEntry->getType().getBaseType().toLLVMType(context, structScope); - - const size_t fieldCount = structScope->getFieldCount(); - for (size_t i = 0; i < fieldCount; i++) { - SymbolTableEntry *fieldSymbol = structScope->symbolTable.lookupStrictByIndex(i); - assert(fieldSymbol != nullptr && fieldSymbol->isField()); - const SymbolType &fieldType = fieldSymbol->getType(); - auto fieldNode = spice_pointer_cast(fieldSymbol->declNode); - - // Call ctor for struct fields - if (fieldType.is(TY_STRUCT)) { - // Lookup ctor function and call if available - Scope *matchScope = fieldType.getBodyScope(); - const Function *ctorFunction = FunctionManager::lookupFunction(matchScope, CTOR_FUNCTION_NAME, fieldType, {}, false); - if (ctorFunction) - generateCtorOrDtorCall(fieldSymbol, ctorFunction, {}); - - continue; + // Store default field values + if (fieldNode->defaultValue() != nullptr || cliOptions.buildMode == BuildMode::DEBUG) { + // Retrieve field address + if (!thisAddressLoaded) + thisAddressLoaded = builder.CreateLoad(builder.getPtrTy(), thisAddress); + llvm::Value *indices[2] = {builder.getInt32(0), builder.getInt32(i)}; + llvm::Value *fieldAddress = builder.CreateInBoundsGEP(structType, thisAddressLoaded, indices); + // Retrieve default value + llvm::Value *value; + if (fieldNode->defaultValue() != nullptr) { + assert(fieldNode->defaultValue()->hasCompileTimeValue()); + const CompileTimeValue compileTimeValue = fieldNode->defaultValue()->getCompileTimeValue(); + value = getConst(compileTimeValue, fieldType, fieldNode->defaultValue()); + } else { + assert(cliOptions.buildMode == BuildMode::DEBUG); + value = getDefaultValueForSymbolType(fieldType); } + // Store default value + builder.CreateStore(value, fieldAddress); + } + } +} + +void IRGenerator::generateDefaultCtor(const Function *ctorFunction) { + assert(ctorFunction->implicitDefault && ctorFunction->name == CTOR_FUNCTION_NAME); + const std::function generateBody = [&]() { generateCtorBodyPreamble(ctorFunction, ctorFunction->bodyScope); }; + generateImplicitProcedure(generateBody, ctorFunction); +} - // Store default field values - if (fieldNode->defaultValue() != nullptr || cliOptions.buildMode == BuildMode::DEBUG) { +void IRGenerator::generateCopyCtorBodyPreamble(const Function *copyCtorFunction) { + // Retrieve struct scope + Scope *structScope = copyCtorFunction->bodyScope->parent; + assert(structScope != nullptr); + + // Get struct address + SymbolTableEntry *thisEntry = copyCtorFunction->bodyScope->lookupStrict(THIS_VARIABLE_NAME); + assert(thisEntry != nullptr); + llvm::Value *thisAddress = thisEntry->getAddress(); + assert(thisAddress != nullptr); + llvm::Value *thisAddressLoaded = nullptr; + llvm::Type *structType = thisEntry->getType().getBaseType().toLLVMType(context, structScope); + + const size_t fieldCount = structScope->getFieldCount(); + for (size_t i = 0; i < fieldCount; i++) { + SymbolTableEntry *fieldSymbol = structScope->symbolTable.lookupStrictByIndex(i); + assert(fieldSymbol != nullptr && fieldSymbol->isField()); + if (fieldSymbol->isImplicitField) + continue; + const SymbolType &fieldType = fieldSymbol->getType(); + + // Call copy ctor for struct fields + if (fieldType.is(TY_STRUCT)) { + // Lookup copy ctor function and call if available + Scope *matchScope = fieldType.getBodyScope(); + std::vector paramTypes = {fieldType.toConstReference(nullptr)}; + const Function *ctorFct = FunctionManager::lookupFunction(matchScope, CTOR_FUNCTION_NAME, fieldType, paramTypes, false); + if (ctorFct) { // Retrieve field address if (!thisAddressLoaded) thisAddressLoaded = builder.CreateLoad(builder.getPtrTy(), thisAddress); llvm::Value *indices[2] = {builder.getInt32(0), builder.getInt32(i)}; llvm::Value *fieldAddress = builder.CreateInBoundsGEP(structType, thisAddressLoaded, indices); - // Retrieve default value - llvm::Value *value; - if (fieldNode->defaultValue() != nullptr) { - assert(fieldNode->defaultValue()->hasCompileTimeValue()); - const CompileTimeValue compileTimeValue = fieldNode->defaultValue()->getCompileTimeValue(); - value = getConst(compileTimeValue, fieldType, fieldNode->defaultValue()); - } else { - assert(cliOptions.buildMode == BuildMode::DEBUG); - value = getDefaultValueForSymbolType(fieldType); - } - // Store default value - builder.CreateStore(value, fieldAddress); + generateCtorOrDtorCall(fieldSymbol, ctorFct, {fieldAddress}); } } - }; - generateImplicitProcedure(generateBody, ctorFunction); + } } -void IRGenerator::generateDefaultDefaultCopyCtor(const Function *copyCtorFunction) { +void IRGenerator::generateDefaultCopyCtor(const Function *copyCtorFunction) { assert(copyCtorFunction->implicitDefault && copyCtorFunction->name == CTOR_FUNCTION_NAME); + const std::function generateBody = [&]() { generateCopyCtorBodyPreamble(copyCtorFunction); }; + generateImplicitProcedure(generateBody, copyCtorFunction); +} - const std::function generateBody = [&]() { - // Retrieve struct scope - Scope *structScope = copyCtorFunction->bodyScope->parent; - assert(structScope != nullptr); +void IRGenerator::generateDtorBodyPreamble(const spice::compiler::Function *dtorFunction) { + // Retrieve struct scope + Scope *structScope = dtorFunction->bodyScope->parent; + assert(structScope != nullptr); + + // Get struct address + SymbolTableEntry *thisEntry = dtorFunction->bodyScope->lookupStrict(THIS_VARIABLE_NAME); + assert(thisEntry != nullptr); + llvm::Value *thisAddress = thisEntry->getAddress(); + assert(thisAddress != nullptr); + llvm::Value *thisAddressLoaded = nullptr; + llvm::Type *structType = thisEntry->getType().getBaseType().toLLVMType(context, structScope); + + const size_t fieldCount = structScope->getFieldCount(); + for (size_t i = 0; i < fieldCount; i++) { + SymbolTableEntry *fieldSymbol = structScope->symbolTable.lookupStrictByIndex(i); + assert(fieldSymbol != nullptr && fieldSymbol->isField()); + if (fieldSymbol->isImplicitField) + continue; + const SymbolType &fieldType = fieldSymbol->getType(); + + // Call dtor for struct fields + if (fieldType.is(TY_STRUCT)) { + // Lookup dtor function + Scope *matchScope = fieldType.getBodyScope(); + const Function *dtorFunction = FunctionManager::lookupFunction(matchScope, DTOR_FUNCTION_NAME, fieldType, {}, false); + + // Generate call to dtor + if (dtorFunction) + generateCtorOrDtorCall(fieldSymbol, dtorFunction, {}); + + continue; + } - // Get struct address - SymbolTableEntry *thisEntry = copyCtorFunction->bodyScope->lookupStrict(THIS_VARIABLE_NAME); - assert(thisEntry != nullptr); - llvm::Value *thisAddress = thisEntry->getAddress(); - assert(thisAddress != nullptr); - llvm::Value *thisAddressLoaded = nullptr; - llvm::Type *structType = thisEntry->getType().getBaseType().toLLVMType(context, structScope); - - const size_t fieldCount = structScope->getFieldCount(); - for (size_t i = 0; i < fieldCount; i++) { - SymbolTableEntry *fieldSymbol = structScope->symbolTable.lookupStrictByIndex(i); - assert(fieldSymbol != nullptr && fieldSymbol->isField()); - const SymbolType &fieldType = fieldSymbol->getType(); - - // Call copy ctor for struct fields - if (fieldType.is(TY_STRUCT)) { - // Lookup copy ctor function and call if available - Scope *matchScope = fieldType.getBodyScope(); - std::vector paramTypes = {fieldType.toConstReference(nullptr)}; - const Function *ctorFct = FunctionManager::lookupFunction(matchScope, CTOR_FUNCTION_NAME, fieldType, paramTypes, false); - if (ctorFct) { - // Retrieve field address - if (!thisAddressLoaded) - thisAddressLoaded = builder.CreateLoad(builder.getPtrTy(), thisAddress); - llvm::Value *indices[2] = {builder.getInt32(0), builder.getInt32(i)}; - llvm::Value *fieldAddress = builder.CreateInBoundsGEP(structType, thisAddressLoaded, indices); - generateCtorOrDtorCall(fieldSymbol, ctorFct, {fieldAddress}); - } - } + // Deallocate fields, that are stored on the heap + if (fieldType.isHeap()) { + // Retrieve field address + if (!thisAddressLoaded) + thisAddressLoaded = builder.CreateLoad(builder.getPtrTy(), thisAddress); + llvm::Value *indices[2] = {builder.getInt32(0), builder.getInt32(i)}; + llvm::Value *fieldAddress = builder.CreateInBoundsGEP(structType, thisAddressLoaded, indices); + // Call dealloc function + generateDeallocCall(fieldAddress); } - }; - generateImplicitProcedure(generateBody, copyCtorFunction); + } } -void IRGenerator::generateDefaultDefaultDtor(const Function *dtorFunction) { +void IRGenerator::generateDefaultDtor(const Function *dtorFunction) { assert(dtorFunction->implicitDefault && dtorFunction->name == DTOR_FUNCTION_NAME); - - const std::function generateBody = [&]() { - // Retrieve struct scope - Scope *structScope = dtorFunction->bodyScope->parent; - assert(structScope != nullptr); - - // Get struct address - SymbolTableEntry *thisEntry = dtorFunction->bodyScope->lookupStrict(THIS_VARIABLE_NAME); - assert(thisEntry != nullptr); - llvm::Value *thisAddress = thisEntry->getAddress(); - assert(thisAddress != nullptr); - llvm::Value *thisAddressLoaded = nullptr; - llvm::Type *structType = thisEntry->getType().getBaseType().toLLVMType(context, structScope); - - const size_t fieldCount = structScope->getFieldCount(); - for (size_t i = 0; i < fieldCount; i++) { - SymbolTableEntry *fieldSymbol = structScope->symbolTable.lookupStrictByIndex(i); - assert(fieldSymbol != nullptr && fieldSymbol->isField()); - const SymbolType &fieldType = fieldSymbol->getType(); - - // Call dtor for struct fields - if (fieldType.is(TY_STRUCT)) { - // Lookup dtor function - Scope *matchScope = fieldType.getBodyScope(); - const Function *dtorFunction = FunctionManager::lookupFunction(matchScope, DTOR_FUNCTION_NAME, fieldType, {}, false); - - // Generate call to dtor - if (dtorFunction) - generateCtorOrDtorCall(fieldSymbol, dtorFunction, {}); - - continue; - } - - // Deallocate fields, that are stored on the heap - if (fieldType.isHeap()) { - // Retrieve field address - if (!thisAddressLoaded) - thisAddressLoaded = builder.CreateLoad(builder.getPtrTy(), thisAddress); - llvm::Value *indices[2] = {builder.getInt32(0), builder.getInt32(i)}; - llvm::Value *fieldAddress = builder.CreateInBoundsGEP(structType, thisAddressLoaded, indices); - // Call dealloc function - generateDeallocCall(fieldAddress); - } - } - }; + const std::function generateBody = [&]() { generateDtorBodyPreamble(dtorFunction); }; generateImplicitProcedure(generateBody, dtorFunction); } diff --git a/src/irgenerator/GenTopLevelDefinitions.cpp b/src/irgenerator/GenTopLevelDefinitions.cpp index dd796a511..3d38a967f 100644 --- a/src/irgenerator/GenTopLevelDefinitions.cpp +++ b/src/irgenerator/GenTopLevelDefinitions.cpp @@ -128,7 +128,7 @@ std::any IRGenerator::visitMainFctDef(const MainFctDefNode *node) { std::any IRGenerator::visitFctDef(const FctDefNode *node) { // Loop through manifestations manIdx = 0; // Reset the symbolTypeIndex - for (const Function *manifestation : node->manifestations) { + for (Function *manifestation : node->manifestations) { assert(manifestation->entry != nullptr); // Check if the manifestation is substantiated or not public and not used by anybody @@ -201,6 +201,7 @@ std::any IRGenerator::visitFctDef(const FctDefNode *node) { module->getOrInsertFunction(mangledName, funcType); llvm::Function *func = module->getFunction(mangledName); node->entry->updateAddress(func); + manifestation->llvmFunction = func; // Set attributes to function func->setDSOLocal(true); @@ -294,7 +295,7 @@ std::any IRGenerator::visitFctDef(const FctDefNode *node) { std::any IRGenerator::visitProcDef(const ProcDefNode *node) { // Loop through manifestations manIdx = 0; // Reset the symbolTypeIndex - for (const Function *manifestation : node->manifestations) { + for (Function *manifestation : node->manifestations) { assert(manifestation->entry != nullptr); // Check if the manifestation is substantiated or not public and not used by anybody @@ -368,6 +369,7 @@ std::any IRGenerator::visitProcDef(const ProcDefNode *node) { module->getOrInsertFunction(mangledName, procType); llvm::Function *proc = module->getFunction(mangledName); node->entry->updateAddress(proc); + manifestation->llvmFunction = proc; // Set attributes to procedure proc->setDSOLocal(true); @@ -422,14 +424,9 @@ std::any IRGenerator::visitProcDef(const ProcDefNode *node) { visit(params.at(argIdx)); } - // If this is a constructor, store the default field values - if (node->isCtor && cliOptions.buildMode == BuildMode::DEBUG) { - assert(node->isMethod && thisEntry != nullptr); - assert(thisEntry->getType().isPtrOf(TY_STRUCT)); - const SymbolType structType = thisEntry->getType().getContainedTy(); - llvm::Constant *defaultStruct = getDefaultValueForSymbolType(structType); - builder.CreateStore(defaultStruct, proc->getArg(0)); - } + // Generate special ctor preamble before generating the body to store VTable, default field values, etc. if required + if (node->isCtor) + generateCtorBodyPreamble(manifestation, currentScope); // Visit procedure body visit(node->body()); @@ -486,10 +483,26 @@ std::any IRGenerator::visitStructDef(const StructDefNode *node) { SymbolTableEntry *structEntry = spiceStruct->entry; assert(structEntry != nullptr); structEntry->setStructLLVMType(structType); - - // Collect concrete field types std::vector fieldTypes; fieldTypes.reserve(node->fields().size()); + + // Collect interface types + if (const TypeLstNode *typeLst = node->interfaceTypeLst()) { + for (const DataTypeNode *interfaceTypeNode : typeLst->dataTypes()) { + const SymbolType symbolType = interfaceTypeNode->getEvaluatedSymbolType(manIdx); + assert(symbolType.is(TY_INTERFACE)); + const Interface *interface = symbolType.getInterface(interfaceTypeNode); + assert(interface != nullptr); + llvm::StructType *interfaceType = interface->entry->getStructLLVMType(); + assert(interfaceType != nullptr); + fieldTypes.push_back(interfaceType); + } + } else if (node->emitVTable) { + // If no interface was specified, we still need to add a pointer to the VTable + fieldTypes.push_back(builder.getPtrTy()); + } + + // Collect concrete field types for (const FieldNode *field : node->fields()) { SymbolTableEntry *fieldEntry = currentScope->lookupStrict(field->fieldName); assert(fieldEntry && !fieldEntry->getType().hasAnyGenericParts()); @@ -500,25 +513,27 @@ std::any IRGenerator::visitStructDef(const StructDefNode *node) { structType->setBody(fieldTypes); // Generate VTable if required - if (node->emitVTable) + if (node->emitVTable) { generateVTable(spiceStruct); + deferredVTableInitializations.emplace_back([=, this]() { generateVTableInitializer(spiceStruct); }, false); + } // Generate default ctor if required const SymbolType &thisType = structEntry->getType(); const Function *ctorFunc = FunctionManager::lookupFunction(currentScope, CTOR_FUNCTION_NAME, thisType, {}, true); if (ctorFunc != nullptr && ctorFunc->implicitDefault) - generateDefaultDefaultCtor(ctorFunc); + generateDefaultCtor(ctorFunc); // Generate default copy ctor if required const std::vector paramTypes = {thisType.toConstReference(node)}; const Function *copyCtorFunc = FunctionManager::lookupFunction(currentScope, CTOR_FUNCTION_NAME, thisType, paramTypes, true); if (copyCtorFunc != nullptr && copyCtorFunc->implicitDefault) - generateDefaultDefaultCopyCtor(copyCtorFunc); + generateDefaultCopyCtor(copyCtorFunc); // Generate default dtor if required const Function *dtorFunc = FunctionManager::lookupFunction(currentScope, DTOR_FUNCTION_NAME, thisType, {}, true); if (dtorFunc != nullptr && dtorFunc->implicitDefault) - generateDefaultDefaultDtor(dtorFunc); + generateDefaultDtor(dtorFunc); // Return to root scope currentScope = rootScope; @@ -552,9 +567,11 @@ std::any IRGenerator::visitInterfaceDef(const InterfaceDefNode *node) { // Set LLVM type to the interface entry node->entry->setStructLLVMType(structType); + spiceInterface->entry->setStructLLVMType(structType); // Generate VTable information generateVTable(spiceInterface); + deferredVTableInitializations.emplace_back([=, this]() { generateVTableInitializer(spiceInterface); }, false); } return nullptr; diff --git a/src/irgenerator/GenVTable.cpp b/src/irgenerator/GenVTable.cpp index 84e98a5c0..09d07fbd6 100644 --- a/src/irgenerator/GenVTable.cpp +++ b/src/irgenerator/GenVTable.cpp @@ -23,7 +23,7 @@ llvm::Constant *IRGenerator::generateTypeInfoName(StructBase *spiceStruct) { const std::string globalName = NameMangling::mangleTypeInfoName(spiceStruct); // Generate global string constant - llvm::Constant *typeInfoNameValue = builder.CreateGlobalStringPtr(spiceStruct->name, globalName, 0, module); + builder.CreateGlobalStringPtr(NameMangling::mangleTypeInfoValue(spiceStruct->name), globalName, 0, module); llvm::GlobalVariable *global = module->getNamedGlobal(globalName); // Set global attributes @@ -38,7 +38,6 @@ llvm::Constant *IRGenerator::generateTypeInfoName(StructBase *spiceStruct) { llvm::Constant *IRGenerator::generateTypeInfo(StructBase *spiceStruct) { assert(spiceStruct->entry != nullptr); - const bool isInterface = spiceStruct->entry->getType().is(TY_INTERFACE); // Generate type info name llvm::Constant *typeInfoName = generateTypeInfoName(spiceStruct); @@ -46,19 +45,36 @@ llvm::Constant *IRGenerator::generateTypeInfo(StructBase *spiceStruct) { // Generate LLVM type for type info const std::string mangledName = NameMangling::mangleTypeInfo(spiceStruct); llvm::PointerType *ptrTy = builder.getPtrTy(); - llvm::StructType *structType = llvm::StructType::get(context, {ptrTy, ptrTy}); + + std::vector interfaceTypes; + if (spiceStruct->entry->getType().is(TY_STRUCT)) { + auto spiceStructEnsured = static_cast(spiceStruct); + interfaceTypes = spiceStructEnsured->interfaceTypes; + } + + // Build type info LLVM type + std::vector typeInfoFieldTypes = {ptrTy, ptrTy}; + for (size_t i = 0; i < interfaceTypes.size(); i++) + typeInfoFieldTypes.push_back(ptrTy); + spiceStruct->typeInfoType = llvm::StructType::get(context, typeInfoFieldTypes); // Generate type info values llvm::Constant *typeInfoVTable = llvm::Constant::getNullValue(ptrTy); if (!sourceFile->isRttiRT()) - typeInfoVTable = llvm::ConstantExpr::getInBoundsGetElementPtr(ptrTy, typeInfoExtPtr, builder.getInt32(2)); + typeInfoVTable = llvm::ConstantExpr::getInBoundsGetElementPtr(ptrTy, typeInfoExtPtr, builder.getInt64(2)); std::vector fieldValues; fieldValues.push_back(typeInfoVTable); fieldValues.push_back(typeInfoName); - llvm::Constant *typeInfo = llvm::ConstantStruct::get(structType, fieldValues); + for (const SymbolType &interfaceType : interfaceTypes) { + Interface *interface = interfaceType.getInterface(nullptr); + assert(interface != nullptr && interface->typeInfo != nullptr); + llvm::Constant *global = module->getOrInsertGlobal(interface->typeInfo->getName(), builder.getPtrTy()); + fieldValues.push_back(global); + } + llvm::Constant *typeInfo = llvm::ConstantStruct::get(spiceStruct->typeInfoType, fieldValues); // Generate global variable - module->getOrInsertGlobal(mangledName, structType); + module->getOrInsertGlobal(mangledName, spiceStruct->typeInfoType); llvm::GlobalVariable *global = module->getNamedGlobal(mangledName); global->setInitializer(typeInfo); @@ -68,6 +84,7 @@ llvm::Constant *IRGenerator::generateTypeInfo(StructBase *spiceStruct) { global->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::None); global->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage); global->setComdat(module->getOrInsertComdat(mangledName)); + global->setAlignment(llvm::MaybeAlign(8)); return spiceStruct->typeInfo = global; } @@ -77,12 +94,40 @@ llvm::Constant *IRGenerator::generateVTable(StructBase *spiceStruct) { ensureRTTIRuntime(); // Retrieve virtual method count - const size_t virtualMethodCount = spiceStruct->scope->getMethodCount(); + const std::vector virtualMethods = spiceStruct->scope->getVirtualMethods(); + const size_t virtualMethodCount = virtualMethods.size(); const size_t arrayElementCount = virtualMethodCount + 2; // +2 for nullptr and TypeInfo // Generate type info data structures generateTypeInfo(spiceStruct); + // Generate VTable type + llvm::PointerType *ptrTy = llvm::PointerType::get(context, 0); + llvm::ArrayType *vtableArrayTy = llvm::ArrayType::get(ptrTy, arrayElementCount); + spiceStruct->vtableType = llvm::StructType::get(context, vtableArrayTy, false); + + const std::string mangledName = NameMangling::mangleVTable(spiceStruct); + module->getOrInsertGlobal(mangledName, spiceStruct->vtableType); + llvm::GlobalVariable *global = module->getNamedGlobal(mangledName); + + // Set global attributes + global->setConstant(true); + global->setDSOLocal(true); + global->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); + global->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage); + global->setComdat(module->getOrInsertComdat(mangledName)); + global->setAlignment(llvm::MaybeAlign(8)); + + return spiceStruct->vtable = global; +} + +void IRGenerator::generateVTableInitializer(StructBase *spiceStruct) { + // Retrieve virtual method count + assert(spiceStruct->scope); + const std::vector virtualMethods = spiceStruct->scope->getVirtualMethods(); + const size_t virtualMethodCount = virtualMethods.size(); + const size_t arrayElementCount = virtualMethodCount + 2; // +2 for nullptr and TypeInfo + // Generate VTable type llvm::PointerType *ptrTy = llvm::PointerType::get(context, 0); llvm::ArrayType *vtableArrayTy = llvm::ArrayType::get(ptrTy, arrayElementCount); @@ -92,29 +137,20 @@ llvm::Constant *IRGenerator::generateVTable(StructBase *spiceStruct) { std::vector arrayValues; arrayValues.push_back(llvm::Constant::getNullValue(ptrTy)); // nullptr as safety guard arrayValues.push_back(spiceStruct->typeInfo); // TypeInfo to identify the type for the VTable - for (size_t i = 0; i < virtualMethodCount; i++) { - // ToDo - arrayValues.push_back(llvm::Constant::getNullValue(ptrTy)); + for (Function *virtualMethod : virtualMethods) { + assert(spiceStruct->scope->type == ScopeType::INTERFACE || virtualMethod->llvmFunction != nullptr); + arrayValues.push_back(virtualMethod->llvmFunction ?: llvm::Constant::getNullValue(ptrTy)); } // Generate VTable struct std::vector fieldValues; fieldValues.push_back(llvm::ConstantArray::get(vtableArrayTy, arrayValues)); - spiceStruct->vtable = llvm::ConstantStruct::get(vtableTy, fieldValues); + llvm::Constant *initializer = llvm::ConstantStruct::get(vtableTy, fieldValues); const std::string mangledName = NameMangling::mangleVTable(spiceStruct); - module->getOrInsertGlobal(mangledName, vtableTy); llvm::GlobalVariable *global = module->getNamedGlobal(mangledName); - global->setInitializer(spiceStruct->vtable); - - // Set global attributes - global->setConstant(true); - global->setDSOLocal(true); - global->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::None); - global->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage); - global->setComdat(module->getOrInsertComdat(mangledName)); - - return global; + assert(global != nullptr); + global->setInitializer(initializer); } -} // namespace spice::compiler +} // namespace spice::compiler \ No newline at end of file diff --git a/src/irgenerator/GenValues.cpp b/src/irgenerator/GenValues.cpp index 7126d983f..641a015b8 100644 --- a/src/irgenerator/GenValues.cpp +++ b/src/irgenerator/GenValues.cpp @@ -73,7 +73,7 @@ std::any IRGenerator::visitFctCall(const FctCallNode *node) { assert(!data.isCtorCall()); // Retrieve entry of the first fragment - assert(firstFragEntry != nullptr && firstFragEntry->getType().isBaseType(TY_STRUCT)); + assert(firstFragEntry != nullptr && firstFragEntry->getType().getBaseType().isOneOf({TY_STRUCT, TY_INTERFACE})); Scope *structScope = firstFragEntry->getType().getBaseType().getBodyScope(); // Get address of the referenced variable / struct instance @@ -177,7 +177,9 @@ std::any IRGenerator::visitFctCall(const FctCallNode *node) { // Function is not defined in the current module -> declare it llvm::FunctionType *fctType = nullptr; - if (!module->getFunction(mangledName)) { + if (llvm::Function *fct = module->getFunction(mangledName)) { + fctType = fct->getFunctionType(); + } else { // Get returnType llvm::Type *returnType = builder.getVoidTy(); if (!returnSType.is(TY_DYN)) @@ -193,22 +195,33 @@ std::any IRGenerator::visitFctCall(const FctCallNode *node) { argTypes.push_back(paramType.toLLVMType(context, accessScope)); fctType = llvm::FunctionType::get(returnType, argTypes, false); - if (!data.isFctPtrCall()) + if (!data.isFctPtrCall() && !data.isVirtualMethodCall()) module->getOrInsertFunction(mangledName, fctType); } + assert(fctType != nullptr); - llvm::Value *result; - if (data.isFctPtrCall()) { - // Get entry to load the function pointer + llvm::CallInst *result; + if (data.isVirtualMethodCall()) { + assert(data.callee->isVirtual); + assert(thisPtr != nullptr); + // Load VTable + llvm::Value *vtablePtr = builder.CreateLoad(builder.getPtrTy(), thisPtr, "vtable.addr"); + const size_t vtableIndex = data.callee->vtableIndex; + // Lookup function pointer in VTable + fctPtr = builder.CreateInBoundsGEP(builder.getPtrTy(), vtablePtr, builder.getInt64(vtableIndex), "vfct.addr"); + llvm::Value *fct = builder.CreateLoad(builder.getPtrTy(), fctPtr, "fct"); + + // Generate function call + result = builder.CreateCall({fctType, fct}, argValues); + } else if (data.isFctPtrCall()) { assert(firstFragEntry != nullptr); SymbolType firstFragType = firstFragEntry->getType(); if (!fctPtr) fctPtr = firstFragEntry->getAddress(); autoDeReferencePtr(fctPtr, firstFragType, currentScope); - llvm::Value *fct = builder.CreateLoad(builder.getPtrTy(), fctPtr); + llvm::Value *fct = builder.CreateLoad(builder.getPtrTy(), fctPtr, "fct"); // Generate function call - assert(fctType != nullptr); result = builder.CreateCall({fctType, fct}, argValues); } else { // Get callee function @@ -219,6 +232,14 @@ std::any IRGenerator::visitFctCall(const FctCallNode *node) { result = builder.CreateCall(callee, argValues); } + if (data.isMethodCall() || data.isCtorCall() || data.isVirtualMethodCall()) { + llvm::Type *thisType = data.thisType.toLLVMType(context, currentScope); + result->addParamAttr(0, llvm::Attribute::NoUndef); + result->addParamAttr(0, llvm::Attribute::NonNull); + result->addDereferenceableParamAttr(0, module->getDataLayout().getTypeStoreSize(thisType)); + result->addParamAttr(0, llvm::Attribute::getWithAlignment(context, module->getDataLayout().getABITypeAlign(thisType))); + } + // Attach address to anonymous symbol to keep track of deallocation SymbolTableEntry *anonymousSymbol = nullptr; llvm::Value *resultPtr = nullptr; @@ -339,6 +360,10 @@ std::any IRGenerator::visitStructInstantiation(const StructInstantiationNode *no if (canBeConstant) { // All field values are constants, so we can create a global constant struct instantiation // Collect constants std::vector constants; + // For each interface a nullptr + for (const SymbolType &interfaceType : spiceStruct->interfaceTypes) + constants.push_back(getDefaultValueForSymbolType(interfaceType)); + // Constant value for each field for (const LLVMExprResult &exprResult : fieldValueResults) constants.push_back(exprResult.constant); @@ -348,9 +373,23 @@ std::any IRGenerator::visitStructInstantiation(const StructInstantiationNode *no return LLVMExprResult{.constant = constantStruct}; } else { // We have at least one non-immediate value, so we need to take normal struct instantiation as fallback llvm::Value *structAddr = insertAlloca(structType); + const size_t interfaceCount = spiceStruct->interfaceTypes.size(); + const size_t fieldCount = spiceStruct->fieldTypes.size(); + size_t i = 0; + + // Store interface values at their corresponding offsets + for (; i < interfaceCount; i++) { + const SymbolType &interfaceType = spiceStruct->interfaceTypes.at(i); + // Get field value + llvm::Value *itemValue = getDefaultValueForSymbolType(interfaceType); + // Get field address + llvm::Value *currentFieldAddress = builder.CreateStructGEP(structType, structAddr, i); + // Store the item value + builder.CreateStore(itemValue, currentFieldAddress); + } // Store all field values at their corresponding offsets - for (size_t i = 0; i < fieldValueResults.size(); i++) { + for (; i < interfaceCount + fieldCount; i++) { LLVMExprResult &exprResult = fieldValueResults.at(i); // Get field value llvm::Value *itemValue = fieldTypes.at(i).isRef() ? resolveAddress(exprResult) : resolveValue(exprResult.node, exprResult); diff --git a/src/irgenerator/IRGenerator.cpp b/src/irgenerator/IRGenerator.cpp index 1e46b05e1..ed3bd9bf7 100644 --- a/src/irgenerator/IRGenerator.cpp +++ b/src/irgenerator/IRGenerator.cpp @@ -28,6 +28,10 @@ std::any IRGenerator::visitEntry(const EntryNode *node) { // Generate IR visitChildren(node); + // Execute deferred VTable initializations + for (DeferredLogic &deferredVTableInit : deferredVTableInitializations) + deferredVTableInit.execute(); + // Finalize debug info generator diGenerator.finalize(); @@ -197,6 +201,8 @@ llvm::Constant *IRGenerator::getDefaultValueForSymbolType(const SymbolType &symb // Get default values for all fields of the struct std::vector fieldConstants; fieldConstants.reserve(fieldCount); + + // Add default value for each struct field for (size_t i = 0; i < fieldCount; i++) { // Get entry of the field SymbolTableEntry *fieldEntry = structScope->symbolTable.lookupStrictByIndex(i); @@ -218,6 +224,16 @@ llvm::Constant *IRGenerator::getDefaultValueForSymbolType(const SymbolType &symb return llvm::ConstantStruct::get(structType, fieldConstants); } + // Interface + if (symbolType.is(TY_INTERFACE)) { + // Retrieve struct type + Scope *interfaceScope = symbolType.getBodyScope(); + assert(interfaceScope != nullptr); + auto structType = reinterpret_cast(symbolType.toLLVMType(context, interfaceScope)); + + return llvm::ConstantStruct::get(structType, llvm::Constant::getNullValue(builder.getPtrTy())); + } + throw CompilerError(INTERNAL_ERROR, "Cannot determine default value for symbol type"); // GCOV_EXCL_LINE } diff --git a/src/irgenerator/IRGenerator.h b/src/irgenerator/IRGenerator.h index 814635c63..38725f55f 100644 --- a/src/irgenerator/IRGenerator.h +++ b/src/irgenerator/IRGenerator.h @@ -8,6 +8,7 @@ #include #include #include +#include namespace spice::compiler { @@ -140,16 +141,20 @@ class IRGenerator : private CompilerPass, public ParallelizableASTVisitor { void generateScopeCleanup(const StmtLstNode *node) const; void generateCtorOrDtorCall(SymbolTableEntry *entry, const Function *ctorOrDtor, const std::vector &args) const; void generateDeallocCall(llvm::Value *variableAddress) const; - llvm::Function *generateImplicitProcedure(const std::function &generateBody, const Function *spiceFunc); - void generateDefaultDefaultCtor(const Function *ctorFunction); - void generateDefaultDefaultCopyCtor(const Function *copyCtorFunction); - void generateDefaultDefaultDtor(const Function *dtorFunction); + llvm::Function *generateImplicitProcedure(const std::function &generateBody, const Function *spiceFunc); + void generateCtorBodyPreamble(const Function *ctorFunction, Scope *bodyScope); + void generateDefaultCtor(const Function *ctorFunction); + void generateCopyCtorBodyPreamble(const Function *copyCtorFunction); + void generateDefaultCopyCtor(const Function *copyCtorFunction); + void generateDtorBodyPreamble(const Function *dtorFunction); + void generateDefaultDtor(const Function *dtorFunction); // Generate VTable void ensureRTTIRuntime(); llvm::Constant *generateTypeInfoName(StructBase *spiceStruct); llvm::Constant *generateTypeInfo(StructBase *spiceStruct); llvm::Constant *generateVTable(StructBase *spiceStruct); + void generateVTableInitializer(StructBase *spiceStruct); // Private members llvm::LLVMContext &context; @@ -167,6 +172,7 @@ class IRGenerator : private CompilerPass, public ParallelizableASTVisitor { llvm::BasicBlock *allocaInsertBlock = nullptr; llvm::Instruction *allocaInsertInst = nullptr; bool blockAlreadyTerminated = false; + std::vector deferredVTableInitializations; }; } // namespace spice::compiler \ No newline at end of file diff --git a/src/irgenerator/NameMangling.cpp b/src/irgenerator/NameMangling.cpp index 2135f2f9a..0307c2d84 100644 --- a/src/irgenerator/NameMangling.cpp +++ b/src/irgenerator/NameMangling.cpp @@ -244,6 +244,8 @@ std::string NameMangling::mangleTypeInfoName(const StructBase *structBase) { return out.str(); } +std::string NameMangling::mangleTypeInfoValue(const std::string &value) { return std::to_string(value.size()) + value; } + std::string NameMangling::mangleTypeInfo(const StructBase *structBase) { std::stringstream out; out << "_ZTI"; diff --git a/src/irgenerator/NameMangling.h b/src/irgenerator/NameMangling.h index 81df00a93..9da32ad93 100644 --- a/src/irgenerator/NameMangling.h +++ b/src/irgenerator/NameMangling.h @@ -49,6 +49,7 @@ class NameMangling { [[nodiscard]] static std::string mangleStruct(const Struct &spiceStruct); [[nodiscard]] static std::string mangleInterface(const Interface &spiceInterface); [[nodiscard]] static std::string mangleTypeInfoName(const StructBase *structBase); + [[nodiscard]] static std::string mangleTypeInfoValue(const std::string &value); [[nodiscard]] static std::string mangleTypeInfo(const StructBase *structBase); [[nodiscard]] static std::string mangleVTable(const StructBase *structBase); [[nodiscard]] static std::string mangleVTable(const std::string &typeName); diff --git a/src/model/Function.h b/src/model/Function.h index f9bf00224..c933c06e5 100644 --- a/src/model/Function.h +++ b/src/model/Function.h @@ -54,6 +54,7 @@ class Function { [[nodiscard]] ALWAYS_INLINE bool isNormalProcedure() const { return isProcedure() && !isMethod(); } [[nodiscard]] ALWAYS_INLINE bool isMethodFunction() const { return isFunction() && isMethod(); } [[nodiscard]] ALWAYS_INLINE bool isMethodProcedure() const { return isProcedure() && isMethod(); } + [[nodiscard]] ALWAYS_INLINE bool isVirtualMethod() const { return isMethod() && isVirtual; } [[nodiscard]] bool hasSubstantiatedParams() const; [[nodiscard]] bool hasSubstantiatedGenerics() const; [[nodiscard]] bool isFullySubstantiated() const; @@ -76,6 +77,9 @@ class Function { bool alreadyTypeChecked = false; bool used = false; bool implicitDefault = false; + llvm::Function *llvmFunction = nullptr; + bool isVirtual = false; + size_t vtableIndex = 0; // Json serializer/deserializer NLOHMANN_DEFINE_TYPE_INTRUSIVE(Function, name, thisType, returnType, paramList, templateTypes) diff --git a/src/model/StructBase.h b/src/model/StructBase.h index 29ecebeda..6c0936e05 100644 --- a/src/model/StructBase.h +++ b/src/model/StructBase.h @@ -42,10 +42,14 @@ class StructBase { size_t manifestationIndex = 0; bool genericSubstantiation = false; bool used = false; - llvm::DICompositeType *structDIType = nullptr; - llvm::Constant *typeInfoName = nullptr; - llvm::Constant *typeInfo = nullptr; - llvm::Constant *vtable = nullptr; + llvm::DICompositeType *diType = nullptr; + struct { + llvm::StructType *typeInfoType = nullptr; + llvm::StructType *vtableType = nullptr; + llvm::Constant *typeInfoName = nullptr; + llvm::Constant *typeInfo = nullptr; + llvm::Constant *vtable = nullptr; + }; }; } // namespace spice::compiler \ No newline at end of file diff --git a/src/symboltablebuilder/Scope.cpp b/src/symboltablebuilder/Scope.cpp index fcc60942f..1bd991629 100644 --- a/src/symboltablebuilder/Scope.cpp +++ b/src/symboltablebuilder/Scope.cpp @@ -149,14 +149,37 @@ size_t Scope::getFieldCount() const { } /** - * Get the number of methods if this is a struct scope + * Get all virtual methods in this scope, sorted by declaration code location * - * @return Number of methods + * @return List of virtual method pointers */ -size_t Scope::getMethodCount() const { +std::vector Scope::getVirtualMethods() { + assert(type == ScopeType::STRUCT || type == ScopeType::INTERFACE); + + // Collect all virtual methods + std::vector methods; + for (auto &symbol : functions) { + assert(!symbol.second.empty()); + for (auto &fct : symbol.second) + if (fct.second.isVirtualMethod()) + methods.push_back(&functions.at(symbol.first).at(fct.first)); + } + + // Sort the list + std::ranges::sort(methods, [](const Function *a, const Function *b) { return a->getDeclCodeLoc() < b->getDeclCodeLoc(); }); + + return methods; +} + +/** + * Get the number of virtual methods in this scope + * + * @return Number of virtual methods + */ +size_t Scope::getVirtualMethodCount() const { assert(type == ScopeType::STRUCT || type == ScopeType::INTERFACE); size_t methodCount = 0; - for (const auto& symbol : symbolTable.symbols) { + for (const auto &symbol : symbolTable.symbols) { const ASTNode *declNode = symbol.second.declNode; if (declNode->isFctOrProcDef() || declNode->isStructDef()) methodCount++; diff --git a/src/symboltablebuilder/Scope.h b/src/symboltablebuilder/Scope.h index 0ac570943..82c96cf31 100644 --- a/src/symboltablebuilder/Scope.h +++ b/src/symboltablebuilder/Scope.h @@ -77,7 +77,8 @@ class Scope { void collectWarnings(std::vector &warnings) const; void checkSuccessfulTypeInference() const; [[nodiscard]] size_t getFieldCount() const; - [[nodiscard]] size_t getMethodCount() const; + [[nodiscard]] std::vector getVirtualMethods(); + [[nodiscard]] size_t getVirtualMethodCount() const; [[nodiscard]] bool hasRefFields(); [[nodiscard]] size_t getLoopNestingDepth() const; [[nodiscard]] bool doesAllowUnsafeOperations() const; diff --git a/src/symboltablebuilder/SymbolTableBuilder.cpp b/src/symboltablebuilder/SymbolTableBuilder.cpp index cf1d0de4a..f9efb41ed 100644 --- a/src/symboltablebuilder/SymbolTableBuilder.cpp +++ b/src/symboltablebuilder/SymbolTableBuilder.cpp @@ -185,6 +185,16 @@ std::any SymbolTableBuilder::visitStructDef(StructDefNode *node) { rootScope->createChildScope(STRUCT_SCOPE_PREFIX + node->structName, ScopeType::STRUCT, &node->codeLoc); currentScope->isGenericScope = node->hasTemplateTypes; + // Insert implicit field for each interface type + if (node->interfaceTypeLst()) { + for (DataTypeNode *interfaceNode : node->interfaceTypeLst()->dataTypes()) { + const std::string &interfaceName = interfaceNode->baseDataType()->customDataType()->typeNameFragments.back(); + SymbolTableEntry *interfaceFieldEntry = currentScope->insert("this." + interfaceName, interfaceNode); + interfaceFieldEntry->used = true; + interfaceFieldEntry->isImplicitField = true; + } + } + // Visit children visitChildren(node); diff --git a/src/symboltablebuilder/SymbolTableEntry.h b/src/symboltablebuilder/SymbolTableEntry.h index ab65f40d3..19a38557b 100644 --- a/src/symboltablebuilder/SymbolTableEntry.h +++ b/src/symboltablebuilder/SymbolTableEntry.h @@ -57,6 +57,7 @@ class SymbolTableEntry { bool anonymous = false; bool used = false; bool omitDtorCall = false; + bool isImplicitField = false; private: // Members diff --git a/src/symboltablebuilder/SymbolType.cpp b/src/symboltablebuilder/SymbolType.cpp index 2c980b05b..e63d1695b 100644 --- a/src/symboltablebuilder/SymbolType.cpp +++ b/src/symboltablebuilder/SymbolType.cpp @@ -521,7 +521,9 @@ Struct *SymbolType::getStruct(const ASTNode *node) const { Interface *SymbolType::getInterface(const ASTNode *node) const { assert(is(TY_INTERFACE)); Scope *interfaceDefScope = getBodyScope()->parent; - return InterfaceManager::matchInterface(interfaceDefScope, getSubType(), getTemplateTypes(), node); + const std::string structName = getOriginalSubType(); + const std::vector &templateTypes = getTemplateTypes(); + return InterfaceManager::matchInterface(interfaceDefScope, structName, templateTypes, node); } bool operator==(const SymbolType &lhs, const SymbolType &rhs) { diff --git a/src/symboltablebuilder/TypeChain.cpp b/src/symboltablebuilder/TypeChain.cpp index 3e9a2c09d..4736c28bb 100644 --- a/src/symboltablebuilder/TypeChain.cpp +++ b/src/symboltablebuilder/TypeChain.cpp @@ -91,10 +91,9 @@ std::string SymbolType::TypeChainElement::getName(bool withSize) const { } case TY_ENUM: return "enum"; - case TY_GENERIC: - return "generic(" + subType + ")"; + case TY_GENERIC: // fall-through case TY_ALIAS: - return "alias(" + subType + ")"; + return subType; case TY_DYN: return "dyn"; case TY_FUNCTION: { diff --git a/src/typechecker/FunctionManager.cpp b/src/typechecker/FunctionManager.cpp index 4075817cf..d3cb12030 100644 --- a/src/typechecker/FunctionManager.cpp +++ b/src/typechecker/FunctionManager.cpp @@ -279,65 +279,6 @@ Function *FunctionManager::matchFunction(Scope *matchScope, const std::string &r return matches.front(); } -/** - * Check if there is a function in the scope, fulfilling all given requirements and if found, return it. - * If more than one function matches the requirement, an error gets thrown. - * - * @param matchScope Scope to match against - * @param requestedName Function name requirement - * @param templateTypeHints Template types to substantiate generic types - * @param requestedParamTypes Argument types requirement - * @param requestedReturnType Return type requirement - * @param strictSpecifierMatching Match argument and this type specifiers strictly - * @param callNode Call AST node for printing error messages - * @return Matched or not - */ -bool FunctionManager::matchInterfaceMethod(Scope *matchScope, const std::string &requestedName, - const std::vector &requestedParamTypes, - const SymbolType &requestedReturnType, bool strictSpecifierMatching) { - // Copy the registry to prevent iterating over items, that are created within the loop - FunctionRegistry functionRegistry = matchScope->functions; - // Loop over function registry to find functions, that match the requirements of the call - std::vector matches; - for (const auto &[defCodeLocStr, m] : functionRegistry) { - // Copy the manifestation list to prevent iterating over items, that are created within the loop - const FunctionManifestationList manifestations = m; - for (const auto &[mangledName, presetFunction] : manifestations) { - assert(presetFunction.hasSubstantiatedParams()); // No optional params are allowed at this point - - // Skip generic substantiations to prevent double matching of a function - if (presetFunction.genericSubstantiation) - continue; - - // Copy the function to be able to substantiate types - Function candidate = presetFunction; - - // Check name requirement - if (!matchName(candidate, requestedName)) - 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 - TypeMapping &typeMapping = candidate.typeMapping; - typeMapping.clear(); - typeMapping.reserve(candidate.templateTypes.size()); - - // Check arg types requirement - bool forceSubstantiation = false; - if (!matchArgTypes(candidate, requestedParamTypes, typeMapping, strictSpecifierMatching, forceSubstantiation)) - continue; // Leave this manifestation and try the next one - - if (!matchReturnType(candidate, requestedReturnType, typeMapping, strictSpecifierMatching)) - continue; // Leave this manifestation and try the next one - - // We found a match - return true; - } - } - - // We did not find a match - return false; -} - MatchResult FunctionManager::matchManifestation(Function &candidate, Scope *&matchScope, const std::string &requestedName, const SymbolType &requestedThisType, const std::vector &requestedParamTypes, bool strictSpecifierMatching, @@ -433,8 +374,10 @@ bool FunctionManager::matchThisType(Function &candidate, const SymbolType &reque */ bool FunctionManager::matchArgTypes(Function &candidate, const std::vector &requestedArgTypes, TypeMapping &typeMapping, bool strictSpecifierMatching, bool &needsSubstantiation) { + std::vector &candidateParamList = candidate.paramList; + // If the number of arguments does not match with the number of params, the matching fails - if (requestedArgTypes.size() != candidate.paramList.size()) + if (requestedArgTypes.size() != candidateParamList.size()) return false; // Give the type matcher a way to retrieve instances of GenericType by their name @@ -446,8 +389,8 @@ bool FunctionManager::matchArgTypes(Function &candidate, const std::vector &requestedParamTypes, bool strictSpecifierMatching, const ASTNode *callNode); - [[nodiscard]] static bool matchInterfaceMethod(Scope *matchScope, const std::string &requestedName, - const std::vector &requestedParamTypes, - const SymbolType &requestedReturnType, bool strictSpecifierMatching); private: // Private methods diff --git a/src/typechecker/StructManager.cpp b/src/typechecker/StructManager.cpp index 30a7636ce..1e32c9285 100644 --- a/src/typechecker/StructManager.cpp +++ b/src/typechecker/StructManager.cpp @@ -126,13 +126,34 @@ Struct *StructManager::matchStruct(Scope *matchScope, const std::string &request // Replace symbol types of field entries with concrete types assert(substantiatedStruct->scope != nullptr); - for (size_t i = 0; i < substantiatedStruct->fieldTypes.size(); i++) { + const size_t fieldCount = substantiatedStruct->fieldTypes.size(); + const size_t explicitFieldsStartIdx = substantiatedStruct->scope->getFieldCount() - fieldCount; + for (size_t i = 0; i < fieldCount; i++) { // Replace field type with concrete template type - SymbolTableEntry *fieldEntry = substantiatedStruct->scope->symbolTable.lookupStrictByIndex(i); + SymbolTableEntry *fieldEntry = substantiatedStruct->scope->symbolTable.lookupStrictByIndex(explicitFieldsStartIdx + i); assert(fieldEntry != nullptr && fieldEntry->isField()); fieldEntry->updateType(substantiatedStruct->fieldTypes.at(i), /*overwriteExistingType=*/true); } + // Instantiate implemented interfaces if required + for (SymbolType &interfaceType : substantiatedStruct->interfaceTypes) { + // Skip non-generic interfaces + if (!interfaceType.hasAnyGenericParts()) + continue; + + // Build template types + std::vector templateTypes = interfaceType.getTemplateTypes(); + TypeMatcher::substantiateTypesWithTypeMapping(templateTypes, typeMapping); + + // Instantiate interface + Scope *interfaceMatchScope = interfaceType.getBodyScope()->parent; + Interface *spiceInterface = + InterfaceManager::matchInterface(interfaceMatchScope, interfaceType.getOriginalSubType(), templateTypes, node); + assert(spiceInterface != nullptr); + + interfaceType = spiceInterface->entry->getType(); + } + // Add to matched structs matches.push_back(substantiatedStruct); } diff --git a/src/typechecker/TypeChecker.cpp b/src/typechecker/TypeChecker.cpp index a9d7b499f..4020b3bb1 100644 --- a/src/typechecker/TypeChecker.cpp +++ b/src/typechecker/TypeChecker.cpp @@ -427,6 +427,7 @@ std::any TypeChecker::visitSignature(SignatureNode *node) { // Add signature to current scope Function *manifestation = FunctionManager::insertFunction(currentScope, signature, &node->signatureManifestations); + manifestation->entry = node->entry; manifestation->used = true; // Prepare signature type @@ -1575,10 +1576,9 @@ std::any TypeChecker::visitFctCall(FctCallNode *node) { // Retrieve return type const bool isFct = data.isFctPtrCall() ? firstFragEntry->getType().getBaseType().is(TY_FUNCTION) : data.callee->isFunction(); - SymbolType returnType(TY_DYN); + SymbolType returnType; if (data.isFctPtrCall()) { - if (isFct) - returnType = firstFragEntry->getType().getBaseType().getFunctionReturnType(); + returnType = isFct ? firstFragEntry->getType().getBaseType().getFunctionReturnType() : SymbolType(TY_BOOL); } else if (data.isCtorCall()) { // Set return type to 'this' type returnType = data.thisType; @@ -1591,7 +1591,7 @@ std::any TypeChecker::visitFctCall(FctCallNode *node) { // Initialize return type if required SymbolTableEntry *anonymousSymbol = nullptr; - if (returnType.is(TY_STRUCT)) { + if (returnType.isBaseType(TY_STRUCT)) { SymbolType returnBaseType = returnType.getBaseType(); const std::string structName = returnBaseType.getOriginalSubType(); Scope *matchScope = returnBaseType.getBodyScope()->parent; @@ -1601,6 +1601,8 @@ std::any TypeChecker::visitFctCall(FctCallNode *node) { returnBaseType.setBodyScope(spiceStruct->scope); returnType = returnType.replaceBaseType(returnBaseType); + returnType = mapImportedScopeTypeToLocalType(returnType.getBaseType().getBodyScope(), returnType); + // Add anonymous symbol to keep track of deallocation if (returnType.is(TY_STRUCT)) anonymousSymbol = currentScope->symbolTable.insertAnonymous(returnType, node); @@ -1896,13 +1898,15 @@ std::any TypeChecker::visitStructInstantiation(StructInstantiationNode *node) { "You've passed too less/many field values. Pass either none or all of them") // Check if the field types are matching + const size_t fieldCount = spiceStruct->fieldTypes.size(); + const size_t explicitFieldsStartIdx = structScope->getFieldCount() - fieldCount; for (size_t i = 0; i < node->fieldLst()->args().size(); i++) { // Get actual type AssignExprNode *assignExpr = node->fieldLst()->args().at(i); auto fieldResult = std::any_cast(visit(assignExpr)); HANDLE_UNRESOLVED_TYPE_ER(fieldResult.type) // Get expected type - const SymbolTableEntry *expectedField = structScope->symbolTable.lookupStrictByIndex(i); + const SymbolTableEntry *expectedField = structScope->symbolTable.lookupStrictByIndex(explicitFieldsStartIdx + i); assert(expectedField != nullptr); SymbolType expectedType = expectedField->getType(); const bool rhsIsImmediate = assignExpr->hasCompileTimeValue(); @@ -2348,7 +2352,7 @@ std::any TypeChecker::visitFunctionDataType(FunctionDataTypeNode *node) { SymbolType TypeChecker::mapLocalTypeToImportedScopeType(const Scope *targetScope, const SymbolType &symbolType) const { // Skip all types, except structs - if (!symbolType.getBaseType().is(TY_STRUCT)) + if (!symbolType.isBaseType(TY_STRUCT)) return symbolType; // If the target scope is in the current source file, we can return the symbol type as is @@ -2375,19 +2379,20 @@ SymbolType TypeChecker::mapLocalTypeToImportedScopeType(const Scope *targetScope SymbolType TypeChecker::mapImportedScopeTypeToLocalType(const Scope *sourceScope, const SymbolType &symbolType) const { // Skip all types, except structs - if (!symbolType.getBaseType().is(TY_STRUCT)) + if (!symbolType.isBaseType(TY_STRUCT)) return symbolType; - // If the target scope is in the current source file, we can return the symbol type as is + // If the source scope is in the current source file, we can return the symbol type as is SourceFile *sourceSourceFile = sourceScope->sourceFile; if (sourceSourceFile == sourceFile) return symbolType; - // Match the scope of the symbol type against all scopes in the name registry of the target source file + // Match the scope of the symbol type against all scopes in the name registry of this source file + const SymbolType baseType = symbolType.getBaseType(); for (const auto &[_, entry] : sourceFile->exportedNameRegistry) if (entry.targetEntry != nullptr && entry.targetEntry->getType().isBaseType(TY_STRUCT)) for (const Struct *manifestation : *entry.targetEntry->declNode->getStructManifestations()) - if (manifestation->scope == symbolType.getBaseType().getBodyScope()) { + if (manifestation->scope == baseType.getBodyScope()) { // Get the 'fullest-qualified' registry entry const NameRegistryEntry *mostQualifiedEntry = sourceFile->getNameRegistryEntry(entry.name); assert(mostQualifiedEntry != nullptr); @@ -2396,10 +2401,9 @@ SymbolType TypeChecker::mapImportedScopeTypeToLocalType(const Scope *sourceScope // This source file does not know about the struct at all // -> show it how to find the struct - const std::string structName = symbolType.getBaseType().getSubType(); - const NameRegistryEntry *origRegistryEntry = sourceSourceFile->getNameRegistryEntry(structName); + const NameRegistryEntry *origRegistryEntry = sourceSourceFile->getNameRegistryEntry(baseType.getOriginalSubType()); assert(origRegistryEntry != nullptr); - sourceFile->addNameRegistryEntry(structName, origRegistryEntry->targetEntry, origRegistryEntry->targetScope, false); + sourceFile->addNameRegistryEntry(baseType.getSubType(), origRegistryEntry->targetEntry, origRegistryEntry->targetScope, false); return symbolType; } diff --git a/src/typechecker/TypeCheckerCheck.cpp b/src/typechecker/TypeCheckerCheck.cpp index bb8a9aa25..913b0170c 100644 --- a/src/typechecker/TypeCheckerCheck.cpp +++ b/src/typechecker/TypeCheckerCheck.cpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace spice::compiler { @@ -135,34 +136,63 @@ std::any TypeChecker::visitProcDefCheck(ProcDefNode *node) { } std::any TypeChecker::visitStructDefCheck(StructDefNode *node) { - // Change to generic struct scope - currentScope = currentScope->getChildScope(STRUCT_SCOPE_PREFIX + node->structName); - assert(currentScope != nullptr && currentScope->type == ScopeType::STRUCT); - - // Check if the struct implements all methods of all attached interfaces - for (const SymbolType &interfaceType : node->structManifestations.front()->interfaceTypes) { - // Retrieve interface instance - const std::string interfaceName = interfaceType.getOriginalSubType(); - Scope *matchScope = interfaceType.getBodyScope()->parent; - Interface *interface = InterfaceManager::matchInterface(matchScope, interfaceName, interfaceType.getTemplateTypes(), node); - assert(interface != nullptr); - - // Check for all methods, that it is implemented by the struct - for (const Function *expectedMethod : interface->methods) { - const std::string methodName = expectedMethod->name; - const std::vector params = expectedMethod->getParamTypes(); - const SymbolType &returnType = expectedMethod->returnType; - bool success = FunctionManager::matchInterfaceMethod(currentScope, methodName, params, returnType, true); - if (!success) - softError(node, INTERFACE_METHOD_NOT_IMPLEMENTED, - "The struct '" + node->structName + "' does not implement the method '" + expectedMethod->getSignature() + - "', requested of interface '" + interface->name + "'"); + node->resizeToNumberOfManifestations(node->structManifestations.size()); + manIdx = 0; // Reset the manifestation index + + // Get all manifestations for this procedure definition + for (auto &manifestation : node->structManifestations) { + // Skip non-substantiated or already checked procedures + if (!manifestation->isFullySubstantiated()) { + manIdx++; // Increase the manifestation index + continue; } - } - // Return to the root scope - currentScope = rootScope; - assert(currentScope != nullptr && currentScope->type == ScopeType::GLOBAL); + // Change to struct scope + changeToScope(manifestation->scope, ScopeType::STRUCT); + + // Build struct type + const SymbolType structType = manifestation->entry->getType(); + + // Check if the struct implements all methods of all attached interfaces + size_t vtableIndex = 0; + for (const SymbolType &interfaceType : manifestation->interfaceTypes) { + // Retrieve interface instance + const std::string interfaceName = interfaceType.getOriginalSubType(); + Scope *matchScope = interfaceType.getBodyScope()->parent; + Interface *interface = InterfaceManager::matchInterface(matchScope, interfaceName, interfaceType.getTemplateTypes(), node); + assert(interface != nullptr); + + // Check for all methods, that it is implemented by the struct + for (const Function *expectedMethod : interface->methods) { + const std::string methodName = expectedMethod->name; + std::vector params = expectedMethod->getParamTypes(); + SymbolType returnType = expectedMethod->returnType; + + // Substantiate + TypeMatcher::substantiateTypesWithTypeMapping(params, interface->typeMapping); + if (returnType.hasAnyGenericParts()) + TypeMatcher::substantiateTypeWithTypeMapping(returnType, interface->typeMapping); + + Function *spiceFunction = FunctionManager::matchFunction(currentScope, methodName, structType, params, true, nullptr); + if (!spiceFunction) { + softError(node, INTERFACE_METHOD_NOT_IMPLEMENTED, + "The struct '" + node->structName + "' does not implement method '" + expectedMethod->getSignature() + "'"); + continue; + } + + // Set to virtual, since it overrides the interface method + spiceFunction->isVirtual = true; + spiceFunction->vtableIndex = vtableIndex++; + } + } + + // Return to the root scope + currentScope = rootScope; + assert(currentScope != nullptr && currentScope->type == ScopeType::GLOBAL); + + manIdx++; // Increase the manifestation index + } + manIdx = 0; // Reset the manifestation index return nullptr; } diff --git a/src/typechecker/TypeCheckerImplicit.cpp b/src/typechecker/TypeCheckerImplicit.cpp index f173e3a77..c46e72048 100644 --- a/src/typechecker/TypeCheckerImplicit.cpp +++ b/src/typechecker/TypeCheckerImplicit.cpp @@ -85,14 +85,24 @@ void TypeChecker::createDefaultCtorIfRequired(const Struct &spiceStruct, Scope * if (thisType.isRef()) return; - auto fieldNode = spice_pointer_cast(fieldSymbol->declNode); - hasFieldsWithDefaultValue |= fieldNode->defaultValue() != nullptr; - if (fieldSymbol->getType().is(TY_STRUCT)) { - Scope *fieldScope = fieldSymbol->getType().getBodyScope(); - // Lookup ctor function - const Function *ctorFct = FunctionManager::matchFunction(fieldScope, CTOR_FUNCTION_NAME, thisType, {}, true, node); - hasFieldsToConstruct |= ctorFct != nullptr; - requestRevisitIfRequired(ctorFct); + if (auto fieldNode = dynamic_cast(fieldSymbol->declNode)) { + hasFieldsWithDefaultValue |= fieldNode->defaultValue() != nullptr; + if (fieldSymbol->getType().is(TY_STRUCT)) { + Scope *fieldScope = fieldSymbol->getType().getBodyScope(); + // Lookup ctor function + const Function *ctorFct = FunctionManager::matchFunction(fieldScope, CTOR_FUNCTION_NAME, thisType, {}, true, node); + hasFieldsToConstruct |= ctorFct != nullptr; + requestRevisitIfRequired(ctorFct); + } + } else { + assert(dynamic_cast(fieldSymbol->declNode) != nullptr); + if (fieldSymbol->getType().is(TY_STRUCT)) { + Scope *fieldScope = fieldSymbol->getType().getBodyScope(); + // Lookup ctor function + const Function *ctorFct = FunctionManager::matchFunction(fieldScope, CTOR_FUNCTION_NAME, thisType, {}, true, node); + hasFieldsToConstruct |= ctorFct != nullptr; + requestRevisitIfRequired(ctorFct); + } } } diff --git a/src/typechecker/TypeCheckerPrepare.cpp b/src/typechecker/TypeCheckerPrepare.cpp index 28ea553af..c74e99a04 100644 --- a/src/typechecker/TypeCheckerPrepare.cpp +++ b/src/typechecker/TypeCheckerPrepare.cpp @@ -432,14 +432,24 @@ std::any TypeChecker::visitInterfaceDefPrepare(InterfaceDefNode *node) { currentScope = node->interfaceScope; assert(currentScope->type == ScopeType::INTERFACE); - // Visit signatures - std::vector signatures; - signatures.reserve(node->signatures().size()); + // Visit methods + size_t vtableIndex = 0; + std::vector methods; + methods.reserve(node->signatures().size()); for (SignatureNode *signature : node->signatures()) { auto method = std::any_cast *>(visit(signature)); if (!method) return nullptr; - signatures.insert(signatures.end(), method->begin(), method->end()); + + // Set 'this' type + for (Function *m : *method) { + m->isVirtual = true; // Interface methods are always virtual + m->vtableIndex = vtableIndex; + m->thisType = interfaceType; + } + + methods.insert(methods.end(), method->begin(), method->end()); + vtableIndex++; } // Change to root scope @@ -447,7 +457,7 @@ std::any TypeChecker::visitInterfaceDefPrepare(InterfaceDefNode *node) { assert(currentScope->type == ScopeType::GLOBAL); // Build interface object - Interface spiceInterface(node->interfaceName, node->entry, node->interfaceScope, signatures, templateTypesGeneric, node); + Interface spiceInterface(node->interfaceName, node->entry, node->interfaceScope, methods, templateTypesGeneric, node); InterfaceManager::insertInterface(currentScope, spiceInterface, &node->interfaceManifestations); spiceInterface.scope = node->interfaceScope; diff --git a/src/typechecker/TypeMatcher.cpp b/src/typechecker/TypeMatcher.cpp index f5acf7cab..7d3dbcf20 100644 --- a/src/typechecker/TypeMatcher.cpp +++ b/src/typechecker/TypeMatcher.cpp @@ -102,6 +102,12 @@ bool TypeMatcher::matchRequestedToCandidateType(SymbolType candidateType, Symbol } } +void TypeMatcher::substantiateTypesWithTypeMapping(std::vector &symbolTypes, const TypeMapping &typeMapping) { + for (SymbolType &symbolType : symbolTypes) + if (symbolType.hasAnyGenericParts()) + substantiateTypeWithTypeMapping(symbolType, typeMapping); +} + void TypeMatcher::substantiateTypeWithTypeMapping(SymbolType &symbolType, const TypeMapping &typeMapping) { assert(symbolType.hasAnyGenericParts()); diff --git a/src/typechecker/TypeMatcher.h b/src/typechecker/TypeMatcher.h index ff5cb5af5..ffe2e04f4 100644 --- a/src/typechecker/TypeMatcher.h +++ b/src/typechecker/TypeMatcher.h @@ -24,6 +24,7 @@ class TypeMatcher { ResolverFct &resolverFct, bool strictSpecifiers); static bool matchRequestedToCandidateType(SymbolType candidateType, SymbolType requestedType, TypeMapping &typeMapping, ResolverFct &resolverFct, bool strictSpecifierMatching); + static void substantiateTypesWithTypeMapping(std::vector &symbolTypes, const TypeMapping &typeMapping); static void substantiateTypeWithTypeMapping(SymbolType &symbolType, const TypeMapping &typeMapping); }; diff --git a/src/util/DeferredLogic.h b/src/util/DeferredLogic.h index c6b0035ce..f6eb6abfd 100644 --- a/src/util/DeferredLogic.h +++ b/src/util/DeferredLogic.h @@ -10,11 +10,12 @@ namespace spice::compiler { struct DeferredLogic { public: // Constructors - explicit DeferredLogic(std::function deferredFunc) : deferredFunc(std::move(deferredFunc)) {} + explicit DeferredLogic(std::function deferredFunc, bool triggerOnDestruct = true) + : deferredFunc(std::move(deferredFunc)), triggerOnDestruct(triggerOnDestruct) {} // Destructor ~DeferredLogic() { - if (!alreadyExecuted) + if (triggerOnDestruct && !alreadyExecuted) deferredFunc(); } @@ -27,6 +28,7 @@ struct DeferredLogic { private: // Private members std::function deferredFunc; + bool triggerOnDestruct; bool alreadyExecuted = false; }; diff --git a/test/test-files/benchmark/success-fibonacci-threaded/ir-code-O3.ll b/test/test-files/benchmark/success-fibonacci-threaded/ir-code-O3.ll index 116c6829c..4d6a72f7b 100644 --- a/test/test-files/benchmark/success-fibonacci-threaded/ir-code-O3.ll +++ b/test/test-files/benchmark/success-fibonacci-threaded/ir-code-O3.ll @@ -65,79 +65,79 @@ for.body.L11: %.fca.1.gep = getelementptr inbounds %struct.Thread, ptr %0, i64 0, i32 1 %1 = getelementptr inbounds i8, ptr %threads, i64 24 call void @llvm.memset.p0.i64(ptr noundef nonnull align 8 dereferenceable(168) %1, i8 0, i64 168, i1 false) - call void @_ZN6Thread4ctorEPFvE(ptr nonnull %0, { ptr, ptr } { ptr @_Z15lambda.L12C29.0v, ptr undef }) #4 + call void @_ZN6Thread4ctorEPFvE(ptr noundef nonnull align 8 dereferenceable(24) %0, { ptr, ptr } { ptr @_Z15lambda.L12C29.0v, ptr undef }) #4 %.fca.0.0.load = load ptr, ptr %0, align 8 %.fca.0.1.load = load ptr, ptr %.fca.0.1.gep, align 8 %.fca.1.load = load i64, ptr %.fca.1.gep, align 8 store ptr %.fca.0.0.load, ptr %threads, align 8 store ptr %.fca.0.1.load, ptr %.fca.0.0.1.gep, align 8 store i64 %.fca.1.load, ptr %.fca.0.1.gep9, align 8 - call void @_ZN6Thread3runEv(ptr nonnull %threads) #4 - call void @_ZN6Thread4ctorEPFvE(ptr nonnull %0, { ptr, ptr } { ptr @_Z15lambda.L12C29.0v, ptr undef }) #4 + call void @_ZN6Thread3runEv(ptr noundef nonnull align 8 dereferenceable(8) %threads) #4 + call void @_ZN6Thread4ctorEPFvE(ptr noundef nonnull align 8 dereferenceable(24) %0, { ptr, ptr } { ptr @_Z15lambda.L12C29.0v, ptr undef }) #4 %.fca.0.0.load.1 = load ptr, ptr %0, align 8 %.fca.0.1.load.1 = load ptr, ptr %.fca.0.1.gep, align 8 %.fca.1.load.1 = load i64, ptr %.fca.1.gep, align 8 store ptr %.fca.0.0.load.1, ptr %.fca.1.0.0.gep, align 8 store ptr %.fca.0.1.load.1, ptr %.fca.1.0.1.gep, align 8 store i64 %.fca.1.load.1, ptr %.fca.1.1.gep, align 8 - call void @_ZN6Thread3runEv(ptr nonnull %.fca.1.0.0.gep) #4 - call void @_ZN6Thread4ctorEPFvE(ptr nonnull %0, { ptr, ptr } { ptr @_Z15lambda.L12C29.0v, ptr undef }) #4 + call void @_ZN6Thread3runEv(ptr noundef nonnull align 8 dereferenceable(8) %.fca.1.0.0.gep) #4 + call void @_ZN6Thread4ctorEPFvE(ptr noundef nonnull align 8 dereferenceable(24) %0, { ptr, ptr } { ptr @_Z15lambda.L12C29.0v, ptr undef }) #4 %.fca.0.0.load.2 = load ptr, ptr %0, align 8 %.fca.0.1.load.2 = load ptr, ptr %.fca.0.1.gep, align 8 %.fca.1.load.2 = load i64, ptr %.fca.1.gep, align 8 store ptr %.fca.0.0.load.2, ptr %.fca.2.0.0.gep, align 8 store ptr %.fca.0.1.load.2, ptr %.fca.2.0.1.gep, align 8 store i64 %.fca.1.load.2, ptr %.fca.2.1.gep, align 8 - call void @_ZN6Thread3runEv(ptr nonnull %.fca.2.0.0.gep) #4 - call void @_ZN6Thread4ctorEPFvE(ptr nonnull %0, { ptr, ptr } { ptr @_Z15lambda.L12C29.0v, ptr undef }) #4 + call void @_ZN6Thread3runEv(ptr noundef nonnull align 8 dereferenceable(8) %.fca.2.0.0.gep) #4 + call void @_ZN6Thread4ctorEPFvE(ptr noundef nonnull align 8 dereferenceable(24) %0, { ptr, ptr } { ptr @_Z15lambda.L12C29.0v, ptr undef }) #4 %.fca.0.0.load.3 = load ptr, ptr %0, align 8 %.fca.0.1.load.3 = load ptr, ptr %.fca.0.1.gep, align 8 %.fca.1.load.3 = load i64, ptr %.fca.1.gep, align 8 store ptr %.fca.0.0.load.3, ptr %.fca.3.0.0.gep, align 8 store ptr %.fca.0.1.load.3, ptr %.fca.3.0.1.gep, align 8 store i64 %.fca.1.load.3, ptr %.fca.3.1.gep, align 8 - call void @_ZN6Thread3runEv(ptr nonnull %.fca.3.0.0.gep) #4 - call void @_ZN6Thread4ctorEPFvE(ptr nonnull %0, { ptr, ptr } { ptr @_Z15lambda.L12C29.0v, ptr undef }) #4 + call void @_ZN6Thread3runEv(ptr noundef nonnull align 8 dereferenceable(8) %.fca.3.0.0.gep) #4 + call void @_ZN6Thread4ctorEPFvE(ptr noundef nonnull align 8 dereferenceable(24) %0, { ptr, ptr } { ptr @_Z15lambda.L12C29.0v, ptr undef }) #4 %.fca.0.0.load.4 = load ptr, ptr %0, align 8 %.fca.0.1.load.4 = load ptr, ptr %.fca.0.1.gep, align 8 %.fca.1.load.4 = load i64, ptr %.fca.1.gep, align 8 store ptr %.fca.0.0.load.4, ptr %.fca.4.0.0.gep, align 8 store ptr %.fca.0.1.load.4, ptr %.fca.4.0.1.gep, align 8 store i64 %.fca.1.load.4, ptr %.fca.4.1.gep, align 8 - call void @_ZN6Thread3runEv(ptr nonnull %.fca.4.0.0.gep) #4 - call void @_ZN6Thread4ctorEPFvE(ptr nonnull %0, { ptr, ptr } { ptr @_Z15lambda.L12C29.0v, ptr undef }) #4 + call void @_ZN6Thread3runEv(ptr noundef nonnull align 8 dereferenceable(8) %.fca.4.0.0.gep) #4 + call void @_ZN6Thread4ctorEPFvE(ptr noundef nonnull align 8 dereferenceable(24) %0, { ptr, ptr } { ptr @_Z15lambda.L12C29.0v, ptr undef }) #4 %.fca.0.0.load.5 = load ptr, ptr %0, align 8 %.fca.0.1.load.5 = load ptr, ptr %.fca.0.1.gep, align 8 %.fca.1.load.5 = load i64, ptr %.fca.1.gep, align 8 store ptr %.fca.0.0.load.5, ptr %.fca.5.0.0.gep, align 8 store ptr %.fca.0.1.load.5, ptr %.fca.5.0.1.gep, align 8 store i64 %.fca.1.load.5, ptr %.fca.5.1.gep, align 8 - call void @_ZN6Thread3runEv(ptr nonnull %.fca.5.0.0.gep) #4 - call void @_ZN6Thread4ctorEPFvE(ptr nonnull %0, { ptr, ptr } { ptr @_Z15lambda.L12C29.0v, ptr undef }) #4 + call void @_ZN6Thread3runEv(ptr noundef nonnull align 8 dereferenceable(8) %.fca.5.0.0.gep) #4 + call void @_ZN6Thread4ctorEPFvE(ptr noundef nonnull align 8 dereferenceable(24) %0, { ptr, ptr } { ptr @_Z15lambda.L12C29.0v, ptr undef }) #4 %.fca.0.0.load.6 = load ptr, ptr %0, align 8 %.fca.0.1.load.6 = load ptr, ptr %.fca.0.1.gep, align 8 %.fca.1.load.6 = load i64, ptr %.fca.1.gep, align 8 store ptr %.fca.0.0.load.6, ptr %.fca.6.0.0.gep, align 8 store ptr %.fca.0.1.load.6, ptr %.fca.6.0.1.gep, align 8 store i64 %.fca.1.load.6, ptr %.fca.6.1.gep, align 8 - call void @_ZN6Thread3runEv(ptr nonnull %.fca.6.0.0.gep) #4 - call void @_ZN6Thread4ctorEPFvE(ptr nonnull %0, { ptr, ptr } { ptr @_Z15lambda.L12C29.0v, ptr undef }) #4 + call void @_ZN6Thread3runEv(ptr noundef nonnull align 8 dereferenceable(8) %.fca.6.0.0.gep) #4 + call void @_ZN6Thread4ctorEPFvE(ptr noundef nonnull align 8 dereferenceable(24) %0, { ptr, ptr } { ptr @_Z15lambda.L12C29.0v, ptr undef }) #4 %.fca.0.0.load.7 = load ptr, ptr %0, align 8 %.fca.0.1.load.7 = load ptr, ptr %.fca.0.1.gep, align 8 %.fca.1.load.7 = load i64, ptr %.fca.1.gep, align 8 store ptr %.fca.0.0.load.7, ptr %.fca.7.0.0.gep, align 8 store ptr %.fca.0.1.load.7, ptr %.fca.7.0.1.gep, align 8 store i64 %.fca.1.load.7, ptr %.fca.7.1.gep, align 8 - call void @_ZN6Thread3runEv(ptr nonnull %.fca.7.0.0.gep) #4 + call void @_ZN6Thread3runEv(ptr noundef nonnull align 8 dereferenceable(8) %.fca.7.0.0.gep) #4 %puts = call i32 @puts(ptr nonnull dereferenceable(1) @str) - call void @_ZN6Thread4joinEv(ptr nonnull %threads) #4 - call void @_ZN6Thread4joinEv(ptr nonnull %.fca.1.0.0.gep) #4 - call void @_ZN6Thread4joinEv(ptr nonnull %.fca.2.0.0.gep) #4 - call void @_ZN6Thread4joinEv(ptr nonnull %.fca.3.0.0.gep) #4 - call void @_ZN6Thread4joinEv(ptr nonnull %.fca.4.0.0.gep) #4 - call void @_ZN6Thread4joinEv(ptr nonnull %.fca.5.0.0.gep) #4 - call void @_ZN6Thread4joinEv(ptr nonnull %.fca.6.0.0.gep) #4 - call void @_ZN6Thread4joinEv(ptr nonnull %.fca.7.0.0.gep) #4 + call void @_ZN6Thread4joinEv(ptr noundef nonnull align 8 dereferenceable(8) %threads) #4 + call void @_ZN6Thread4joinEv(ptr noundef nonnull align 8 dereferenceable(8) %.fca.1.0.0.gep) #4 + call void @_ZN6Thread4joinEv(ptr noundef nonnull align 8 dereferenceable(8) %.fca.2.0.0.gep) #4 + call void @_ZN6Thread4joinEv(ptr noundef nonnull align 8 dereferenceable(8) %.fca.3.0.0.gep) #4 + call void @_ZN6Thread4joinEv(ptr noundef nonnull align 8 dereferenceable(8) %.fca.4.0.0.gep) #4 + call void @_ZN6Thread4joinEv(ptr noundef nonnull align 8 dereferenceable(8) %.fca.5.0.0.gep) #4 + call void @_ZN6Thread4joinEv(ptr noundef nonnull align 8 dereferenceable(8) %.fca.6.0.0.gep) #4 + call void @_ZN6Thread4joinEv(ptr noundef nonnull align 8 dereferenceable(8) %.fca.7.0.0.gep) #4 %2 = call i32 (ptr, ...) @printf(ptr noundef nonnull dereferenceable(1) @printf.str.2) ret i32 0 } 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 f28b48e23..76acf3db0 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 @@ -25,4 +25,4 @@ pair = {first = 2, second = } $1 = {contents = , capacity = 5, size = 5} $2 = 5 All assertions passed! -[Inferior 1 (process 79152) exited normally] +[Inferior 1 (process 27560) 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 c2b339b59..57ef0c7c6 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 @@ -4,7 +4,8 @@ target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16 target triple = "x86_64-w64-windows-gnu" %struct.Vector = type { ptr, i64, i64 } -%struct.VectorIterator = type { ptr, i64 } +%struct.VectorIterator = type { %interface.Iterable, ptr, i64 } +%interface.Iterable = type { ptr } %struct.Pair = type { i64, ptr } @anon.string.0 = private unnamed_addr constant [68 x i8] c"Assertion failed: Condition 'vi.getSize() == 3' evaluated to false.\00", align 1 @@ -66,14 +67,14 @@ define dso_local i32 @main(i32 %0, ptr %1) #0 !dbg !15 { call void @llvm.dbg.declare(metadata ptr %_argv, metadata !26, metadata !DIExpression()), !dbg !24 store ptr %1, ptr %_argv, align 8, !dbg !24 call void @llvm.dbg.declare(metadata ptr %vi, metadata !27, metadata !DIExpression()), !dbg !36 - call void @_ZN6VectorIiE4ctorEv(ptr %vi), !dbg !37 + call void @_ZN6VectorIiE4ctorEv(ptr noundef nonnull align 8 dereferenceable(24) %vi), !dbg !37 store i32 123, ptr %3, align 4, !dbg !38 - call void @_ZN6VectorIiE8pushBackERKi(ptr %vi, ptr %3), !dbg !38 + call void @_ZN6VectorIiE8pushBackERKi(ptr noundef nonnull align 8 dereferenceable(24) %vi, ptr %3), !dbg !38 store i32 4321, ptr %4, align 4, !dbg !39 - call void @_ZN6VectorIiE8pushBackERKi(ptr %vi, ptr %4), !dbg !39 + call void @_ZN6VectorIiE8pushBackERKi(ptr noundef nonnull align 8 dereferenceable(24) %vi, ptr %4), !dbg !39 store i32 9876, ptr %5, align 4, !dbg !40 - call void @_ZN6VectorIiE8pushBackERKi(ptr %vi, ptr %5), !dbg !40 - %15 = call i64 @_ZN6VectorIiE7getSizeEv(ptr %vi), !dbg !41 + call void @_ZN6VectorIiE8pushBackERKi(ptr noundef nonnull align 8 dereferenceable(24) %vi, ptr %5), !dbg !40 + %15 = call i64 @_ZN6VectorIiE7getSizeEv(ptr noundef nonnull align 8 dereferenceable(24) %vi), !dbg !41 %16 = icmp eq i64 %15, 3, !dbg !42 br i1 %16, label %assert.exit.L12, label %assert.then.L12, !dbg !42, !prof !43 @@ -86,7 +87,7 @@ assert.exit.L12: ; preds = %2 %18 = call %struct.VectorIterator @_Z7iterateRN3std4data6vector6VectorIiEE(ptr %vi), !dbg !44 call void @llvm.dbg.declare(metadata ptr %it, metadata !45, metadata !DIExpression()), !dbg !52 store %struct.VectorIterator %18, ptr %it, align 8, !dbg !44 - %19 = call i1 @_ZN14VectorIteratorIiE7isValidEv(ptr %it), !dbg !53 + %19 = call i1 @_ZN14VectorIteratorIiE7isValidEv(ptr noundef nonnull align 8 dereferenceable(24) %it), !dbg !53 br i1 %19, label %assert.exit.L16, label %assert.then.L16, !dbg !53, !prof !43 assert.then.L16: ; preds = %assert.exit.L12 @@ -95,7 +96,7 @@ assert.then.L16: ; preds = %assert.exit.L12 unreachable, !dbg !53 assert.exit.L16: ; preds = %assert.exit.L12 - %21 = call ptr @_ZN14VectorIteratorIiE3getEv(ptr %it), !dbg !54 + %21 = call ptr @_ZN14VectorIteratorIiE3getEv(ptr noundef nonnull align 8 dereferenceable(24) %it), !dbg !54 %22 = load i32, ptr %21, align 4, !dbg !55 %23 = icmp eq i32 %22, 123, !dbg !55 br i1 %23, label %assert.exit.L17, label %assert.then.L17, !dbg !55, !prof !43 @@ -106,7 +107,7 @@ assert.then.L17: ; preds = %assert.exit.L16 unreachable, !dbg !55 assert.exit.L17: ; preds = %assert.exit.L16 - %25 = call ptr @_ZN14VectorIteratorIiE3getEv(ptr %it), !dbg !56 + %25 = call ptr @_ZN14VectorIteratorIiE3getEv(ptr noundef nonnull align 8 dereferenceable(24) %it), !dbg !56 %26 = load i32, ptr %25, align 4, !dbg !57 %27 = icmp eq i32 %26, 123, !dbg !57 br i1 %27, label %assert.exit.L18, label %assert.then.L18, !dbg !57, !prof !43 @@ -117,8 +118,8 @@ assert.then.L18: ; preds = %assert.exit.L17 unreachable, !dbg !57 assert.exit.L18: ; preds = %assert.exit.L17 - call void @_ZN14VectorIteratorIiE4nextEv(ptr %it), !dbg !58 - %29 = call ptr @_ZN14VectorIteratorIiE3getEv(ptr %it), !dbg !59 + call void @_ZN14VectorIteratorIiE4nextEv(ptr noundef nonnull align 8 dereferenceable(24) %it), !dbg !58 + %29 = call ptr @_ZN14VectorIteratorIiE3getEv(ptr noundef nonnull align 8 dereferenceable(24) %it), !dbg !59 %30 = load i32, ptr %29, align 4, !dbg !60 %31 = icmp eq i32 %30, 4321, !dbg !60 br i1 %31, label %assert.exit.L20, label %assert.then.L20, !dbg !60, !prof !43 @@ -129,7 +130,7 @@ assert.then.L20: ; preds = %assert.exit.L18 unreachable, !dbg !60 assert.exit.L20: ; preds = %assert.exit.L18 - %33 = call i1 @_ZN14VectorIteratorIiE7isValidEv(ptr %it), !dbg !61 + %33 = call i1 @_ZN14VectorIteratorIiE7isValidEv(ptr noundef nonnull align 8 dereferenceable(24) %it), !dbg !61 br i1 %33, label %assert.exit.L21, label %assert.then.L21, !dbg !61, !prof !43 assert.then.L21: ; preds = %assert.exit.L20 @@ -138,11 +139,11 @@ assert.then.L21: ; preds = %assert.exit.L20 unreachable, !dbg !61 assert.exit.L21: ; preds = %assert.exit.L20 - call void @_ZN14VectorIteratorIiE4nextEv(ptr %it), !dbg !62 - %35 = call %struct.Pair @_ZN14VectorIteratorIiE6getIdxEv(ptr %it), !dbg !63 + call void @_ZN14VectorIteratorIiE4nextEv(ptr noundef nonnull align 8 dereferenceable(24) %it), !dbg !62 + %35 = call %struct.Pair @_ZN14VectorIteratorIiE6getIdxEv(ptr noundef nonnull align 8 dereferenceable(24) %it), !dbg !63 call void @llvm.dbg.declare(metadata ptr %pair, metadata !64, metadata !DIExpression()), !dbg !70 store %struct.Pair %35, ptr %pair, align 8, !dbg !63 - %36 = call ptr @_ZN4PairImRiE8getFirstEv(ptr %pair), !dbg !71 + %36 = call ptr @_ZN4PairImRiE8getFirstEv(ptr noundef nonnull align 8 dereferenceable(16) %pair), !dbg !71 %37 = load i64, ptr %36, align 8, !dbg !72 %38 = icmp eq i64 %37, 2, !dbg !72 br i1 %38, label %assert.exit.L24, label %assert.then.L24, !dbg !72, !prof !43 @@ -153,7 +154,7 @@ assert.then.L24: ; preds = %assert.exit.L21 unreachable, !dbg !72 assert.exit.L24: ; preds = %assert.exit.L21 - %40 = call ptr @_ZN4PairImRiE9getSecondEv(ptr %pair), !dbg !73 + %40 = call ptr @_ZN4PairImRiE9getSecondEv(ptr noundef nonnull align 8 dereferenceable(16) %pair), !dbg !73 %41 = load i32, ptr %40, align 4, !dbg !74 %42 = icmp eq i32 %41, 9876, !dbg !74 br i1 %42, label %assert.exit.L25, label %assert.then.L25, !dbg !74, !prof !43 @@ -164,8 +165,8 @@ assert.then.L25: ; preds = %assert.exit.L24 unreachable, !dbg !74 assert.exit.L25: ; preds = %assert.exit.L24 - call void @_ZN14VectorIteratorIiE4nextEv(ptr %it), !dbg !75 - %44 = call i1 @_ZN14VectorIteratorIiE7isValidEv(ptr %it), !dbg !76 + call void @_ZN14VectorIteratorIiE4nextEv(ptr noundef nonnull align 8 dereferenceable(24) %it), !dbg !75 + %44 = call i1 @_ZN14VectorIteratorIiE7isValidEv(ptr noundef nonnull align 8 dereferenceable(24) %it), !dbg !76 %45 = xor i1 %44, true, !dbg !76 store i1 %45, ptr %6, align 1, !dbg !76 br i1 %45, label %assert.exit.L27, label %assert.then.L27, !dbg !76, !prof !43 @@ -177,10 +178,10 @@ assert.then.L27: ; preds = %assert.exit.L25 assert.exit.L27: ; preds = %assert.exit.L25 store i32 321, ptr %7, align 4, !dbg !77 - call void @_ZN6VectorIiE8pushBackERKi(ptr %vi, ptr %7), !dbg !77 + call void @_ZN6VectorIiE8pushBackERKi(ptr noundef nonnull align 8 dereferenceable(24) %vi, ptr %7), !dbg !77 store i32 -99, ptr %8, align 4, !dbg !78 - call void @_ZN6VectorIiE8pushBackERKi(ptr %vi, ptr %8), !dbg !78 - %47 = call i1 @_ZN14VectorIteratorIiE7isValidEv(ptr %it), !dbg !79 + call void @_ZN6VectorIiE8pushBackERKi(ptr noundef nonnull align 8 dereferenceable(24) %vi, ptr %8), !dbg !78 + %47 = call i1 @_ZN14VectorIteratorIiE7isValidEv(ptr noundef nonnull align 8 dereferenceable(24) %it), !dbg !79 br i1 %47, label %assert.exit.L32, label %assert.then.L32, !dbg !79, !prof !43 assert.then.L32: ; preds = %assert.exit.L27 @@ -190,7 +191,7 @@ assert.then.L32: ; preds = %assert.exit.L27 assert.exit.L32: ; preds = %assert.exit.L27 call void @_Z13op.minusequalR14VectorIteratorIiEi(ptr %it, i32 3), !dbg !80 - %49 = call ptr @_ZN14VectorIteratorIiE3getEv(ptr %it), !dbg !81 + %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 br i1 %51, label %assert.exit.L36, label %assert.then.L36, !dbg !82, !prof !43 @@ -201,7 +202,7 @@ assert.then.L36: ; preds = %assert.exit.L32 unreachable, !dbg !82 assert.exit.L36: ; preds = %assert.exit.L32 - %53 = call i1 @_ZN14VectorIteratorIiE7isValidEv(ptr %it), !dbg !83 + %53 = call i1 @_ZN14VectorIteratorIiE7isValidEv(ptr noundef nonnull align 8 dereferenceable(24) %it), !dbg !83 br i1 %53, label %assert.exit.L37, label %assert.then.L37, !dbg !83, !prof !43 assert.then.L37: ; preds = %assert.exit.L36 @@ -212,7 +213,7 @@ assert.then.L37: ; preds = %assert.exit.L36 assert.exit.L37: ; preds = %assert.exit.L36 %55 = load %struct.VectorIterator, ptr %it, align 8, !dbg !84 call void @_Z16op.plusplus.postR14VectorIteratorIiE(ptr %it), !dbg !84 - %56 = call ptr @_ZN14VectorIteratorIiE3getEv(ptr %it), !dbg !85 + %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 br i1 %58, label %assert.exit.L39, label %assert.then.L39, !dbg !86, !prof !43 @@ -225,7 +226,7 @@ assert.then.L39: ; preds = %assert.exit.L37 assert.exit.L39: ; preds = %assert.exit.L37 %60 = load %struct.VectorIterator, ptr %it, align 8, !dbg !87 call void @_Z18op.minusminus.postR14VectorIteratorIiE(ptr %it), !dbg !87 - %61 = call ptr @_ZN14VectorIteratorIiE3getEv(ptr %it), !dbg !88 + %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 br i1 %63, label %assert.exit.L41, label %assert.then.L41, !dbg !89, !prof !43 @@ -237,7 +238,7 @@ assert.then.L41: ; preds = %assert.exit.L39 assert.exit.L41: ; preds = %assert.exit.L39 call void @_Z12op.plusequalR14VectorIteratorIiEi(ptr %it, i32 4), !dbg !90 - %65 = call ptr @_ZN14VectorIteratorIiE3getEv(ptr %it), !dbg !91 + %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 br i1 %67, label %assert.exit.L43, label %assert.then.L43, !dbg !92, !prof !43 @@ -248,8 +249,8 @@ assert.then.L43: ; preds = %assert.exit.L41 unreachable, !dbg !92 assert.exit.L43: ; preds = %assert.exit.L41 - call void @_ZN14VectorIteratorIiE4nextEv(ptr %it), !dbg !93 - %69 = call i1 @_ZN14VectorIteratorIiE7isValidEv(ptr %it), !dbg !94 + call void @_ZN14VectorIteratorIiE4nextEv(ptr noundef nonnull align 8 dereferenceable(24) %it), !dbg !93 + %69 = call i1 @_ZN14VectorIteratorIiE7isValidEv(ptr noundef nonnull align 8 dereferenceable(24) %it), !dbg !94 %70 = xor i1 %69, true, !dbg !94 store i1 %70, ptr %9, align 1, !dbg !94 br i1 %70, label %assert.exit.L45, label %assert.then.L45, !dbg !94, !prof !43 @@ -283,7 +284,7 @@ foreach.tail.L48: ; preds = %foreach.body.L48 br label %foreach.head.L48, !dbg !99 foreach.exit.L48: ; preds = %foreach.head.L48 - %78 = call ptr @_ZN6VectorIiE3getEj(ptr %vi, i32 0), !dbg !100 + %78 = call ptr @_ZN6VectorIiE3getEj(ptr noundef nonnull align 8 dereferenceable(24) %vi, i32 0), !dbg !100 %79 = load i32, ptr %78, align 4, !dbg !101 %80 = icmp eq i32 %79, 123, !dbg !101 br i1 %80, label %assert.exit.L51, label %assert.then.L51, !dbg !101, !prof !43 @@ -294,7 +295,7 @@ assert.then.L51: ; preds = %foreach.exit.L48 unreachable, !dbg !101 assert.exit.L51: ; preds = %foreach.exit.L48 - %82 = call ptr @_ZN6VectorIiE3getEj(ptr %vi, i32 1), !dbg !102 + %82 = call ptr @_ZN6VectorIiE3getEj(ptr noundef nonnull align 8 dereferenceable(24) %vi, i32 1), !dbg !102 %83 = load i32, ptr %82, align 4, !dbg !103 %84 = icmp eq i32 %83, 4321, !dbg !103 br i1 %84, label %assert.exit.L52, label %assert.then.L52, !dbg !103, !prof !43 @@ -305,7 +306,7 @@ assert.then.L52: ; preds = %assert.exit.L51 unreachable, !dbg !103 assert.exit.L52: ; preds = %assert.exit.L51 - %86 = call ptr @_ZN6VectorIiE3getEj(ptr %vi, i32 2), !dbg !104 + %86 = call ptr @_ZN6VectorIiE3getEj(ptr noundef nonnull align 8 dereferenceable(24) %vi, i32 2), !dbg !104 %87 = load i32, ptr %86, align 4, !dbg !105 %88 = icmp eq i32 %87, 9876, !dbg !105 br i1 %88, label %assert.exit.L53, label %assert.then.L53, !dbg !105, !prof !43 @@ -339,7 +340,7 @@ foreach.tail.L56: ; preds = %foreach.body.L56 br label %foreach.head.L56, !dbg !110 foreach.exit.L56: ; preds = %foreach.head.L56 - %96 = call ptr @_ZN6VectorIiE3getEj(ptr %vi, i32 0), !dbg !111 + %96 = call ptr @_ZN6VectorIiE3getEj(ptr noundef nonnull align 8 dereferenceable(24) %vi, i32 0), !dbg !111 %97 = load i32, ptr %96, align 4, !dbg !112 %98 = icmp eq i32 %97, 124, !dbg !112 br i1 %98, label %assert.exit.L59, label %assert.then.L59, !dbg !112, !prof !43 @@ -350,7 +351,7 @@ assert.then.L59: ; preds = %foreach.exit.L56 unreachable, !dbg !112 assert.exit.L59: ; preds = %foreach.exit.L56 - %100 = call ptr @_ZN6VectorIiE3getEj(ptr %vi, i32 1), !dbg !113 + %100 = call ptr @_ZN6VectorIiE3getEj(ptr noundef nonnull align 8 dereferenceable(24) %vi, i32 1), !dbg !113 %101 = load i32, ptr %100, align 4, !dbg !114 %102 = icmp eq i32 %101, 4322, !dbg !114 br i1 %102, label %assert.exit.L60, label %assert.then.L60, !dbg !114, !prof !43 @@ -361,7 +362,7 @@ assert.then.L60: ; preds = %assert.exit.L59 unreachable, !dbg !114 assert.exit.L60: ; preds = %assert.exit.L59 - %104 = call ptr @_ZN6VectorIiE3getEj(ptr %vi, i32 2), !dbg !115 + %104 = call ptr @_ZN6VectorIiE3getEj(ptr noundef nonnull align 8 dereferenceable(24) %vi, i32 2), !dbg !115 %105 = load i32, ptr %104, align 4, !dbg !116 %106 = icmp eq i32 %105, 9877, !dbg !116 br i1 %106, label %assert.exit.L61, label %assert.then.L61, !dbg !116, !prof !43 @@ -405,7 +406,7 @@ foreach.tail.L63: ; preds = %foreach.body.L63 br label %foreach.head.L63, !dbg !124 foreach.exit.L63: ; preds = %foreach.head.L63 - %117 = call ptr @_ZN6VectorIiE3getEj(ptr %vi, i32 0), !dbg !125 + %117 = call ptr @_ZN6VectorIiE3getEj(ptr noundef nonnull align 8 dereferenceable(24) %vi, i32 0), !dbg !125 %118 = load i32, ptr %117, align 4, !dbg !126 %119 = icmp eq i32 %118, 124, !dbg !126 br i1 %119, label %assert.exit.L66, label %assert.then.L66, !dbg !126, !prof !43 @@ -416,7 +417,7 @@ assert.then.L66: ; preds = %foreach.exit.L63 unreachable, !dbg !126 assert.exit.L66: ; preds = %foreach.exit.L63 - %121 = call ptr @_ZN6VectorIiE3getEj(ptr %vi, i32 1), !dbg !127 + %121 = call ptr @_ZN6VectorIiE3getEj(ptr noundef nonnull align 8 dereferenceable(24) %vi, i32 1), !dbg !127 %122 = load i32, ptr %121, align 4, !dbg !128 %123 = icmp eq i32 %122, 4323, !dbg !128 br i1 %123, label %assert.exit.L67, label %assert.then.L67, !dbg !128, !prof !43 @@ -427,7 +428,7 @@ assert.then.L67: ; preds = %assert.exit.L66 unreachable, !dbg !128 assert.exit.L67: ; preds = %assert.exit.L66 - %125 = call ptr @_ZN6VectorIiE3getEj(ptr %vi, i32 2), !dbg !129 + %125 = call ptr @_ZN6VectorIiE3getEj(ptr noundef nonnull align 8 dereferenceable(24) %vi, i32 2), !dbg !129 %126 = load i32, ptr %125, align 4, !dbg !130 %127 = icmp eq i32 %126, 9879, !dbg !130 br i1 %127, label %assert.exit.L68, label %assert.then.L68, !dbg !130, !prof !43 @@ -497,7 +498,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: 70, type: !6, isLocal: true, isDefinition: true) !2 = distinct !DICompileUnit(language: DW_LANG_C17, 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\\I516467\\Documents\\JustForFunGitHubClones\\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") +!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") !6 = !DIStringType(name: "printf.str.0", size: 192) @@ -523,7 +524,7 @@ attributes #3 = { cold noreturn nounwind } !26 = !DILocalVariable(name: "_argv", arg: 2, scope: !15, file: !5, line: 6, type: !19) !27 = !DILocalVariable(name: "vi", scope: !15, file: !5, line: 8, type: !28) !28 = !DICompositeType(tag: DW_TAG_structure_type, name: "Vector", scope: !29, file: !29, line: 22, size: 192, align: 8, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !30, identifier: "struct.Vector") -!29 = !DIFile(filename: "vector.spice", directory: "C:\\Users\\I516467\\Documents\\JustForFunGitHubClones\\spice\\std\\data") +!29 = !DIFile(filename: "vector.spice", directory: "C:\\Users\\Marc\\Documents\\JustForFunGitHubClonesFast\\spice\\std\\data") !30 = !{!31, !33, !35} !31 = !DIDerivedType(tag: DW_TAG_member, name: "contents", scope: !28, file: !29, line: 23, baseType: !32, size: 64) !32 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !18, size: 64) @@ -540,12 +541,12 @@ attributes #3 = { cold noreturn nounwind } !43 = !{!"branch_weights", i32 2000, i32 1} !44 = !DILocation(line: 15, column: 22, scope: !15) !45 = !DILocalVariable(name: "it", scope: !15, file: !5, line: 15, type: !46) -!46 = !DICompositeType(tag: DW_TAG_structure_type, name: "VectorIterator", scope: !47, file: !47, line: 13, size: 128, align: 8, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !48, identifier: "struct.VectorIterator") -!47 = !DIFile(filename: "vector-iterator.spice", directory: "C:\\Users\\I516467\\Documents\\JustForFunGitHubClones\\spice\\std\\iterator") +!46 = !DICompositeType(tag: DW_TAG_structure_type, name: "VectorIterator", scope: !47, file: !47, line: 13, size: 192, align: 8, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !48, identifier: "struct.VectorIterator") +!47 = !DIFile(filename: "vector-iterator.spice", directory: "C:\\Users\\Marc\\Documents\\JustForFunGitHubClonesFast\\spice\\std\\iterator") !48 = !{!49, !51} -!49 = !DIDerivedType(tag: DW_TAG_member, name: "vector", scope: !46, file: !47, line: 14, baseType: !50, size: 64) +!49 = !DIDerivedType(tag: DW_TAG_member, name: "vector", scope: !46, file: !47, line: 14, baseType: !50, size: 64, offset: 64) !50 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !28, size: 64) -!51 = !DIDerivedType(tag: DW_TAG_member, name: "cursor", scope: !46, file: !47, line: 15, baseType: !34, size: 64, offset: 64) +!51 = !DIDerivedType(tag: DW_TAG_member, name: "cursor", scope: !46, file: !47, line: 15, baseType: !34, size: 64, offset: 128) !52 = !DILocation(line: 15, column: 5, scope: !15) !53 = !DILocation(line: 16, column: 12, scope: !15) !54 = !DILocation(line: 17, column: 12, scope: !15) @@ -560,7 +561,7 @@ attributes #3 = { cold noreturn nounwind } !63 = !DILocation(line: 23, column: 16, scope: !15) !64 = !DILocalVariable(name: "pair", scope: !15, file: !5, line: 23, type: !65) !65 = !DICompositeType(tag: DW_TAG_structure_type, name: "Pair", scope: !66, file: !66, line: 8, size: 128, align: 8, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !67, identifier: "struct.Pair") -!66 = !DIFile(filename: "pair.spice", directory: "C:\\Users\\I516467\\Documents\\JustForFunGitHubClones\\spice\\std\\data") +!66 = !DIFile(filename: "pair.spice", directory: "C:\\Users\\Marc\\Documents\\JustForFunGitHubClonesFast\\spice\\std\\data") !67 = !{!68, !69} !68 = !DIDerivedType(tag: DW_TAG_member, name: "first", scope: !65, file: !66, line: 9, baseType: !34, size: 64) !69 = !DIDerivedType(tag: DW_TAG_member, name: "second", scope: !65, file: !66, line: 10, baseType: !32, size: 64, offset: 64) 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 65bcbb547..86d90c41b 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 @@ -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 !53 store ptr %0, ptr %ref, align 8, !dbg !53 - call void @_ZN6String4ctorEPc(ptr %2, ptr @anon.string.0), !dbg !55 + call void @_ZN6String4ctorEPc(ptr noundef nonnull align 8 dereferenceable(24) %2, ptr @anon.string.0), !dbg !55 %3 = getelementptr inbounds %struct.TestStruct, ptr %ts, i32 0, i32 0, !dbg !56 store i64 6, ptr %3, align 8, !dbg !56 %4 = load %struct.String, ptr %2, align 8, !dbg !56 @@ -68,7 +68,7 @@ define dso_local i32 @main() #2 !dbg !60 { %2 = load i64, ptr %lng_addr, align 8, !dbg !71 %3 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.0, i64 %2), !dbg !71 %4 = getelementptr inbounds %struct.TestStruct, ptr %res, i32 0, i32 1, !dbg !72 - %5 = call ptr @_ZN6String6getRawEv(ptr %4), !dbg !72 + %5 = call ptr @_ZN6String6getRawEv(ptr noundef nonnull align 8 dereferenceable(24) %4), !dbg !72 %6 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.1, ptr %5), !dbg !72 %i_addr = getelementptr inbounds %struct.TestStruct, ptr %res, i32 0, i32 2, !dbg !73 %7 = load i32, ptr %i_addr, align 4, !dbg !73 @@ -95,7 +95,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_C17, 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\\I516467\\Documents\\JustForFunGitHubClones\\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") +!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()) !6 = distinct !DIGlobalVariable(name: "printf.str.0", linkageName: "printf.str.0", scope: !2, file: !7, line: 15, type: !8, isLocal: true, isDefinition: true) @@ -126,7 +126,7 @@ attributes #3 = { nofree nounwind } !31 = !DIBasicType(name: "long", size: 64, encoding: DW_ATE_signed) !32 = !DIDerivedType(tag: DW_TAG_member, name: "str", scope: !28, file: !7, line: 3, baseType: !33, size: 192, align: 8, offset: 64) !33 = !DICompositeType(tag: DW_TAG_structure_type, name: "String", scope: !34, file: !34, line: 13, size: 192, align: 8, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !35, identifier: "struct.String") -!34 = !DIFile(filename: "string_rt.spice", directory: "C:\\Users\\I516467\\Documents\\JustForFunGitHubClones\\spice\\std\\runtime") +!34 = !DIFile(filename: "string_rt.spice", directory: "C:\\Users\\Marc\\Documents\\JustForFunGitHubClonesFast\\spice\\std\\runtime") !35 = !{!36, !39, !41} !36 = !DIDerivedType(tag: DW_TAG_member, name: "contents", scope: !33, file: !34, line: 14, baseType: !37, size: 64) !37 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !38, size: 64) 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 4cdca3ead..67e616215 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 @@ -3,8 +3,9 @@ source_filename = "source.spice" target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-w64-windows-gnu" -%struct.NumberIterator = type { i16, i16, i16 } -%struct.NumberIterator.0 = type { i64, i64, i64 } +%struct.NumberIterator = type { %interface.Iterable.1, i16, i16, i16 } +%interface.Iterable.1 = type { ptr } +%struct.NumberIterator.2 = type { %interface.Iterable.1, i64, i64, i64 } @printf.str.0 = private unnamed_addr constant [10 x i8] c"Short %d\0A\00", align 1 @printf.str.1 = private unnamed_addr constant [9 x i8] c"Long %d\0A\00", align 1 @@ -13,22 +14,26 @@ target triple = "x86_64-w64-windows-gnu" ; Function Attrs: noinline nounwind optnone uwtable define dso_local i32 @main() local_unnamed_addr #0 { %shortIterator = alloca %struct.NumberIterator, align 8 - %1 = alloca %struct.NumberIterator.0, align 8 + %1 = alloca %struct.NumberIterator.2, align 8 %2 = tail call %struct.NumberIterator @_Z5rangess(i16 3, i16 8) #2 - %.fca.0.extract2 = extractvalue %struct.NumberIterator %2, 0 - store i16 %.fca.0.extract2, ptr %shortIterator, align 8 + %.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 %.fca.1.gep5 = getelementptr inbounds %struct.NumberIterator, ptr %shortIterator, i64 0, i32 1 - store i16 %.fca.1.extract4, ptr %.fca.1.gep5, align 2 + store i16 %.fca.1.extract4, ptr %.fca.1.gep5, align 8 %.fca.2.extract6 = extractvalue %struct.NumberIterator %2, 2 %.fca.2.gep7 = getelementptr inbounds %struct.NumberIterator, ptr %shortIterator, i64 0, i32 2 - store i16 %.fca.2.extract6, ptr %.fca.2.gep7, align 4 + store i16 %.fca.2.extract6, ptr %.fca.2.gep7, align 2 + %.fca.3.extract8 = extractvalue %struct.NumberIterator %2, 3 + %.fca.3.gep9 = getelementptr inbounds %struct.NumberIterator, ptr %shortIterator, i64 0, i32 3 + store i16 %.fca.3.extract8, ptr %.fca.3.gep9, align 4 %3 = call i1 @_ZN14NumberIteratorIsE7isValidEv(ptr nonnull %shortIterator) #2 br i1 %3, label %foreach.body.L5.lr.ph, label %foreach.exit.L5 foreach.body.L5.lr.ph: ; preds = %0 - %.fca.1.gep = getelementptr inbounds %struct.NumberIterator.0, ptr %1, i64 0, i32 1 - %.fca.2.gep = getelementptr inbounds %struct.NumberIterator.0, ptr %1, i64 0, i32 2 + %.fca.1.gep = getelementptr inbounds %struct.NumberIterator.2, ptr %1, i64 0, i32 1 + %.fca.2.gep = getelementptr inbounds %struct.NumberIterator.2, ptr %1, i64 0, i32 2 + %.fca.3.gep = getelementptr inbounds %struct.NumberIterator.2, ptr %1, i64 0, i32 3 br label %foreach.body.L5 foreach.body.L5: ; preds = %foreach.body.L5.lr.ph, %foreach.tail.L5 @@ -41,13 +46,15 @@ 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.0 @_Z5rangell(i64 1, i64 2) #2 - %.fca.0.extract = extractvalue %struct.NumberIterator.0 %9, 0 - store i64 %.fca.0.extract, ptr %1, align 8 - %.fca.1.extract = extractvalue %struct.NumberIterator.0 %9, 1 + %9 = call %struct.NumberIterator.2 @_Z5rangell(i64 1, i64 2) #2 + %.fca.0.0.extract = extractvalue %struct.NumberIterator.2 %9, 0, 0 + store ptr %.fca.0.0.extract, ptr %1, align 8 + %.fca.1.extract = extractvalue %struct.NumberIterator.2 %9, 1 store i64 %.fca.1.extract, ptr %.fca.1.gep, align 8 - %.fca.2.extract = extractvalue %struct.NumberIterator.0 %9, 2 + %.fca.2.extract = extractvalue %struct.NumberIterator.2 %9, 2 store i64 %.fca.2.extract, ptr %.fca.2.gep, align 8 + %.fca.3.extract = extractvalue %struct.NumberIterator.2 %9, 3 + store i64 %.fca.3.extract, ptr %.fca.3.gep, align 8 %10 = call i1 @_ZN14NumberIteratorIlE7isValidEv(ptr nonnull %1) #2 br i1 %10, label %foreach.body.L8, label %foreach.tail.L5 @@ -76,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.0 @_Z5rangell(i64, i64) local_unnamed_addr +declare %struct.NumberIterator.2 @_Z5rangell(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 01fd34345..50bdad982 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 @@ -3,8 +3,9 @@ source_filename = "source.spice" target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-w64-windows-gnu" -%struct.NumberIterator = type { i16, i16, i16 } -%struct.NumberIterator.0 = type { i64, i64, i64 } +%struct.NumberIterator = type { %interface.Iterable.1, i16, i16, i16 } +%interface.Iterable.1 = type { ptr } +%struct.NumberIterator.2 = type { %interface.Iterable.1, i64, i64, i64 } @printf.str.0 = private unnamed_addr constant [10 x i8] c"Short %d\0A\00", align 1 @printf.str.1 = private unnamed_addr constant [9 x i8] c"Long %d\0A\00", align 1 @@ -15,12 +16,12 @@ define dso_local i32 @main() #0 { %result = alloca i32, align 4 %shortIterator = alloca %struct.NumberIterator, align 8 %s = alloca i16, align 2 - %1 = alloca %struct.NumberIterator.0, align 8 + %1 = alloca %struct.NumberIterator.2, align 8 %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) - store %struct.NumberIterator %3, ptr %shortIterator, align 2 + store %struct.NumberIterator %3, ptr %shortIterator, align 8 br label %foreach.head.L5 foreach.head.L5: ; preds = %foreach.tail.L5, %0 @@ -41,8 +42,8 @@ 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.0 @_Z5rangell(i64 1, i64 2) - store %struct.NumberIterator.0 %14, ptr %1, align 8 + %14 = call %struct.NumberIterator.2 @_Z5rangell(i64 1, i64 2) + store %struct.NumberIterator.2 %14, ptr %1, align 8 br label %foreach.head.L8 foreach.head.L8: ; preds = %foreach.tail.L8, %if.then.L7 @@ -86,7 +87,7 @@ declare ptr @_ZN14NumberIteratorIsE3getEv(ptr) ; Function Attrs: nofree nounwind declare noundef i32 @printf(ptr nocapture noundef readonly, ...) #1 -declare %struct.NumberIterator.0 @_Z5rangell(i64, i64) +declare %struct.NumberIterator.2 @_Z5rangell(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 c0e1e3383..ba0b8844a 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 @@ -3,8 +3,9 @@ source_filename = "source.spice" target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-w64-windows-gnu" -%struct.NumberIterator = type { i16, i16, i16 } -%struct.NumberIterator.0 = type { i64, i64, i64 } +%struct.NumberIterator = type { %interface.Iterable.1, i16, i16, i16 } +%interface.Iterable.1 = type { ptr } +%struct.NumberIterator.2 = type { %interface.Iterable.1, i64, i64, i64 } @printf.str.0 = private unnamed_addr constant [10 x i8] c"Short %d\0A\00", align 1 @printf.str.1 = private unnamed_addr constant [9 x i8] c"Long %d\0A\00", align 1 @@ -13,22 +14,26 @@ target triple = "x86_64-w64-windows-gnu" ; Function Attrs: noinline nounwind optnone uwtable define dso_local i32 @main() local_unnamed_addr #0 { %shortIterator = alloca %struct.NumberIterator, align 8 - %1 = alloca %struct.NumberIterator.0, align 8 + %1 = alloca %struct.NumberIterator.2, align 8 %2 = tail call %struct.NumberIterator @_Z5rangess(i16 3, i16 8) #2 - %.fca.0.extract2 = extractvalue %struct.NumberIterator %2, 0 - store i16 %.fca.0.extract2, ptr %shortIterator, align 8 + %.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 %.fca.1.gep5 = getelementptr inbounds %struct.NumberIterator, ptr %shortIterator, i64 0, i32 1 - store i16 %.fca.1.extract4, ptr %.fca.1.gep5, align 2 + store i16 %.fca.1.extract4, ptr %.fca.1.gep5, align 8 %.fca.2.extract6 = extractvalue %struct.NumberIterator %2, 2 %.fca.2.gep7 = getelementptr inbounds %struct.NumberIterator, ptr %shortIterator, i64 0, i32 2 - store i16 %.fca.2.extract6, ptr %.fca.2.gep7, align 4 + store i16 %.fca.2.extract6, ptr %.fca.2.gep7, align 2 + %.fca.3.extract8 = extractvalue %struct.NumberIterator %2, 3 + %.fca.3.gep9 = getelementptr inbounds %struct.NumberIterator, ptr %shortIterator, i64 0, i32 3 + store i16 %.fca.3.extract8, ptr %.fca.3.gep9, align 4 %3 = call i1 @_ZN14NumberIteratorIsE7isValidEv(ptr nonnull %shortIterator) #2 br i1 %3, label %foreach.body.L5.lr.ph, label %foreach.exit.L5 foreach.body.L5.lr.ph: ; preds = %0 - %.fca.1.gep = getelementptr inbounds %struct.NumberIterator.0, ptr %1, i64 0, i32 1 - %.fca.2.gep = getelementptr inbounds %struct.NumberIterator.0, ptr %1, i64 0, i32 2 + %.fca.1.gep = getelementptr inbounds %struct.NumberIterator.2, ptr %1, i64 0, i32 1 + %.fca.2.gep = getelementptr inbounds %struct.NumberIterator.2, ptr %1, i64 0, i32 2 + %.fca.3.gep = getelementptr inbounds %struct.NumberIterator.2, ptr %1, i64 0, i32 3 br label %foreach.body.L5 foreach.body.L5: ; preds = %foreach.body.L5.lr.ph, %foreach.tail.L5 @@ -41,13 +46,15 @@ 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.0 @_Z5rangell(i64 1, i64 2) #2 - %.fca.0.extract = extractvalue %struct.NumberIterator.0 %9, 0 - store i64 %.fca.0.extract, ptr %1, align 8 - %.fca.1.extract = extractvalue %struct.NumberIterator.0 %9, 1 + %9 = call %struct.NumberIterator.2 @_Z5rangell(i64 1, i64 2) #2 + %.fca.0.0.extract = extractvalue %struct.NumberIterator.2 %9, 0, 0 + store ptr %.fca.0.0.extract, ptr %1, align 8 + %.fca.1.extract = extractvalue %struct.NumberIterator.2 %9, 1 store i64 %.fca.1.extract, ptr %.fca.1.gep, align 8 - %.fca.2.extract = extractvalue %struct.NumberIterator.0 %9, 2 + %.fca.2.extract = extractvalue %struct.NumberIterator.2 %9, 2 store i64 %.fca.2.extract, ptr %.fca.2.gep, align 8 + %.fca.3.extract = extractvalue %struct.NumberIterator.2 %9, 3 + store i64 %.fca.3.extract, ptr %.fca.3.gep, align 8 %10 = call i1 @_ZN14NumberIteratorIlE7isValidEv(ptr nonnull %1) #2 br i1 %10, label %foreach.body.L8, label %foreach.tail.L5 @@ -76,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.0 @_Z5rangell(i64, i64) local_unnamed_addr +declare %struct.NumberIterator.2 @_Z5rangell(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 2e1da347c..b1bc81bb1 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 @@ -3,8 +3,9 @@ source_filename = "source.spice" target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-w64-windows-gnu" -%struct.NumberIterator = type { i16, i16, i16 } -%struct.NumberIterator.0 = type { i64, i64, i64 } +%struct.NumberIterator = type { %interface.Iterable.1, i16, i16, i16 } +%interface.Iterable.1 = type { ptr } +%struct.NumberIterator.2 = type { %interface.Iterable.1, i64, i64, i64 } @printf.str.0 = private unnamed_addr constant [10 x i8] c"Short %d\0A\00", align 1 @printf.str.1 = private unnamed_addr constant [9 x i8] c"Long %d\0A\00", align 1 @@ -15,12 +16,12 @@ define dso_local i32 @main() #0 { %result = alloca i32, align 4 %shortIterator = alloca %struct.NumberIterator, align 8 %s = alloca i16, align 2 - %1 = alloca %struct.NumberIterator.0, align 8 + %1 = alloca %struct.NumberIterator.2, align 8 %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) - store %struct.NumberIterator %3, ptr %shortIterator, align 2 + store %struct.NumberIterator %3, ptr %shortIterator, align 8 br label %foreach.head.L5 foreach.head.L5: ; preds = %foreach.tail.L5, %0 @@ -41,8 +42,8 @@ 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.0 @_Z5rangell(i64 1, i64 2) - store %struct.NumberIterator.0 %14, ptr %1, align 8 + %14 = call %struct.NumberIterator.2 @_Z5rangell(i64 1, i64 2) + store %struct.NumberIterator.2 %14, ptr %1, align 8 br label %foreach.head.L8 foreach.head.L8: ; preds = %foreach.tail.L8, %if.then.L7 @@ -86,7 +87,7 @@ declare ptr @_ZN14NumberIteratorIsE3getEv(ptr) ; Function Attrs: nofree nounwind declare noundef i32 @printf(ptr nocapture noundef readonly, ...) #1 -declare %struct.NumberIterator.0 @_Z5rangell(i64, i64) +declare %struct.NumberIterator.2 @_Z5rangell(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 ddd88099f..ba86524b5 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 @@ -3,7 +3,8 @@ source_filename = "source.spice" target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-w64-windows-gnu" -%struct.ArrayIterator = type { ptr, i64, i64 } +%struct.ArrayIterator = type { %interface.Iterable, ptr, i64, i64 } +%interface.Iterable = type { ptr } %struct.Pair = type { i64, ptr } @anon.array.0 = private unnamed_addr constant [7 x i32] [i32 1, i32 5, i32 4, i32 0, i32 12, i32 12345, i32 9] 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 1d1600157..8a31032aa 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 @@ -3,7 +3,8 @@ source_filename = "source.spice" target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-w64-windows-gnu" -%struct.ArrayIterator = type { ptr, i64, i64 } +%struct.ArrayIterator = type { %interface.Iterable, ptr, i64, i64 } +%interface.Iterable = type { ptr } @anon.array.0 = private unnamed_addr constant [7 x i32] [i32 1, i32 5, i32 4, i32 0, i32 12, i32 12345, i32 9] @printf.str.0 = private unnamed_addr constant [10 x i8] c"Item: %d\0A\00", align 1 diff --git a/test/test-files/irgenerator/function-pointers/success-basic/ir-code.ll b/test/test-files/irgenerator/function-pointers/success-basic/ir-code.ll index a2acd7980..fbaaa219e 100644 --- a/test/test-files/irgenerator/function-pointers/success-basic/ir-code.ll +++ b/test/test-files/irgenerator/function-pointers/success-basic/ir-code.ll @@ -22,13 +22,13 @@ define dso_local i32 @main() #0 { %2 = load { ptr, ptr }, ptr %fat.ptr, align 8 store { ptr, ptr } %2, ptr %testFct, align 8 %3 = getelementptr inbounds { ptr, ptr }, ptr %testFct, i32 0, i32 0 - %4 = load ptr, ptr %3, align 8 - %5 = call i32 %4() - store i32 %5, ptr %i, align 4 - %6 = load i32, ptr %i, align 4 - %7 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.0, i32 %6) - %8 = load i32, ptr %result, align 4 - ret i32 %8 + %fct = load ptr, ptr %3, align 8 + %4 = call i32 %fct() + 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) + %7 = load i32, ptr %result, align 4 + ret i32 %7 } ; Function Attrs: nofree nounwind 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 6891e5722..bdb549627 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 @@ -18,9 +18,9 @@ define private i32 @_Z6invokePFiPcE({ ptr, ptr } %0) { %fctPtr = alloca { ptr, ptr }, align 8 store { ptr, ptr } %0, ptr %fctPtr, align 8 %2 = getelementptr inbounds { ptr, ptr }, ptr %fctPtr, i32 0, i32 0 - %3 = load ptr, ptr %2, align 8 - %4 = call i32 %3(ptr @anon.string.0) - ret i32 %4 + %fct = load ptr, ptr %2, align 8 + %3 = call i32 %fct(ptr @anon.string.0) + ret i32 %3 } ; Function Attrs: noinline nounwind optnone uwtable 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 2c3ec0513..ab713a96f 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 @@ -22,9 +22,9 @@ define private i32 @_Z6invokePPPFiPcE(ptr %0) { %2 = getelementptr inbounds { ptr, ptr }, ptr %fctPtr, i32 0, i32 0 %3 = load ptr, ptr %2, align 8 %4 = load ptr, ptr %3, align 8 - %5 = load ptr, ptr %4, align 8 - %6 = call i32 %5(ptr @anon.string.0) - ret i32 %6 + %fct = load ptr, ptr %4, align 8 + %5 = call i32 %fct(ptr @anon.string.0) + ret i32 %5 } define private i32 @_Z6invokeRPFiPcE(ptr %0) { @@ -33,9 +33,9 @@ define private i32 @_Z6invokeRPFiPcE(ptr %0) { store ptr %0, ptr %fctPtr, align 8 %2 = getelementptr inbounds { ptr, ptr }, ptr %fctPtr, i32 0, i32 0 %3 = load ptr, ptr %2, align 8 - %4 = load ptr, ptr %3, align 8 - %5 = call i32 %4(ptr @anon.string.1) - ret i32 %5 + %fct = load ptr, ptr %3, align 8 + %4 = call i32 %fct(ptr @anon.string.1) + ret i32 %4 } ; Function Attrs: noinline nounwind optnone uwtable diff --git a/test/test-files/irgenerator/interfaces/success-basic-interface/disabled b/test/test-files/irgenerator/interfaces/success-basic-interface/disabled deleted file mode 100644 index e69de29bb..000000000 diff --git a/test/test-files/irgenerator/interfaces/success-basic-interface/ir-code.ll b/test/test-files/irgenerator/interfaces/success-basic-interface/ir-code.ll index d1e5d62cb..cc851eca1 100644 --- a/test/test-files/irgenerator/interfaces/success-basic-interface/ir-code.ll +++ b/test/test-files/irgenerator/interfaces/success-basic-interface/ir-code.ll @@ -3,57 +3,90 @@ source_filename = "source.spice" target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-w64-windows-gnu" -%__Car__bool = type { i1 } +%struct.Car = type { %interface.Driveable, i1 } +%interface.Driveable = type { ptr } +$_ZTS9Driveable = comdat any + +$_ZTI9Driveable = comdat any + +$_ZTV9Driveable = comdat any + +$_ZTS3Car = comdat any + +$_ZTI3Car = comdat any + +$_ZTV3Car = comdat any + +@_ZTV8TypeInfo = external global ptr +@_ZTS9Driveable = linkonce_odr dso_local constant [11 x i8] c"9Driveable\00", comdat, align 1 +@_ZTI9Driveable = linkonce_odr dso_local constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTV8TypeInfo, i64 2), ptr @_ZTS9Driveable }, comdat, align 8 +@_ZTV9Driveable = linkonce_odr dso_local unnamed_addr constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr @_ZTI9Driveable, ptr null, ptr null] }, comdat, align 8 +@_ZTS3Car = linkonce_odr dso_local constant [5 x i8] c"3Car\00", comdat, align 1 +@_ZTI3Car = linkonce_odr dso_local constant { ptr, ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTV8TypeInfo, i64 2), ptr @_ZTS3Car, ptr @_ZTI9Driveable }, comdat, align 8 +@_ZTV3Car = linkonce_odr dso_local unnamed_addr constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr @_ZTI3Car, ptr @_ZN3Car5driveEi, ptr @_ZN3Car9isDrivingEv] }, comdat, align 8 @printf.str.0 = private unnamed_addr constant [15 x i8] c"Is driving: %d\00", align 1 -define dso_local void @_mp__Car__void__ctor(ptr noundef nonnull %0) { +define dso_local void @_ZN3Car4ctorEv(ptr noundef nonnull align 8 dereferenceable(16) %0) { %this = alloca ptr, align 8 store ptr %0, ptr %this, align 8 %2 = load ptr, ptr %this, align 8 - %driving = getelementptr inbounds %__Car__bool, ptr %2, i32 0, i32 0 - store i1 false, ptr %driving, align 1 + store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV3Car, i32 0, i32 0, i32 2), ptr %2, align 8 + %3 = getelementptr inbounds %struct.Car, ptr %2, i32 0, i32 1 + store i1 false, ptr %3, align 1 + %4 = load ptr, ptr %this, align 8 + %driving_addr = getelementptr inbounds %struct.Car, ptr %4, i32 0, i32 1 + store i1 false, ptr %driving_addr, align 1 ret void } -define dso_local void @_mp__Car__void__drive__int(ptr noundef nonnull %0, i32 %1) { +define dso_local void @_ZN3Car5driveEi(ptr noundef nonnull align 8 dereferenceable(16) %0, i32 %1) { %this = alloca ptr, align 8 %param = alloca i32, align 4 store ptr %0, ptr %this, align 8 store i32 %1, ptr %param, align 4 %3 = load ptr, ptr %this, align 8 - %driving = getelementptr inbounds %__Car__bool, ptr %3, i32 0, i32 0 - store i1 true, ptr %driving, align 1 + %driving_addr = getelementptr inbounds %struct.Car, ptr %3, i32 0, i32 1 + store i1 true, ptr %driving_addr, align 1 ret void } -define dso_local i1 @_mf__Car__bool__isDriving(ptr noundef nonnull %0) { +define dso_local i1 @_ZN3Car9isDrivingEv(ptr noundef nonnull align 8 dereferenceable(16) %0) { %result = alloca i1, align 1 %this = alloca ptr, align 8 store ptr %0, ptr %this, align 8 %2 = load ptr, ptr %this, align 8 - %driving = getelementptr inbounds %__Car__bool, ptr %2, i32 0, i32 0 - %3 = load i1, ptr %driving, align 1 + %driving_addr = getelementptr inbounds %struct.Car, ptr %2, i32 0, i32 1 + %3 = load i1, ptr %driving_addr, align 1 ret i1 %3 } ; Function Attrs: noinline nounwind optnone uwtable define dso_local i32 @main() #0 { %result = alloca i32, align 4 - %1 = alloca %__Car__bool, align 8 - %car = alloca %__Car__bool, align 8 + %car = alloca %struct.Car, align 8 + %driveable = alloca ptr, align 8 store i32 0, ptr %result, align 4 - call void @_mp__Car__void__ctor(ptr %1) - %2 = load %__Car__bool, ptr %1, align 1 - store %__Car__bool %2, ptr %car, align 1 - call void @_mp__Car__void__drive__int(ptr %car, i32 12) - %3 = call i1 @_mf__Car__bool__isDriving(ptr %car) + call void @_ZN3Car4ctorEv(ptr noundef nonnull align 8 dereferenceable(16) %car) + store ptr %car, ptr %driveable, align 8 + %1 = load ptr, ptr %driveable, align 8 + %vtable.addr = load ptr, ptr %1, align 8 + %vfct.addr = getelementptr inbounds ptr, ptr %vtable.addr, i64 0 + %fct = load ptr, ptr %vfct.addr, align 8 + call void %fct(ptr noundef nonnull align 8 dereferenceable(8) %1, i32 12) + %2 = load ptr, ptr %driveable, align 8 + %vtable.addr1 = load ptr, ptr %2, align 8 + %vfct.addr2 = getelementptr inbounds ptr, ptr %vtable.addr1, i64 1 + %fct3 = load ptr, ptr %vfct.addr2, align 8 + %3 = call i1 %fct3(ptr noundef nonnull align 8 dereferenceable(8) %2) %4 = zext i1 %3 to i32 %5 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.0, i32 %4) %6 = load i32, ptr %result, align 4 ret i32 %6 } -declare i32 @printf(ptr noundef, ...) +; Function Attrs: nofree nounwind +declare noundef i32 @printf(ptr nocapture noundef readonly, ...) #1 attributes #0 = { noinline nounwind optnone uwtable } +attributes #1 = { nofree nounwind } diff --git a/test/test-files/irgenerator/interfaces/success-basic-interface/source.spice b/test/test-files/irgenerator/interfaces/success-basic-interface/source.spice index 6ccce62f9..e605fa283 100644 --- a/test/test-files/irgenerator/interfaces/success-basic-interface/source.spice +++ b/test/test-files/irgenerator/interfaces/success-basic-interface/source.spice @@ -20,7 +20,8 @@ public f Car.isDriving() { } f main() { - Driveable car = Car(); - car.drive(12); - printf("Is driving: %d", car.isDriving()); + Car car = Car(); + Driveable* driveable = &car; + driveable.drive(12); + printf("Is driving: %d", driveable.isDriving()); } \ No newline at end of file diff --git a/test/test-files/irgenerator/interfaces/success-generic-interfaces/ir-code.ll b/test/test-files/irgenerator/interfaces/success-generic-interfaces/ir-code.ll index 1b892e0e3..2727b285b 100644 --- a/test/test-files/irgenerator/interfaces/success-generic-interfaces/ir-code.ll +++ b/test/test-files/irgenerator/interfaces/success-generic-interfaces/ir-code.ll @@ -3,7 +3,8 @@ source_filename = "source.spice" target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-w64-windows-gnu" -%struct.Person = type { ptr, ptr, i32 } +%struct.Person = type { %interface.Compareable, ptr, ptr, i32 } +%interface.Compareable = type { ptr } $_ZTS11CompareableIlE = comdat any @@ -18,17 +19,17 @@ $_ZTI6Person = comdat any $_ZTV6Person = comdat any @_ZTV8TypeInfo = external global ptr -@_ZTS11CompareableIlE = linkonce_odr dso_local constant [12 x i8] c"Compareable\00", comdat, align 1 -@_ZTI11CompareableIlE = linkonce_odr dso_local constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTV8TypeInfo, i32 2), ptr @_ZTS11CompareableIlE }, comdat -@_ZTV11CompareableIlE = linkonce_odr dso_local constant { [2 x ptr] } { [2 x ptr] [ptr null, ptr @_ZTI11CompareableIlE] }, comdat -@_ZTS6Person = linkonce_odr dso_local constant [7 x i8] c"Person\00", comdat, align 1 -@_ZTI6Person = linkonce_odr dso_local constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTV8TypeInfo, i32 2), ptr @_ZTS6Person }, comdat -@_ZTV6Person = linkonce_odr dso_local constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr @_ZTI6Person, ptr null] }, comdat +@_ZTS11CompareableIlE = linkonce_odr dso_local constant [14 x i8] c"11Compareable\00", comdat, align 1 +@_ZTI11CompareableIlE = linkonce_odr dso_local constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTV8TypeInfo, i64 2), ptr @_ZTS11CompareableIlE }, comdat, align 8 +@_ZTV11CompareableIlE = linkonce_odr dso_local unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr @_ZTI11CompareableIlE, ptr null] }, comdat, align 8 +@_ZTS6Person = linkonce_odr dso_local constant [8 x i8] c"6Person\00", comdat, align 1 +@_ZTI6Person = linkonce_odr dso_local constant { ptr, ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTV8TypeInfo, i64 2), ptr @_ZTS6Person, ptr @_ZTI11CompareableIlE }, comdat, align 8 +@_ZTV6Person = linkonce_odr dso_local unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr @_ZTI6Person, ptr @_ZN6Person7compareERKlRKl] }, comdat, align 8 @anon.string.0 = private unnamed_addr constant [5 x i8] c"Mike\00", align 1 @anon.string.1 = private unnamed_addr constant [7 x i8] c"Miller\00", align 1 @printf.str.0 = private unnamed_addr constant [3 x i8] c"%d\00", align 1 -define private i32 @_ZN6Person7compareERKlRKl(ptr noundef nonnull align 8 dereferenceable(24) %0, ptr %1, ptr %2) { +define private i32 @_ZN6Person7compareERKlRKl(ptr noundef nonnull align 8 dereferenceable(32) %0, ptr %1, ptr %2) { %result = alloca i32, align 4 %this = alloca ptr, align 8 %a = alloca ptr, align 8 @@ -69,10 +70,10 @@ define dso_local i32 @main() #0 { %2 = alloca i64, align 8 %isEqual = alloca i1, align 1 store i32 0, ptr %result, align 4 - store %struct.Person { ptr @anon.string.0, ptr @anon.string.1, i32 43 }, ptr %mike, align 8 + store %struct.Person { %interface.Compareable zeroinitializer, ptr @anon.string.0, ptr @anon.string.1, i32 43 }, ptr %mike, align 8 store i64 22, ptr %1, align 8 store i64 22, ptr %2, align 8 - %3 = call i32 @_ZN6Person7compareERKlRKl(ptr %mike, ptr %1, ptr %2) + %3 = call i32 @_ZN6Person7compareERKlRKl(ptr noundef nonnull align 8 dereferenceable(32) %mike, ptr %1, ptr %2) %4 = icmp eq i32 %3, 1 store i1 %4, ptr %isEqual, align 1 %5 = load i1, ptr %isEqual, align 1 diff --git a/test/test-files/irgenerator/lambdas/success-captures/ir-code.ll b/test/test-files/irgenerator/lambdas/success-captures/ir-code.ll index 6d470aca3..d29e21d41 100644 --- a/test/test-files/irgenerator/lambdas/success-captures/ir-code.ll +++ b/test/test-files/irgenerator/lambdas/success-captures/ir-code.ll @@ -54,44 +54,44 @@ define dso_local i32 @main() #0 { %15 = getelementptr inbounds { ptr, ptr }, ptr %foo1, i32 0, i32 0 %16 = getelementptr inbounds { ptr, ptr }, ptr %foo1, i32 0, i32 1 %captures3 = load ptr, ptr %16, align 8 - %17 = load ptr, ptr %15, align 8 - call void %17(ptr %captures3, ptr %x) - %18 = load i32, ptr %x, align 4 - %19 = icmp eq i32 %18, 6 - br i1 %19, label %assert.exit.L13, label %assert.then.L13, !prof !0 + %fct = load ptr, ptr %15, align 8 + call void %fct(ptr %captures3, ptr %x) + %17 = load i32, ptr %x, align 4 + %18 = icmp eq i32 %17, 6 + br i1 %18, label %assert.exit.L13, label %assert.then.L13, !prof !0 assert.then.L13: ; preds = %0 - %20 = call i32 (ptr, ...) @printf(ptr @anon.string.0) + %19 = call i32 (ptr, ...) @printf(ptr @anon.string.0) call void @exit(i32 1) unreachable assert.exit.L13: ; preds = %0 - %21 = getelementptr inbounds { ptr, ptr }, ptr %foo2, i32 0, i32 0 - %22 = getelementptr inbounds { ptr, ptr }, ptr %foo2, i32 0, i32 1 - %captures4 = load ptr, ptr %22, align 8 - %23 = load ptr, ptr %21, align 8 - %24 = call i1 %23(ptr %captures4, ptr %x) - br i1 %24, label %assert.exit.L14, label %assert.then.L14, !prof !0 + %20 = getelementptr inbounds { ptr, ptr }, ptr %foo2, i32 0, i32 0 + %21 = getelementptr inbounds { ptr, ptr }, ptr %foo2, i32 0, i32 1 + %captures4 = load ptr, ptr %21, align 8 + %fct5 = load ptr, ptr %20, align 8 + %22 = call i1 %fct5(ptr %captures4, ptr %x) + br i1 %22, label %assert.exit.L14, label %assert.then.L14, !prof !0 assert.then.L14: ; preds = %assert.exit.L13 - %25 = call i32 (ptr, ...) @printf(ptr @anon.string.1) + %23 = call i32 (ptr, ...) @printf(ptr @anon.string.1) call void @exit(i32 1) unreachable assert.exit.L14: ; preds = %assert.exit.L13 - %26 = load i32, ptr %x, align 4 - %27 = icmp eq i32 %26, 11 - br i1 %27, label %assert.exit.L15, label %assert.then.L15, !prof !0 + %24 = load i32, ptr %x, align 4 + %25 = icmp eq i32 %24, 11 + br i1 %25, label %assert.exit.L15, label %assert.then.L15, !prof !0 assert.then.L15: ; preds = %assert.exit.L14 - %28 = call i32 (ptr, ...) @printf(ptr @anon.string.2) + %26 = call i32 (ptr, ...) @printf(ptr @anon.string.2) call void @exit(i32 1) unreachable assert.exit.L15: ; preds = %assert.exit.L14 - %29 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.0) - %30 = load i32, ptr %result, align 4 - ret i32 %30 + %27 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.0) + %28 = load i32, ptr %result, align 4 + ret i32 %28 } define private void @_Z14lambda.L4C20.0Ri(ptr noundef nonnull dereferenceable(8) %0, ptr %1) { 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 197532696..e5eaace71 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 @@ -67,37 +67,37 @@ for.body.L9: ; preds = %for.head.L9 %20 = load ptr, ptr %array, align 8 %21 = getelementptr inbounds [10 x i32], ptr %20, i32 0, i32 %19 %22 = load i32, ptr %21, align 4 - %23 = load ptr, ptr %13, align 8 - %24 = call i1 %23(i32 %17, i32 %22) - br i1 %24, label %if.then.L10, label %if.exit.L10 + %fct = load ptr, ptr %13, align 8 + %23 = call i1 %fct(i32 %17, i32 %22) + br i1 %23, label %if.then.L10, label %if.exit.L10 if.then.L10: ; preds = %for.body.L9 - %25 = load i32, ptr %j, align 4 - %26 = load ptr, ptr %array, align 8 - %27 = getelementptr inbounds [10 x i32], ptr %26, i32 0, i32 %25 - %28 = load i32, ptr %j, align 4 - %29 = add i32 %28, 1 - %30 = load ptr, ptr %array, align 8 - %31 = getelementptr inbounds [10 x i32], ptr %30, i32 0, i32 %29 - call void @_Z4swapRiRi(ptr %27, ptr %31) + %24 = load i32, ptr %j, align 4 + %25 = load ptr, ptr %array, align 8 + %26 = getelementptr inbounds [10 x i32], ptr %25, i32 0, i32 %24 + %27 = load i32, ptr %j, align 4 + %28 = add i32 %27, 1 + %29 = load ptr, ptr %array, align 8 + %30 = getelementptr inbounds [10 x i32], ptr %29, i32 0, i32 %28 + call void @_Z4swapRiRi(ptr %26, ptr %30) br label %if.exit.L10 if.exit.L10: ; preds = %if.then.L10, %for.body.L9 br label %for.tail.L9 for.tail.L9: ; preds = %if.exit.L10 - %32 = load i32, ptr %j, align 4 - %33 = add i32 %32, 1 - store i32 %33, ptr %j, align 4 + %31 = load i32, ptr %j, align 4 + %32 = add i32 %31, 1 + store i32 %32, ptr %j, align 4 br label %for.head.L9 for.exit.L9: ; preds = %for.head.L9 br label %for.tail.L8 for.tail.L8: ; preds = %for.exit.L9 - %34 = load i32, ptr %i, align 4 - %35 = add i32 %34, 1 - store i32 %35, ptr %i, align 4 + %33 = load i32, ptr %i, align 4 + %34 = add i32 %33, 1 + store i32 %34, ptr %i, align 4 br label %for.head.L8 for.exit.L8: ; preds = %for.head.L8 diff --git a/test/test-files/irgenerator/lambdas/success-foreign-captures/ir-code.ll b/test/test-files/irgenerator/lambdas/success-foreign-captures/ir-code.ll index 657b07fb1..a23b01837 100644 --- a/test/test-files/irgenerator/lambdas/success-foreign-captures/ir-code.ll +++ b/test/test-files/irgenerator/lambdas/success-foreign-captures/ir-code.ll @@ -21,37 +21,37 @@ define private void @_Z4testPFCvRiEPFCbRiE({ ptr, ptr } %0, { ptr, ptr } %1) { %3 = getelementptr inbounds { ptr, ptr }, ptr %l1, i32 0, i32 0 %4 = getelementptr inbounds { ptr, ptr }, ptr %l1, i32 0, i32 1 %captures = load ptr, ptr %4, align 8 - %5 = load ptr, ptr %3, align 8 - call void %5(ptr %captures, ptr %x) - %6 = load i32, ptr %x, align 4 - %7 = icmp eq i32 %6, 6 - br i1 %7, label %assert.exit.L4, label %assert.then.L4, !prof !0 + %fct = load ptr, ptr %3, align 8 + call void %fct(ptr %captures, ptr %x) + %5 = load i32, ptr %x, align 4 + %6 = icmp eq i32 %5, 6 + br i1 %6, label %assert.exit.L4, label %assert.then.L4, !prof !0 assert.then.L4: ; preds = %2 - %8 = call i32 (ptr, ...) @printf(ptr @anon.string.0) + %7 = call i32 (ptr, ...) @printf(ptr @anon.string.0) call void @exit(i32 1) unreachable assert.exit.L4: ; preds = %2 - %9 = getelementptr inbounds { ptr, ptr }, ptr %l2, i32 0, i32 0 - %10 = getelementptr inbounds { ptr, ptr }, ptr %l2, i32 0, i32 1 - %captures1 = load ptr, ptr %10, align 8 - %11 = load ptr, ptr %9, align 8 - %12 = call i1 %11(ptr %captures1, ptr %x) - br i1 %12, label %assert.exit.L5, label %assert.then.L5, !prof !0 + %8 = getelementptr inbounds { ptr, ptr }, ptr %l2, i32 0, i32 0 + %9 = getelementptr inbounds { ptr, ptr }, ptr %l2, i32 0, i32 1 + %captures1 = load ptr, ptr %9, align 8 + %fct2 = load ptr, ptr %8, align 8 + %10 = call i1 %fct2(ptr %captures1, ptr %x) + br i1 %10, label %assert.exit.L5, label %assert.then.L5, !prof !0 assert.then.L5: ; preds = %assert.exit.L4 - %13 = call i32 (ptr, ...) @printf(ptr @anon.string.1) + %11 = call i32 (ptr, ...) @printf(ptr @anon.string.1) call void @exit(i32 1) unreachable assert.exit.L5: ; preds = %assert.exit.L4 - %14 = load i32, ptr %x, align 4 - %15 = icmp eq i32 %14, 11 - br i1 %15, label %assert.exit.L6, label %assert.then.L6, !prof !0 + %12 = load i32, ptr %x, align 4 + %13 = icmp eq i32 %12, 11 + br i1 %13, label %assert.exit.L6, label %assert.then.L6, !prof !0 assert.then.L6: ; preds = %assert.exit.L5 - %16 = call i32 (ptr, ...) @printf(ptr @anon.string.2) + %14 = call i32 (ptr, ...) @printf(ptr @anon.string.2) call void @exit(i32 1) unreachable 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 8ceba0f4a..27035a251 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 @@ -23,7 +23,7 @@ define dso_local i32 @main() #0 { %fat.ptr1 = alloca { ptr, ptr }, align 8 %callbackWithArgs1 = alloca { ptr, ptr }, align 8 %1 = alloca %struct.String, align 8 - %fat.ptr2 = alloca { ptr, ptr }, align 8 + %fat.ptr3 = alloca { ptr, ptr }, align 8 %callbackWithArgs2 = alloca { ptr, ptr }, align 8 %2 = alloca %struct.String, align 8 store i32 0, ptr %result, align 4 @@ -32,37 +32,37 @@ define dso_local i32 @main() #0 { %4 = load { ptr, ptr }, ptr %fat.ptr, align 8 store { ptr, ptr } %4, ptr %callbackWithoutArgs, align 8 %5 = getelementptr inbounds { ptr, ptr }, ptr %callbackWithoutArgs, i32 0, i32 0 - %6 = load ptr, ptr %5, align 8 - %7 = call ptr %6() - %8 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.0, ptr %7) - %9 = getelementptr inbounds { ptr, ptr }, ptr %fat.ptr1, i32 0, i32 0 - store ptr @_Z14lambda.L7C50.0RN11__rt_string6StringEd, ptr %9, align 8 - %10 = load { ptr, ptr }, ptr %fat.ptr1, align 8 - store { ptr, ptr } %10, ptr %callbackWithArgs1, align 8 - %11 = getelementptr inbounds { ptr, ptr }, ptr %callbackWithArgs1, i32 0, i32 0 - call void @_ZN6String4ctorEPc(ptr %1, ptr @anon.string.2) - %12 = load ptr, ptr %11, align 8 - %13 = call i1 %12(ptr %1, double 3.140000e+00) - %14 = zext i1 %13 to i32 - %15 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.2, i32 %14) - %16 = getelementptr inbounds { ptr, ptr }, ptr %fat.ptr2, i32 0, i32 0 - store ptr @_Z15lambda.L13C49.0N11__rt_string6StringEs, ptr %16, align 8 - %17 = load { ptr, ptr }, ptr %fat.ptr2, align 8 - store { ptr, ptr } %17, ptr %callbackWithArgs2, align 8 - %18 = getelementptr inbounds { ptr, ptr }, ptr %callbackWithArgs2, i32 0, i32 0 - call void @_ZN6String4ctorEPc(ptr %2, ptr @anon.string.3) - %19 = load %struct.String, ptr %2, align 8 - %20 = load ptr, ptr %18, align 8 - %21 = call i16 %20(%struct.String %19, i16 321) - %22 = xor i16 %21, 956 - %23 = sext i16 %22 to i32 - %24 = icmp eq i32 %23, 1 - %25 = select i1 %24, i32 9, i32 12 - %26 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.4, i32 %25) + %fct = load ptr, ptr %5, align 8 + %6 = call ptr %fct() + %7 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.0, ptr %6) + %8 = getelementptr inbounds { ptr, ptr }, ptr %fat.ptr1, i32 0, i32 0 + store ptr @_Z14lambda.L7C50.0RN11__rt_string6StringEd, ptr %8, align 8 + %9 = load { ptr, ptr }, ptr %fat.ptr1, align 8 + store { ptr, ptr } %9, ptr %callbackWithArgs1, align 8 + %10 = getelementptr inbounds { ptr, ptr }, ptr %callbackWithArgs1, i32 0, i32 0 + call void @_ZN6String4ctorEPc(ptr noundef nonnull align 8 dereferenceable(24) %1, ptr @anon.string.2) + %fct2 = load ptr, ptr %10, align 8 + %11 = call i1 %fct2(ptr %1, double 3.140000e+00) + %12 = zext i1 %11 to i32 + %13 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.2, i32 %12) + %14 = getelementptr inbounds { ptr, ptr }, ptr %fat.ptr3, i32 0, i32 0 + store ptr @_Z15lambda.L13C49.0N11__rt_string6StringEs, ptr %14, align 8 + %15 = load { ptr, ptr }, ptr %fat.ptr3, align 8 + store { ptr, ptr } %15, ptr %callbackWithArgs2, align 8 + %16 = getelementptr inbounds { ptr, ptr }, ptr %callbackWithArgs2, i32 0, i32 0 + call void @_ZN6String4ctorEPc(ptr noundef nonnull align 8 dereferenceable(24) %2, ptr @anon.string.3) + %17 = load %struct.String, ptr %2, align 8 + %fct4 = load ptr, ptr %16, align 8 + %18 = call i16 %fct4(%struct.String %17, i16 321) + %19 = xor i16 %18, 956 + %20 = sext i16 %19 to i32 + %21 = icmp eq i32 %20, 1 + %22 = select i1 %21, i32 9, i32 12 + %23 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.4, i32 %22) call void @_ZN6String4dtorEv(ptr %2) call void @_ZN6String4dtorEv(ptr %1) - %27 = load i32, ptr %result, align 4 - ret i32 %27 + %24 = load i32, ptr %result, align 4 + ret i32 %24 } define private ptr @_Z14lambda.L2C39.0v() { @@ -85,7 +85,7 @@ define private i1 @_Z14lambda.L7C50.0RN11__rt_string6StringEd(ptr %0, double %1) %6 = load double, ptr %d, align 8 %7 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.1, ptr %5, double %6) %8 = load ptr, ptr %str, align 8 - %9 = call ptr @_ZN6String6getRawEv(ptr %8) + %9 = call ptr @_ZN6String6getRawEv(ptr noundef nonnull align 8 dereferenceable(8) %8) %10 = call i1 @_Z10isRawEqualPcPc(ptr %9, ptr @anon.string.1) br i1 %10, label %land.1.L9C16, label %land.exit.L9C16 diff --git a/test/test-files/irgenerator/lambdas/success-multiple-visits/ir-code.ll b/test/test-files/irgenerator/lambdas/success-multiple-visits/ir-code.ll index 7a8974e65..7de2ca2dd 100644 --- a/test/test-files/irgenerator/lambdas/success-multiple-visits/ir-code.ll +++ b/test/test-files/irgenerator/lambdas/success-multiple-visits/ir-code.ll @@ -32,8 +32,8 @@ define private void @_Z4testv() { %8 = getelementptr inbounds { ptr, ptr }, ptr %l, i32 0, i32 0 %9 = getelementptr inbounds { ptr, ptr }, ptr %l, i32 0, i32 1 %captures1 = load ptr, ptr %9, align 8 - %10 = load ptr, ptr %8, align 8 - call void %10(ptr %captures1) + %fct = load ptr, ptr %8, align 8 + call void %fct(ptr %captures1) ret void } @@ -75,8 +75,8 @@ define private void @_Z4testi(i32 %0) { %9 = getelementptr inbounds { ptr, ptr }, ptr %l, i32 0, i32 0 %10 = getelementptr inbounds { ptr, ptr }, ptr %l, i32 0, i32 1 %captures1 = load ptr, ptr %10, align 8 - %11 = load ptr, ptr %9, align 8 - call void %11(ptr %captures1) + %fct = load ptr, ptr %9, align 8 + call void %fct(ptr %captures1) ret void } 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 26780723a..6924d8a16 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 @@ -19,7 +19,7 @@ define dso_local i32 @main() #0 { %fat.ptr1 = alloca { ptr, ptr }, align 8 %callbackWithArgs1 = alloca { ptr, ptr }, align 8 %1 = alloca %struct.String, align 8 - %fat.ptr2 = alloca { ptr, ptr }, align 8 + %fat.ptr3 = alloca { ptr, ptr }, align 8 %callbackWithArgs2 = alloca { ptr, ptr }, align 8 %2 = alloca %struct.String, align 8 store i32 0, ptr %result, align 4 @@ -28,29 +28,29 @@ define dso_local i32 @main() #0 { %4 = load { ptr, ptr }, ptr %fat.ptr, align 8 store { ptr, ptr } %4, ptr %callbackWithoutArgs, align 8 %5 = getelementptr inbounds { ptr, ptr }, ptr %callbackWithoutArgs, i32 0, i32 0 - %6 = load ptr, ptr %5, align 8 - call void %6() - %7 = getelementptr inbounds { ptr, ptr }, ptr %fat.ptr1, i32 0, i32 0 - store ptr @_Z14lambda.L7C44.0RN11__rt_string6StringEd, ptr %7, align 8 - %8 = load { ptr, ptr }, ptr %fat.ptr1, align 8 - store { ptr, ptr } %8, ptr %callbackWithArgs1, align 8 - %9 = getelementptr inbounds { ptr, ptr }, ptr %callbackWithArgs1, i32 0, i32 0 - call void @_ZN6String4ctorEPc(ptr %1, ptr @anon.string.0) - %10 = load ptr, ptr %9, align 8 - call void %10(ptr %1, double 3.140000e+00) - %11 = getelementptr inbounds { ptr, ptr }, ptr %fat.ptr2, i32 0, i32 0 - store ptr @_Z15lambda.L12C41.0N11__rt_string6StringEb, ptr %11, align 8 - %12 = load { ptr, ptr }, ptr %fat.ptr2, align 8 - store { ptr, ptr } %12, ptr %callbackWithArgs2, align 8 - %13 = getelementptr inbounds { ptr, ptr }, ptr %callbackWithArgs2, i32 0, i32 0 - call void @_ZN6String4ctorEPc(ptr %2, ptr @anon.string.1) - %14 = load %struct.String, ptr %2, align 8 - %15 = load ptr, ptr %13, align 8 - call void %15(%struct.String %14, i1 false) + %fct = load ptr, ptr %5, align 8 + call void %fct() + %6 = getelementptr inbounds { ptr, ptr }, ptr %fat.ptr1, i32 0, i32 0 + store ptr @_Z14lambda.L7C44.0RN11__rt_string6StringEd, ptr %6, align 8 + %7 = load { ptr, ptr }, ptr %fat.ptr1, align 8 + store { ptr, ptr } %7, ptr %callbackWithArgs1, align 8 + %8 = getelementptr inbounds { ptr, ptr }, ptr %callbackWithArgs1, i32 0, i32 0 + call void @_ZN6String4ctorEPc(ptr noundef nonnull align 8 dereferenceable(24) %1, ptr @anon.string.0) + %fct2 = load ptr, ptr %8, align 8 + call void %fct2(ptr %1, double 3.140000e+00) + %9 = getelementptr inbounds { ptr, ptr }, ptr %fat.ptr3, i32 0, i32 0 + store ptr @_Z15lambda.L12C41.0N11__rt_string6StringEb, ptr %9, align 8 + %10 = load { ptr, ptr }, ptr %fat.ptr3, align 8 + store { ptr, ptr } %10, ptr %callbackWithArgs2, align 8 + %11 = getelementptr inbounds { ptr, ptr }, ptr %callbackWithArgs2, i32 0, i32 0 + call void @_ZN6String4ctorEPc(ptr noundef nonnull align 8 dereferenceable(24) %2, ptr @anon.string.1) + %12 = load %struct.String, ptr %2, align 8 + %fct4 = load ptr, ptr %11, align 8 + call void %fct4(%struct.String %12, i1 false) call void @_ZN6String4dtorEv(ptr %2) call void @_ZN6String4dtorEv(ptr %1) - %16 = load i32, ptr %result, align 4 - ret i32 %16 + %13 = load i32, ptr %result, align 4 + ret i32 %13 } define private void @_Z14lambda.L2C31.0v() { diff --git a/test/test-files/irgenerator/methods/success-method-call-on-return-value/ir-code.ll b/test/test-files/irgenerator/methods/success-method-call-on-return-value/ir-code.ll index 363cfeb14..2e5b8c2b6 100644 --- a/test/test-files/irgenerator/methods/success-method-call-on-return-value/ir-code.ll +++ b/test/test-files/irgenerator/methods/success-method-call-on-return-value/ir-code.ll @@ -49,9 +49,9 @@ define dso_local i32 @main() #1 { %1 = load i1, ptr %glued_addr, align 1 %2 = zext i1 %1 to i32 %3 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.1, i32 %2) - %4 = call %struct.Stamp @_ZN6Letter8getStampEv(ptr %letter) + %4 = call %struct.Stamp @_ZN6Letter8getStampEv(ptr noundef nonnull align 8 dereferenceable(24) %letter) store %struct.Stamp %4, ptr %stamp, align 8 - call void @_ZN5Stamp5printEv(ptr %stamp) + call void @_ZN5Stamp5printEv(ptr noundef nonnull align 8 dereferenceable(16) %stamp) %5 = load i32, ptr %result, align 4 ret i32 %5 } diff --git a/test/test-files/irgenerator/methods/success-method-down-up-call/ir-code.ll b/test/test-files/irgenerator/methods/success-method-down-up-call/ir-code.ll index cf57e3087..f6f2d5e87 100644 --- a/test/test-files/irgenerator/methods/success-method-down-up-call/ir-code.ll +++ b/test/test-files/irgenerator/methods/success-method-down-up-call/ir-code.ll @@ -13,7 +13,7 @@ define dso_local i32 @main() #0 { %s = alloca %struct.TestStruct, align 8 store i32 0, ptr %result, align 4 store %struct.TestStruct { i8 97, i32 1 }, ptr %s, align 4 - call void @_ZN10TestStructIhE9printTestEv(ptr %s) + call void @_ZN10TestStructIhE9printTestEv(ptr noundef nonnull align 4 dereferenceable(8) %s) %1 = load i32, ptr %result, align 4 ret i32 %1 } @@ -22,7 +22,7 @@ define private void @_ZN10TestStructIhE9printTestEv(ptr noundef nonnull align 4 %this = alloca ptr, align 8 store ptr %0, ptr %this, align 8 %2 = load ptr, ptr %this, align 8 - %3 = call i32 @_ZN10TestStructIhE7getTestEv(ptr %2) + %3 = call i32 @_ZN10TestStructIhE7getTestEv(ptr noundef nonnull align 8 dereferenceable(8) %2) %4 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.0, i32 %3) ret void } @@ -47,7 +47,7 @@ if.then.L18: ; preds = %1 %7 = add i32 %6, 1 store i32 %7, ptr %test_addr1, align 4 %8 = load ptr, ptr %this, align 8 - call void @_ZN10TestStructIhE9printTestEv(ptr %8) + call void @_ZN10TestStructIhE9printTestEv(ptr noundef nonnull align 8 dereferenceable(8) %8) br label %if.exit.L18 if.exit.L18: ; preds = %if.then.L18, %1 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 bebb4d7e9..542096d76 100644 --- a/test/test-files/irgenerator/methods/success-methods/ir-code.ll +++ b/test/test-files/irgenerator/methods/success-methods/ir-code.ll @@ -37,8 +37,8 @@ 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 %letter, ptr @anon.string.1) - %1 = call ptr @_ZN6Letter10getContentEv(ptr %letter) + call void @_ZN6Letter10setContentEPc(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 ret i32 %3 diff --git a/test/test-files/irgenerator/operators/success-operator-overloading-binary/ir-code.ll b/test/test-files/irgenerator/operators/success-operator-overloading-binary/ir-code.ll index e21051b33..b78e8508f 100644 --- a/test/test-files/irgenerator/operators/success-operator-overloading-binary/ir-code.ll +++ b/test/test-files/irgenerator/operators/success-operator-overloading-binary/ir-code.ll @@ -14,11 +14,13 @@ define private void @_ZN7Counter4ctorEl(ptr noundef nonnull align 8 dereferencea %initialValue = alloca i64, align 8 store ptr %0, ptr %this, align 8 store i64 %1, ptr %initialValue, align 8 - store %struct.Counter zeroinitializer, ptr %0, align 8 %3 = load ptr, ptr %this, align 8 - %value_addr = getelementptr inbounds %struct.Counter, ptr %3, i32 0, i32 0 - %4 = load i64, ptr %initialValue, align 8 - store i64 %4, ptr %value_addr, align 8 + %4 = getelementptr inbounds %struct.Counter, ptr %3, i32 0, i32 0 + store i64 0, ptr %4, align 8 + %5 = load ptr, ptr %this, align 8 + %value_addr = getelementptr inbounds %struct.Counter, ptr %5, i32 0, i32 0 + %6 = load i64, ptr %initialValue, align 8 + store i64 %6, ptr %value_addr, align 8 ret void } @@ -44,7 +46,7 @@ define private %struct.Counter @_Z7op.plus7Counter7Counter(%struct.Counter %0, % %4 = load i64, ptr %value_addr1, align 8 %5 = load i64, ptr %value_addr, align 8 %6 = add i64 %5, %4 - call void @_ZN7Counter4ctorEl(ptr %3, i64 %6) + call void @_ZN7Counter4ctorEl(ptr noundef nonnull align 8 dereferenceable(8) %3, i64 %6) %7 = load %struct.Counter, ptr %3, align 8 ret %struct.Counter %7 } @@ -56,17 +58,17 @@ define dso_local i32 @main() #0 { %counter2 = alloca %struct.Counter, align 8 %counter3 = alloca %struct.Counter, align 8 store i32 0, ptr %result, align 4 - call void @_ZN7Counter4ctorEl(ptr %counter1, i64 2) - call void @_ZN7Counter4ctorEl(ptr %counter2, i64 3) - %1 = call i64 @_ZN7Counter8getValueEv(ptr %counter1) + call void @_ZN7Counter4ctorEl(ptr noundef nonnull align 8 dereferenceable(8) %counter1, i64 2) + call void @_ZN7Counter4ctorEl(ptr noundef nonnull align 8 dereferenceable(8) %counter2, i64 3) + %1 = call i64 @_ZN7Counter8getValueEv(ptr noundef nonnull align 8 dereferenceable(8) %counter1) %2 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.0, i64 %1) - %3 = call i64 @_ZN7Counter8getValueEv(ptr %counter2) + %3 = call i64 @_ZN7Counter8getValueEv(ptr noundef nonnull align 8 dereferenceable(8) %counter2) %4 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.1, i64 %3) %5 = load %struct.Counter, ptr %counter1, align 8 %6 = load %struct.Counter, ptr %counter2, align 8 %7 = call %struct.Counter @_Z7op.plus7Counter7Counter(%struct.Counter %5, %struct.Counter %6) store %struct.Counter %7, ptr %counter3, align 8 - %8 = call i64 @_ZN7Counter8getValueEv(ptr %counter3) + %8 = call i64 @_ZN7Counter8getValueEv(ptr noundef nonnull align 8 dereferenceable(8) %counter3) %9 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.2, i64 %8) %10 = load i32, ptr %result, align 4 ret i32 %10 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 fe7e3297d..b5c821c72 100644 --- a/test/test-files/irgenerator/structs/success-constructors/ir-code.ll +++ b/test/test-files/irgenerator/structs/success-constructors/ir-code.ll @@ -19,14 +19,18 @@ define private void @_ZN6Vector4ctorEv(ptr noundef nonnull align 8 dereferenceab %msg = alloca ptr, align 8 store ptr %0, ptr %this, align 8 store ptr @anon.string.0, ptr %msg, align 8 - store %struct.Vector { i1 false, ptr @0 }, ptr %0, align 8 %2 = load ptr, ptr %this, align 8 - %field1_addr = getelementptr inbounds %struct.Vector, ptr %2, i32 0, i32 0 + %3 = getelementptr inbounds %struct.Vector, ptr %2, i32 0, i32 0 + store i1 false, ptr %3, align 1 + %4 = getelementptr inbounds %struct.Vector, ptr %2, i32 0, i32 1 + store ptr @0, ptr %4, align 8 + %5 = load ptr, ptr %this, align 8 + %field1_addr = getelementptr inbounds %struct.Vector, ptr %5, i32 0, i32 0 store i1 false, ptr %field1_addr, align 1 - %3 = load ptr, ptr %this, align 8 - %field2_addr = getelementptr inbounds %struct.Vector, ptr %3, i32 0, i32 1 - %4 = load ptr, ptr %msg, align 8 - store ptr %4, ptr %field2_addr, align 8 + %6 = load ptr, ptr %this, align 8 + %field2_addr = getelementptr inbounds %struct.Vector, ptr %6, i32 0, i32 1 + %7 = load ptr, ptr %msg, align 8 + store ptr %7, ptr %field2_addr, align 8 ret void } @@ -35,14 +39,18 @@ define private void @_ZN6Vector4ctorEPc(ptr noundef nonnull align 8 dereferencea %msg = alloca ptr, align 8 store ptr %0, ptr %this, align 8 store ptr %1, ptr %msg, align 8 - store %struct.Vector { i1 false, ptr @1 }, ptr %0, align 8 %3 = load ptr, ptr %this, align 8 - %field1_addr = getelementptr inbounds %struct.Vector, ptr %3, i32 0, i32 0 + %4 = getelementptr inbounds %struct.Vector, ptr %3, i32 0, i32 0 + store i1 false, ptr %4, align 1 + %5 = getelementptr inbounds %struct.Vector, ptr %3, i32 0, i32 1 + store ptr @1, ptr %5, align 8 + %6 = load ptr, ptr %this, align 8 + %field1_addr = getelementptr inbounds %struct.Vector, ptr %6, i32 0, i32 0 store i1 false, ptr %field1_addr, align 1 - %4 = load ptr, ptr %this, align 8 - %field2_addr = getelementptr inbounds %struct.Vector, ptr %4, i32 0, i32 1 - %5 = load ptr, ptr %msg, align 8 - store ptr %5, ptr %field2_addr, align 8 + %7 = load ptr, ptr %this, align 8 + %field2_addr = getelementptr inbounds %struct.Vector, ptr %7, i32 0, i32 1 + %8 = load ptr, ptr %msg, align 8 + store ptr %8, ptr %field2_addr, align 8 ret void } @@ -59,14 +67,14 @@ define dso_local i32 @main() #0 { %vec = alloca %struct.Vector, align 8 %1 = alloca %struct.Vector, align 8 store i32 0, ptr %result, align 4 - call void @_ZN6Vector4ctorEv(ptr %vec) + call void @_ZN6Vector4ctorEv(ptr noundef nonnull align 8 dereferenceable(16) %vec) %field1_addr = getelementptr inbounds %struct.Vector, ptr %vec, i32 0, i32 0 %2 = load i1, ptr %field1_addr, align 1 %3 = zext i1 %2 to i32 %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 %1, ptr @anon.string.2) + call void @_ZN6Vector4ctorEPc(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 @@ -75,7 +83,7 @@ define dso_local i32 @main() #0 { %field2_addr2 = getelementptr inbounds %struct.Vector, ptr %vec, i32 0, i32 1 %9 = load ptr, ptr %field2_addr2, align 8 %10 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.1, i32 %8, ptr %9) - %11 = call ptr @_ZN6Vector4testEv(ptr %vec) + %11 = call ptr @_ZN6Vector4testEv(ptr noundef nonnull align 8 dereferenceable(16) %vec) %12 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.2, ptr %11) %13 = load i32, ptr %result, align 4 ret i32 %13 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 86591e07b..4eeff4824 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 @@ -15,14 +15,16 @@ define private void @_ZN5Inner4ctorERK5Inner(ptr noundef nonnull align 2 derefer %other = alloca ptr, align 8 store ptr %0, ptr %this, align 8 store ptr %1, ptr %other, align 8 - store %struct.Inner { i16 -43 }, ptr %0, align 2 %3 = load ptr, ptr %this, align 8 - %x_addr = getelementptr inbounds %struct.Inner, ptr %3, i32 0, i32 0 - %4 = load ptr, ptr %other, align 8 - %x_addr1 = getelementptr inbounds %struct.Inner, ptr %4, i32 0, i32 0 - %5 = load i16, ptr %x_addr1, align 2 - %6 = add i16 %5, 5 - store i16 %6, ptr %x_addr, align 2 + %4 = getelementptr inbounds %struct.Inner, ptr %3, i32 0, i32 0 + store i16 -43, ptr %4, align 2 + %5 = load ptr, ptr %this, align 8 + %x_addr = getelementptr inbounds %struct.Inner, ptr %5, i32 0, i32 0 + %6 = load ptr, ptr %other, align 8 + %x_addr1 = getelementptr inbounds %struct.Inner, ptr %6, i32 0, i32 0 + %7 = load i16, ptr %x_addr1, align 2 + %8 = add i16 %7, 5 + store i16 %8, ptr %x_addr, align 2 ret void } 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 f507988e0..00d360e84 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 @@ -18,11 +18,15 @@ declare void @free(ptr) define private void @_ZN5Inner4ctorEv(ptr noundef nonnull align 8 dereferenceable(16) %0) { %this = alloca ptr, align 8 store ptr %0, ptr %this, align 8 - store %struct.Inner { ptr @anon.string.0, ptr null }, ptr %0, align 8 %2 = load ptr, ptr %this, align 8 - %data_addr = getelementptr inbounds %struct.Inner, ptr %2, i32 0, i32 1 - %3 = call ptr @malloc(i64 10) - store ptr %3, ptr %data_addr, align 8 + %3 = getelementptr inbounds %struct.Inner, ptr %2, i32 0, i32 0 + store ptr @anon.string.0, ptr %3, align 8 + %4 = getelementptr inbounds %struct.Inner, ptr %2, i32 0, i32 1 + store ptr null, ptr %4, align 8 + %5 = load ptr, ptr %this, align 8 + %data_addr = getelementptr inbounds %struct.Inner, ptr %5, i32 0, i32 1 + %6 = call ptr @malloc(i64 10) + store ptr %6, ptr %data_addr, align 8 ret void } 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 77b344c09..dc967db6b 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 @@ -26,13 +26,15 @@ define private void @_ZN20StructWithHeapFields4ctorEv(ptr noundef nonnull align %this = alloca ptr, align 8 %res = alloca %struct.Result, align 8 store ptr %0, ptr %this, align 8 - store %struct.StructWithHeapFields zeroinitializer, ptr %0, align 8 - %2 = call %struct.Result @_Z6sAllocm(i64 10) - store %struct.Result %2, ptr %res, align 8 - %3 = load ptr, ptr %this, align 8 - %data_addr = getelementptr inbounds %struct.StructWithHeapFields, ptr %3, i32 0, i32 0 - %4 = call ptr @_ZN6ResultIPhE6unwrapEv(ptr %res) - store ptr %4, ptr %data_addr, align 8 + %2 = load ptr, ptr %this, align 8 + %3 = getelementptr inbounds %struct.StructWithHeapFields, ptr %2, i32 0, i32 0 + store ptr null, ptr %3, align 8 + %4 = call %struct.Result @_Z6sAllocm(i64 10) + store %struct.Result %4, ptr %res, align 8 + %5 = load ptr, ptr %this, align 8 + %data_addr = getelementptr inbounds %struct.StructWithHeapFields, ptr %5, i32 0, i32 0 + %6 = call ptr @_ZN6ResultIPhE6unwrapEv(ptr noundef nonnull align 8 dereferenceable(24) %res) + store ptr %6, ptr %data_addr, align 8 ret void } @@ -47,7 +49,7 @@ define dso_local i32 @main() #1 { %s = alloca %struct.StructWithHeapFields, align 8 store i32 0, ptr %result, align 4 store ptr null, ptr %sPtr, align 8 - call void @_ZN20StructWithHeapFields4ctorEv(ptr %s) + call void @_ZN20StructWithHeapFields4ctorEv(ptr noundef nonnull align 8 dereferenceable(8) %s) store ptr %s, ptr %sPtr, align 8 %data_addr = getelementptr inbounds %struct.StructWithHeapFields, ptr %s, i32 0, i32 0 %1 = load ptr, ptr %data_addr, align 8 diff --git a/test/test-files/irgenerator/structs/success-default-field-values4/ir-code.ll b/test/test-files/irgenerator/structs/success-default-field-values4/ir-code.ll index e71b0a3cd..8ab0b7a40 100644 --- a/test/test-files/irgenerator/structs/success-default-field-values4/ir-code.ll +++ b/test/test-files/irgenerator/structs/success-default-field-values4/ir-code.ll @@ -12,9 +12,13 @@ target triple = "x86_64-w64-windows-gnu" define private void @_ZN4Test4ctorEv(ptr noundef nonnull align 8 dereferenceable(16) %0) { %this = alloca ptr, align 8 store ptr %0, ptr %this, align 8 - store %struct.Test { i32 12, ptr @0 }, ptr %0, align 8 %2 = load ptr, ptr %this, align 8 - %i_addr = getelementptr inbounds %struct.Test, ptr %2, i32 0, i32 0 + %3 = getelementptr inbounds %struct.Test, ptr %2, i32 0, i32 0 + store i32 12, ptr %3, align 4 + %4 = getelementptr inbounds %struct.Test, ptr %2, i32 0, i32 1 + store ptr @0, ptr %4, align 8 + %5 = load ptr, ptr %this, align 8 + %i_addr = getelementptr inbounds %struct.Test, ptr %5, i32 0, i32 0 store i32 14, ptr %i_addr, align 4 ret void } @@ -24,7 +28,7 @@ define dso_local i32 @main() #0 { %result = alloca i32, align 4 %t = alloca %struct.Test, align 8 store i32 0, ptr %result, align 4 - call void @_ZN4Test4ctorEv(ptr %t) + call void @_ZN4Test4ctorEv(ptr noundef nonnull align 8 dereferenceable(16) %t) %i_addr = getelementptr inbounds %struct.Test, ptr %t, i32 0, i32 0 %1 = load i32, ptr %i_addr, align 4 %2 = call i32 (ptr, ...) @printf(ptr noundef @printf.str.0, i32 %1) diff --git a/test/test-files/irgenerator/structs/success-external-structs/ir-code.ll b/test/test-files/irgenerator/structs/success-external-structs/ir-code.ll index 5b0aba530..1beda0fdc 100644 --- a/test/test-files/irgenerator/structs/success-external-structs/ir-code.ll +++ b/test/test-files/irgenerator/structs/success-external-structs/ir-code.ll @@ -12,9 +12,9 @@ define dso_local i32 @main() #0 { %v1 = alloca %struct.Vec, align 8 store i32 0, ptr %result, align 4 store %struct.Vec { i32 11, i1 false }, ptr %v, align 4 - call void @_ZN3Vec5printEv(ptr %v) + call void @_ZN3Vec5printEv(ptr noundef nonnull align 4 dereferenceable(8) %v) store %struct.Vec zeroinitializer, ptr %v1, align 4 - call void @_ZN3Vec5printEv(ptr %v1) + call void @_ZN3Vec5printEv(ptr noundef nonnull align 4 dereferenceable(8) %v1) %1 = load i32, ptr %result, align 4 ret i32 %1 } diff --git a/test/test-files/std/time/high-res-timer/ir-code-O2.ll b/test/test-files/std/time/high-res-timer/ir-code-O2.ll index 69073e64b..e8b5c0385 100644 --- a/test/test-files/std/time/high-res-timer/ir-code-O2.ll +++ b/test/test-files/std/time/high-res-timer/ir-code-O2.ll @@ -33,8 +33,8 @@ define dso_local i32 @main() local_unnamed_addr #1 { %t = alloca %struct.Timer, align 8 %duration = alloca i64, align 8 %1 = alloca %struct.Timer, align 8 - call void @_ZN5Timer4ctorEv(ptr nonnull %t) #3 - %2 = call i64 @_ZN5Timer11getDurationEv(ptr nonnull %t) #3 + call void @_ZN5Timer4ctorEv(ptr noundef nonnull align 8 dereferenceable(32) %t) #3 + %2 = call i64 @_ZN5Timer11getDurationEv(ptr noundef nonnull align 8 dereferenceable(32) %t) #3 %3 = icmp eq i64 %2, 0 br i1 %3, label %assert.exit.L12, label %assert.then.L12, !prof !0 @@ -44,10 +44,10 @@ assert.then.L12: ; preds = %0 unreachable assert.exit.L12: ; preds = %0 - call void @_ZN5Timer5startEv(ptr nonnull %t) #3 + call void @_ZN5Timer5startEv(ptr noundef nonnull align 8 dereferenceable(32) %t) #3 call void @_Z5delayi(i32 10) #3 - call void @_ZN5Timer4stopEv(ptr nonnull %t) #3 - %5 = call i64 @_ZN5Timer11getDurationEv(ptr nonnull %t) #3 + call void @_ZN5Timer4stopEv(ptr noundef nonnull align 8 dereferenceable(32) %t) #3 + %5 = call i64 @_ZN5Timer11getDurationEv(ptr noundef nonnull align 8 dereferenceable(32) %t) #3 %6 = call fastcc i1 @_Z9isInRangemmj(i64 %5, i64 10, i32 3) #3 br i1 %6, label %assert.exit.L16, label %assert.then.L16, !prof !0 @@ -58,7 +58,7 @@ assert.then.L16: ; preds = %assert.exit.L12 assert.exit.L16: ; preds = %assert.exit.L12 store i64 0, ptr %duration, align 8 - call void @_ZN5Timer4ctorEiPm(ptr nonnull %1, i32 0, ptr nonnull %duration) #3 + call void @_ZN5Timer4ctorEiPm(ptr noundef nonnull align 8 dereferenceable(32) %1, i32 0, ptr nonnull %duration) #3 %.fca.0.load = load i64, ptr %1, align 8 %.fca.1.gep = getelementptr inbounds %struct.Timer, ptr %1, i64 0, i32 1 %.fca.1.load = load i64, ptr %.fca.1.gep, align 8 @@ -73,7 +73,7 @@ assert.exit.L16: ; preds = %assert.exit.L12 store i32 %.fca.2.load, ptr %.fca.3.insert.fca.2.gep, align 8 %.fca.3.insert.fca.3.gep = getelementptr inbounds %struct.Timer, ptr %t, i64 0, i32 3 store ptr %.fca.3.load, ptr %.fca.3.insert.fca.3.gep, align 8 - %8 = call i64 @_ZN5Timer11getDurationEv(ptr nonnull %t) #3 + %8 = call i64 @_ZN5Timer11getDurationEv(ptr noundef nonnull align 8 dereferenceable(32) %t) #3 %9 = icmp eq i64 %8, 0 br i1 %9, label %assert.exit.L21, label %assert.then.L21, !prof !0 @@ -93,13 +93,13 @@ assert.then.L22: ; preds = %assert.exit.L21 unreachable assert.exit.L22: ; preds = %assert.exit.L21 - call void @_ZN5Timer5startEv(ptr nonnull %t) #3 + call void @_ZN5Timer5startEv(ptr noundef nonnull align 8 dereferenceable(32) %t) #3 call void @_Z5delayi(i32 10) #3 - call void @_ZN5Timer5pauseEv(ptr nonnull %t) #3 + call void @_ZN5Timer5pauseEv(ptr noundef nonnull align 8 dereferenceable(32) %t) #3 call void @_Z5delayi(i32 100) #3 - call void @_ZN5Timer6resumeEv(ptr nonnull %t) #3 + call void @_ZN5Timer6resumeEv(ptr noundef nonnull align 8 dereferenceable(32) %t) #3 call void @_Z5delayi(i32 10) #3 - call void @_ZN5Timer4stopEv(ptr nonnull %t) #3 + call void @_ZN5Timer4stopEv(ptr noundef nonnull align 8 dereferenceable(32) %t) #3 %14 = load i64, ptr %duration, align 8 %15 = call fastcc i1 @_Z9isInRangemmj(i64 %14, i64 20000, i32 5000) #3 br i1 %15, label %assert.exit.L30, label %assert.then.L30, !prof !0 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 c3ecc851d..ac2297b0e 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 @@ -48,7 +48,7 @@ { "captures": [], "children": [], - "name": "printLength()", + "name": "printLength()", "symbols": [ { "codeLoc": "L12C1", @@ -57,14 +57,14 @@ "name": "this", "orderIndex": 0, "state": "declared", - "type": "TestStruct*" + "type": "TestStruct*" } ] }, { "captures": [], "children": [], - "name": "ctor(const unsigned long)", + "name": "ctor(const unsigned long)", "symbols": [ { "codeLoc": "L8C19", @@ -82,7 +82,7 @@ "name": "this", "orderIndex": 0, "state": "declared", - "type": "TestStruct*" + "type": "TestStruct*" } ] } @@ -185,7 +185,7 @@ { "captures": [], "children": [], - "name": "printLength()", + "name": "printLength()", "symbols": [ { "codeLoc": "L12C1", @@ -194,14 +194,14 @@ "name": "this", "orderIndex": 0, "state": "declared", - "type": "TestStruct*" + "type": "TestStruct*" } ] }, { "captures": [], "children": [], - "name": "ctor(const unsigned long)", + "name": "ctor(const unsigned long)", "symbols": [ { "codeLoc": "L8C19", @@ -219,7 +219,7 @@ "name": "this", "orderIndex": 0, "state": "declared", - "type": "TestStruct*" + "type": "TestStruct*" } ] } @@ -260,7 +260,7 @@ "name": "_f1", "orderIndex": 0, "state": "declared", - "type": "generic(T)" + "type": "T" } ] } @@ -300,7 +300,7 @@ "name": "Alias", "orderIndex": 1, "state": "declared", - "type": "alias(TestStruct)" + "type": "TestStruct" }, { "codeLoc": "L3C1", 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 51e84ea75..6ca6f97a0 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 @@ -4,6 +4,31 @@ { "captures": [], "children": [ + { + "captures": [], + "children": [], + "name": "std/data/pair::Pair getIdx()", + "symbols": [ + { + "codeLoc": "L19C1", + "isGlobal": false, + "isVolatile": false, + "name": "result", + "orderIndex": 1, + "state": "declared", + "type": "std/data/pair::Pair" + }, + { + "codeLoc": "L19C1", + "isGlobal": false, + "isVolatile": false, + "name": "this", + "orderIndex": 0, + "state": "declared", + "type": "MockIterator*" + } + ] + }, { "captures": [], "children": [], @@ -73,7 +98,7 @@ { "captures": [], "children": [], - "name": "next()", + "name": "next()", "symbols": [ { "codeLoc": "L27C1", @@ -82,14 +107,14 @@ "name": "this", "orderIndex": 0, "state": "declared", - "type": "MockIterator*" + "type": "MockIterator*" } ] }, { "captures": [], "children": [], - "name": "bool isValid()", + "name": "bool isValid()", "symbols": [ { "codeLoc": "L23C1", @@ -107,17 +132,17 @@ "name": "this", "orderIndex": 0, "state": "declared", - "type": "MockIterator*" + "type": "MockIterator*" } ] }, { "captures": [], "children": [], - "name": "std/data/pair::Pair getIdx()", + "name": "T& get()", "symbols": [ { - "codeLoc": "L19C1", + "codeLoc": "L15C1", "isGlobal": false, "isVolatile": false, "name": "result", @@ -126,20 +151,20 @@ "type": "invalid" }, { - "codeLoc": "L19C1", + "codeLoc": "L15C1", "isGlobal": false, "isVolatile": false, "name": "this", "orderIndex": 0, "state": "declared", - "type": "MockIterator*" + "type": "MockIterator*" } ] }, { "captures": [], "children": [], - "name": "ctor()", + "name": "ctor()", "symbols": [ { "codeLoc": "L11C1", @@ -148,60 +173,69 @@ "name": "this", "orderIndex": 0, "state": "declared", - "type": "MockIterator*" + "type": "MockIterator*" } ] }, { "captures": [], "children": [], - "name": "generic(T)& get()", + "name": "ctor()", "symbols": [ { - "codeLoc": "L15C1", - "isGlobal": false, - "isVolatile": false, - "name": "result", - "orderIndex": 1, - "state": "declared", - "type": "invalid" - }, - { - "codeLoc": "L15C1", + "codeLoc": "L11C1", "isGlobal": false, "isVolatile": false, "name": "this", "orderIndex": 0, "state": "declared", - "type": "MockIterator*" + "type": "MockIterator*" } ] }, { "captures": [], "children": [], - "name": "ctor()", + "name": "std/data/pair::Pair getIdx()", "symbols": [ { - "codeLoc": "L11C1", + "codeLoc": "L19C1", + "isGlobal": false, + "isVolatile": false, + "name": "result", + "orderIndex": 1, + "state": "declared", + "type": "invalid" + }, + { + "codeLoc": "L19C1", "isGlobal": false, "isVolatile": false, "name": "this", "orderIndex": 0, "state": "declared", - "type": "MockIterator*" + "type": "MockIterator*" } ] } ], "name": "struct:MockIterator", "symbols": [ + { + "codeLoc": "L19C1", + "isGlobal": false, + "isVolatile": false, + "name": "getIdx:L19C1", + "orderIndex": 5, + "state": "declared", + "type": "f>()" + }, { "codeLoc": "L23C1", "isGlobal": false, "isVolatile": false, "name": "isValid:L23C1", - "orderIndex": 5, + "orderIndex": 6, "state": "declared", "type": "f()" }, @@ -210,7 +244,7 @@ "isGlobal": false, "isVolatile": false, "name": "ctor:L11C1", - "orderIndex": 2, + "orderIndex": 3, "state": "declared", "type": "p()" }, @@ -219,34 +253,25 @@ "isGlobal": false, "isVolatile": false, "name": "next:L27C1", - "orderIndex": 6, + "orderIndex": 7, "state": "declared", "type": "p()" }, - { - "codeLoc": "L15C1", - "isGlobal": false, - "isVolatile": false, - "name": "get:L15C1", - "orderIndex": 3, - "state": "declared", - "type": "f()" - }, { "codeLoc": "L19C1", "isGlobal": false, "isVolatile": false, "name": "getIdx:L19C1", - "orderIndex": 4, + "orderIndex": 5, "state": "declared", - "type": "f>()" + "type": "f>()" }, { "codeLoc": "L8C5", "isGlobal": false, "isVolatile": false, "name": "cursor", - "orderIndex": 1, + "orderIndex": 2, "state": "initialized", "type": "unsigned long" }, @@ -255,7 +280,7 @@ "isGlobal": false, "isVolatile": false, "name": "next:L27C1", - "orderIndex": 6, + "orderIndex": 7, "state": "declared", "type": "p()" }, @@ -264,16 +289,16 @@ "isGlobal": false, "isVolatile": false, "name": "get:L15C1", - "orderIndex": 3, + "orderIndex": 4, "state": "declared", - "type": "f()" + "type": "f()" }, { "codeLoc": "L23C1", "isGlobal": false, "isVolatile": false, "name": "isValid:L23C1", - "orderIndex": 5, + "orderIndex": 6, "state": "declared", "type": "f()" }, @@ -282,7 +307,7 @@ "isGlobal": false, "isVolatile": false, "name": "ctor:L11C1", - "orderIndex": 2, + "orderIndex": 3, "state": "declared", "type": "p()" }, @@ -291,9 +316,27 @@ "isGlobal": false, "isVolatile": false, "name": "item", - "orderIndex": 0, + "orderIndex": 1, "state": "declared", "type": "short" + }, + { + "codeLoc": "L15C1", + "isGlobal": false, + "isVolatile": false, + "name": "get:L15C1", + "orderIndex": 4, + "state": "declared", + "type": "f()" + }, + { + "codeLoc": "L6C31", + "isGlobal": false, + "isVolatile": false, + "name": "this.Iterable", + "orderIndex": 0, + "state": "declared", + "type": "invalid" } ] }, @@ -345,7 +388,7 @@ { "captures": [], "children": [], - "name": "next()", + "name": "next()", "symbols": [ { "codeLoc": "L27C1", @@ -354,14 +397,14 @@ "name": "this", "orderIndex": 0, "state": "declared", - "type": "MockIterator*" + "type": "MockIterator*" } ] }, { "captures": [], "children": [], - "name": "bool isValid()", + "name": "bool isValid()", "symbols": [ { "codeLoc": "L23C1", @@ -379,17 +422,17 @@ "name": "this", "orderIndex": 0, "state": "declared", - "type": "MockIterator*" + "type": "MockIterator*" } ] }, { "captures": [], "children": [], - "name": "std/data/pair::Pair getIdx()", + "name": "T& get()", "symbols": [ { - "codeLoc": "L19C1", + "codeLoc": "L15C1", "isGlobal": false, "isVolatile": false, "name": "result", @@ -398,54 +441,54 @@ "type": "invalid" }, { - "codeLoc": "L19C1", + "codeLoc": "L15C1", "isGlobal": false, "isVolatile": false, "name": "this", "orderIndex": 0, "state": "declared", - "type": "MockIterator*" + "type": "MockIterator*" } ] }, { "captures": [], "children": [], - "name": "generic(T)& get()", + "name": "ctor()", "symbols": [ { - "codeLoc": "L15C1", - "isGlobal": false, - "isVolatile": false, - "name": "result", - "orderIndex": 1, - "state": "declared", - "type": "invalid" - }, - { - "codeLoc": "L15C1", + "codeLoc": "L11C1", "isGlobal": false, "isVolatile": false, "name": "this", "orderIndex": 0, "state": "declared", - "type": "MockIterator*" + "type": "MockIterator*" } ] }, { "captures": [], "children": [], - "name": "ctor()", + "name": "std/data/pair::Pair getIdx()", "symbols": [ { - "codeLoc": "L11C1", + "codeLoc": "L19C1", + "isGlobal": false, + "isVolatile": false, + "name": "result", + "orderIndex": 1, + "state": "declared", + "type": "invalid" + }, + { + "codeLoc": "L19C1", "isGlobal": false, "isVolatile": false, "name": "this", "orderIndex": 0, "state": "declared", - "type": "MockIterator*" + "type": "MockIterator*" } ] } @@ -457,34 +500,25 @@ "isGlobal": false, "isVolatile": false, "name": "next:L27C1", - "orderIndex": 6, + "orderIndex": 7, "state": "declared", "type": "p()" }, - { - "codeLoc": "L15C1", - "isGlobal": false, - "isVolatile": false, - "name": "get:L15C1", - "orderIndex": 3, - "state": "declared", - "type": "f()" - }, { "codeLoc": "L19C1", "isGlobal": false, "isVolatile": false, "name": "getIdx:L19C1", - "orderIndex": 4, + "orderIndex": 5, "state": "declared", - "type": "f>()" + "type": "f>()" }, { "codeLoc": "L8C5", "isGlobal": false, "isVolatile": false, "name": "cursor", - "orderIndex": 1, + "orderIndex": 2, "state": "declared", "type": "unsigned long" }, @@ -493,7 +527,7 @@ "isGlobal": false, "isVolatile": false, "name": "isValid:L23C1", - "orderIndex": 5, + "orderIndex": 6, "state": "declared", "type": "f()" }, @@ -502,7 +536,7 @@ "isGlobal": false, "isVolatile": false, "name": "ctor:L11C1", - "orderIndex": 2, + "orderIndex": 3, "state": "declared", "type": "p()" }, @@ -511,9 +545,27 @@ "isGlobal": false, "isVolatile": false, "name": "item", + "orderIndex": 1, + "state": "declared", + "type": "T" + }, + { + "codeLoc": "L15C1", + "isGlobal": false, + "isVolatile": false, + "name": "get:L15C1", + "orderIndex": 4, + "state": "declared", + "type": "f()" + }, + { + "codeLoc": "L6C31", + "isGlobal": false, + "isVolatile": false, + "name": "this.Iterable", "orderIndex": 0, "state": "declared", - "type": "generic(T)" + "type": "invalid" } ] } @@ -544,7 +596,7 @@ "name": "MockIterator", "orderIndex": 2, "state": "declared", - "type": "MockIterator" + "type": "MockIterator" }, { "codeLoc": "L2C1", diff --git a/test/test-files/typechecker/interfaces/error-struct-interface-method-not-found/exception.out b/test/test-files/typechecker/interfaces/error-struct-interface-method-not-found/exception.out index fde0acb12..290391f65 100644 --- a/test/test-files/typechecker/interfaces/error-struct-interface-method-not-found/exception.out +++ b/test/test-files/typechecker/interfaces/error-struct-interface-method-not-found/exception.out @@ -2,13 +2,13 @@ Unresolved soft errors: There are unresolved errors. Please fix them and recompile. [Error|Semantic] ./test-files/typechecker/interfaces/error-struct-interface-method-not-found/source.spice:9:1: -Interface method not implemented: The struct 'AstNode' does not implement the method 'bool accept(Visitor*)', requested of interface 'Visitable' +Interface method not implemented: The struct 'AstNode' does not implement method 'bool Visitable.accept(Visitor*)' 9 type AstNode struct : Visitable {} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [Error|Semantic] ./test-files/typechecker/interfaces/error-struct-interface-method-not-found/source.spice:11:1: -Interface method not implemented: The struct 'AstEntryNode' does not implement the method 'bool accept(Visitor*)', requested of interface 'Visitable' +Interface method not implemented: The struct 'AstEntryNode' does not implement method 'bool Visitable.accept(Visitor*)' 11 type AstEntryNode struct : Visitable { ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file