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