Skip to content

Commit

Permalink
Specify rules for borrow checker
Browse files Browse the repository at this point in the history
  • Loading branch information
marcauberer committed Jan 15, 2023
1 parent 0f3eaf5 commit ad8cf13
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 21 deletions.
24 changes: 11 additions & 13 deletions media/test-project/os-test.spice
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
type Letter struct {
string content
}

f<string> Letter.getContent() {
return this.content;
}

p Letter.setContent(string text) {
this.content = text;
p testProc(int[]*** nums) {
int[]* nums1 = **nums;
int[] nums2 = *nums1;
nums2[2] = 10;
printf("1: %d\n", nums2[0]);
printf("2: %d\n", nums2[1]);
printf("3: %d\n", nums2[2]);
printf("4: %d\n", nums2[3]);
}

f<int> main() {
dyn letter = Letter { "No content" };
letter.setContent("Hello World!");
printf("Content: %s\n", letter.getContent());
int[4] intArray = { 1, 2, 3, 4 };
printf("1: %d\n", intArray[1]);
testProc(&&&intArray);
}

/*type T string|char;
Expand Down
23 changes: 23 additions & 0 deletions src/borrowchecker/BorrowChecker.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,29 @@
#include <CompilerPass.h>
#include <ast/ASTVisitor.h>

/**
* The borrow checker enforces the following rules:
*
* - At any given time, there can be at most one mutable reference to a piece of memory. This rule helps to prevent data races and
* other undefined behavior that can occur when two pieces of code simultaneously modify the same piece of memory.
* - There can be multiple immutable references to a piece of memory, but no immutable reference can exist while there is a
* mutable reference. This rule helps to ensure that code that only needs to read from memory can do so safely, even when other
* code is modifying the same memory.
* - A reference must be valid for the entire lifetime of its use. This rule helps to prevent the use of references to memory that
* has been deallocated, which can lead to memory leaks and other undefined behavior.
* - A reference cannot be borrowed for a shorter lifetime than the lifetime of the value it references. This rule helps to ensure
* that a reference is not used after the value it references has been deallocated.
* - A reference cannot be borrowed mutably if it has already been borrowed immutably. This rule helps to ensure that a reference
* is not modified while it is being used for reading.
* - A reference cannot be borrowed mutably while it is borrowed immutably. This rule helps to ensure that a reference is not
* modified while it is being used for reading.
* - A reference cannot be borrowed mutably twice. This rule helps to ensure that a reference is not modified while it is being
* modified.
* - A function that borrows a reference must return it before the function ends. This rule ensures that the borrowed reference is
* not used anymore after the function ends and it will avoid any leaks.
* - A reference cannot be borrowed if it is already borrowed. This rule helps to ensure that a reference is not used while it is
* being borrowed by another piece of code.
*/
namespace spice::compiler {

class BorrowChecker : private CompilerPass, public ASTVisitor {
Expand Down
4 changes: 1 addition & 3 deletions src/irgenerator/GenValues.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,6 @@ std::any IRGenerator::visitFunctionCall(const FunctionCallNode *node) {
if (actualSTy == expectedSTy) {
argValues.push_back(resolveValue(argNode));
} else {
assert(actualSTy.isArray() && actualSTy.getArraySize() != ARRAY_SIZE_UNKNOWN);
assert(expectedSTy.isArray() && expectedSTy.getArraySize() == ARRAY_SIZE_UNKNOWN);
argValues.push_back(doImplicitCast(resolveAddress(argNode), expectedSTy, actualSTy));
}
}
Expand Down Expand Up @@ -298,7 +296,7 @@ std::any IRGenerator::visitStructInstantiation(const StructInstantiationNode *no
llvm::Constant *constantStruct = llvm::ConstantStruct::get(structType, constants);
llvm::Value *constantAddr = createGlobalConstant(ANON_GLOBAL_STRUCT_NAME, constantStruct);

return ExprResult{.ptr = constantAddr, .constant = constantStruct };
return ExprResult{.ptr = constantAddr, .constant = constantStruct};
} else { // We have at least one non-immediate value, so we need to take normal struct instantiation as fallback
llvm::Value *structAddr = insertAlloca(structType);

Expand Down
4 changes: 2 additions & 2 deletions src/symboltablebuilder/SymbolType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,11 +284,11 @@ bool SymbolType::equalsIgnoreArraySize(const SymbolType &otherType) const {
const SymbolType::TypeChainElement &rhsElement = otherType.typeChain.at(i);

// Ignore differences in array size
if (isArray() && otherType.isArray())
if (lhsElement.superType == TY_ARRAY && rhsElement.superType == TY_ARRAY)
continue;

// Not both types are arrays -> compare them as usual
if (*this != otherType)
if (lhsElement != rhsElement)
return false;
}
return true;
Expand Down
6 changes: 3 additions & 3 deletions src/typechecker/FunctionManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ bool FunctionManager::matchArgTypes(Function &candidate, const std::vector<Symbo

// If this is a non-generic type, we can do the type check straight away and move to the next param
if (!paramType.isBaseType(TY_GENERIC)) {
if (paramType == requestedParamType)
if (paramType.equalsIgnoreArraySize(requestedParamType))
continue;
return false;
}
Expand Down Expand Up @@ -385,12 +385,12 @@ bool FunctionManager::matchArgTypes(Function &candidate, const std::vector<Symbo
* @return Generic type object
*/
const GenericType *FunctionManager::getGenericTypeOfCandidateByName(const Function &candidate,
const std::string &templateTypeName) {
const std::string &templateTypeName) {
for (const auto &templateType : candidate.templateTypes) {
if (templateType.getSubType() == templateTypeName)
return &templateType;
}
return nullptr;
}

} // namespace spice::compiler
} // namespace spice::compiler

0 comments on commit ad8cf13

Please sign in to comment.