Skip to content

Commit

Permalink
Fix bug with normal map usecase (#480)
Browse files Browse the repository at this point in the history
  • Loading branch information
marcauberer authored Feb 25, 2024
1 parent 4ae6921 commit 3054ac7
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 52 deletions.
52 changes: 2 additions & 50 deletions media/test-project/test.spice
Original file line number Diff line number Diff line change
@@ -1,55 +1,7 @@
import "bootstrap/bindings/llvm/llvm" as llvm;
import "std/data/vector";
import "std/data/map";

f<int> main() {
llvm::initializeNativeTarget();
llvm::initializeNativeAsmPrinter();

heap string targetTriple = llvm::getDefaultTargetTriple();
string error;
llvm::Target target = llvm::getTargetFromTriple(targetTriple, &error);
llvm::TargetMachine targetMachine = target.createTargetMachine(targetTriple, "generic", "", llvm::LLVMCodeGenOptLevel::Default, llvm::LLVMRelocMode::Default, llvm::LLVMCodeModel::Default);

llvm::LLVMContext context;
llvm::Module module = llvm::Module("test", context);
module.setDataLayout(targetMachine.createDataLayout());
module.setTargetTriple(targetTriple);
llvm::Builder builder = llvm::Builder(context);

llvm::Type returnType = builder.getInt32Ty();
Vector<llvm::Type> argTypes;
llvm::Type funcType = llvm::getFunctionType(returnType, argTypes);
llvm::Function func = llvm::Function(module, "main", funcType);
func.setLinkage(llvm::LLVMLinkage::ExternalLinkage);

llvm::BasicBlock entry = llvm::BasicBlock(context, "");
func.pushBack(entry);
builder.setInsertPoint(entry);

llvm::Value calcResult = builder.createAdd(builder.getInt32(1), builder.getInt32(2), "calcResult");

llvm::Value helloWorldStr = builder.createGlobalStringPtr("Hello, world!\n", "helloWorldStr");
Vector<llvm::Type> printfArgTypes;
printfArgTypes.pushBack(builder.getPtrTy());
printfArgTypes.pushBack(builder.getInt32Ty());
llvm::Type printfFuncType = llvm::getFunctionType(builder.getInt32Ty(), printfArgTypes, true);
llvm::Function printfFunc = module.getOrInsertFunction("printf", printfFuncType);

Vector<llvm::Value> printfArgs;
printfArgs.pushBack(helloWorldStr);
printfArgs.pushBack(calcResult);
builder.createCall(printfFunc, printfArgs);

builder.createRet(builder.getInt32(0));

assert !llvm::verifyFunction(func);
string output;
assert !llvm::verifyModule(module, &output);

printf("%s", module.print());

llvm::PassBuilderOptions passBuilderOptions;

Map<int, string> map;
}

/*import "bootstrap/util/block-allocator";
Expand Down
2 changes: 1 addition & 1 deletion src/symboltablebuilder/SymbolType.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ class SymbolType {
[[nodiscard]] const std::vector<SymbolType> &getFunctionParamAndReturnTypes() const;
void setHasLambdaCaptures(bool hasCaptures);
[[nodiscard]] bool hasLambdaCaptures() const;
[[nodiscard]] Struct *getStruct(const ASTNode *node) const;
Struct *getStruct(const ASTNode *node) const;
[[nodiscard]] Interface *getInterface(const ASTNode *node) const;
friend bool operator==(const SymbolType &lhs, const SymbolType &rhs);
friend bool operator!=(const SymbolType &lhs, const SymbolType &rhs);
Expand Down
4 changes: 4 additions & 0 deletions src/typechecker/StructManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ Struct *StructManager::matchStruct(Scope *matchScope, const std::string &reqName
}

fieldEntry->updateType(fieldType, /*overwriteExistingType=*/true);

// Instantiate structs
if (baseType.is(TY_STRUCT))
baseType.getStruct(node);
}

// Instantiate implemented interfaces if required
Expand Down
5 changes: 5 additions & 0 deletions src/typechecker/TypeChecker.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,14 @@ class TypeChecker : private CompilerPass, public ASTVisitor {
// Implicit code generation
void createDefaultStructMethod(const Struct &spiceStruct, const std::string &methodName, const ParamList &params);
void createDefaultCtorIfRequired(const Struct &spiceStruct, Scope *structScope);
void createDefaultCtorBody(const Function *ctorFunction);
void createDefaultCopyCtorIfRequired(const Struct &spiceStruct, Scope *structScope);
void createDefaultCopyCtorBody(const Function *copyCtorFunction);
void createDefaultDtorIfRequired(const Struct &spiceStruct, Scope *structScope);
void createDefaultDtorBody(const Function *dtorFunction);
void createCtorBodyPreamble(Scope *bodyScope);
void createCopyCtorBodyPreamble(Scope *bodyScope);
void createDtorBodyPreamble(Scope *bodyScope);
Function *implicitlyCallStructMethod(SymbolTableEntry *entry, const std::string &methodName, const ArgList &args,
const ASTNode *node);
void implicitlyCallStructCopyCtor(SymbolTableEntry *entry, const ASTNode *node);
Expand Down
16 changes: 16 additions & 0 deletions src/typechecker/TypeCheckerCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,22 @@ std::any TypeChecker::visitStructDefCheck(StructDefNode *node) {
}
}

// Generate default ctor body if required
const Function *ctorFunc = FunctionManager::lookupFunction(currentScope, CTOR_FUNCTION_NAME, structType, {}, true);
if (ctorFunc != nullptr && ctorFunc->implicitDefault)
createDefaultCtorBody(ctorFunc);

// Generate default copy ctor body if required
const ArgList args = {{structType.toConstReference(node), false /* always non-temporary */}};
const Function *copyCtorFunc = FunctionManager::lookupFunction(currentScope, CTOR_FUNCTION_NAME, structType, args, true);
if (copyCtorFunc != nullptr && copyCtorFunc->implicitDefault)
createDefaultCopyCtorBody(copyCtorFunc);

// Generate default dtor body if required
const Function *dtorFunc = FunctionManager::lookupFunction(currentScope, DTOR_FUNCTION_NAME, structType, {}, true);
if (dtorFunc != nullptr && dtorFunc->implicitDefault)
createDefaultDtorBody(dtorFunc);

// Return to the root scope
currentScope = rootScope;
assert(currentScope != nullptr && currentScope->type == ScopeType::GLOBAL);
Expand Down
68 changes: 67 additions & 1 deletion src/typechecker/TypeCheckerImplicit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ void TypeChecker::createDefaultCtorIfRequired(const Struct &spiceStruct, Scope *
createDefaultStructMethod(spiceStruct, CTOR_FUNCTION_NAME, {});
}

void TypeChecker::createDefaultCtorBody(const Function *ctorFunction) { createCtorBodyPreamble(ctorFunction->bodyScope); }

/**
* Checks if the given struct scope already has an user-defined constructor and creates a default one if not.
*
Expand Down Expand Up @@ -156,6 +158,10 @@ void TypeChecker::createDefaultCopyCtorIfRequired(const Struct &spiceStruct, Sco
createDefaultStructMethod(spiceStruct, CTOR_FUNCTION_NAME, paramTypes);
}

void TypeChecker::createDefaultCopyCtorBody(const Function *copyCtorFunction) {
createCopyCtorBodyPreamble(copyCtorFunction->bodyScope);
}

/**
* Checks if the given struct scope already has an user-defined destructor and creates a default one if not.
*
Expand Down Expand Up @@ -214,6 +220,8 @@ void TypeChecker::createDefaultDtorIfRequired(const Struct &spiceStruct, Scope *
}
}

void TypeChecker::createDefaultDtorBody(const Function *dtorFunction) { createDtorBodyPreamble(dtorFunction->bodyScope); }

/**
* Prepare the generation of the ctor body preamble. This preamble is used to initialize the VTable, construct or initialize
* fields.
Expand All @@ -223,6 +231,64 @@ void TypeChecker::createCtorBodyPreamble(Scope *bodyScope) {
Scope *structScope = bodyScope->parent;
assert(structScope != nullptr);

const size_t fieldCount = structScope->getFieldCount();
for (size_t i = 0; i < fieldCount; i++) {
SymbolTableEntry *fieldSymbol = structScope->symbolTable.lookupStrictByIndex(i);
assert(fieldSymbol != nullptr && fieldSymbol->isField());
if (fieldSymbol->isImplicitField)
continue;
SymbolType fieldType = fieldSymbol->getType();

if (fieldType.is(TY_STRUCT)) {
auto fieldNode = spice_pointer_cast<FieldNode *>(fieldSymbol->declNode);
// Match ctor function, create the concrete manifestation and set it to used
Scope *matchScope = fieldType.getBodyScope();
Function *spiceFunc = FunctionManager::matchFunction(matchScope, CTOR_FUNCTION_NAME, fieldType, {}, {}, false, fieldNode);
if (spiceFunc != nullptr) {
fieldType.setBodyScope(spiceFunc->thisType.getBodyScope());
fieldSymbol->updateType(fieldType, true);
}
}
}
}

/**
* Prepare the generation of the copy ctor body preamble. This preamble is used to initialize the VTable, construct or initialize
* fields.
*/
void TypeChecker::createCopyCtorBodyPreamble(Scope *bodyScope) {
// Retrieve struct scope
Scope *structScope = bodyScope->parent;
assert(structScope != nullptr);

const size_t fieldCount = structScope->getFieldCount();
for (size_t i = 0; i < fieldCount; i++) {
SymbolTableEntry *fieldSymbol = structScope->symbolTable.lookupStrictByIndex(i);
assert(fieldSymbol != nullptr && fieldSymbol->isField());
if (fieldSymbol->isImplicitField)
continue;
SymbolType fieldType = fieldSymbol->getType();

if (fieldType.is(TY_STRUCT)) {
auto fieldNode = spice_pointer_cast<FieldNode *>(fieldSymbol->declNode);
// Match ctor function, create the concrete manifestation and set it to used
Scope *matchScope = fieldType.getBodyScope();
const ArgList args = {{fieldType.toConstReference(fieldNode), false /* we always have the field as storage */}};
Function *spiceFunc = FunctionManager::matchFunction(matchScope, CTOR_FUNCTION_NAME, fieldType, args, {}, false, fieldNode);
fieldType.setBodyScope(spiceFunc->thisType.getBodyScope());
fieldSymbol->updateType(fieldType, true);
}
}
}

/**
* Prepare the generation of the dtor body preamble. This preamble is used to destruct all fields and to free all heap fields.
*/
void TypeChecker::createDtorBodyPreamble(Scope *bodyScope) {
// Retrieve struct scope
Scope *structScope = bodyScope->parent;
assert(structScope != nullptr);

const size_t fieldCount = structScope->getFieldCount();
for (size_t i = 0; i < fieldCount; i++) {
SymbolTableEntry *fieldSymbol = structScope->symbolTable.lookupStrictByIndex(i);
Expand All @@ -235,7 +301,7 @@ void TypeChecker::createCtorBodyPreamble(Scope *bodyScope) {
auto fieldNode = spice_pointer_cast<FieldNode *>(fieldSymbol->declNode);
// Match ctor function, create the concrete manifestation and set it to used
Scope *matchScope = fieldType.getBodyScope();
FunctionManager::matchFunction(matchScope, CTOR_FUNCTION_NAME, fieldType, {}, {}, false, fieldNode);
FunctionManager::matchFunction(matchScope, DTOR_FUNCTION_NAME, fieldType, {}, {}, false, fieldNode);
}
}
}
Expand Down

0 comments on commit 3054ac7

Please sign in to comment.