diff --git a/apps/fib.brc b/samples/fib.brc similarity index 94% rename from apps/fib.brc rename to samples/fib.brc index 6993ecf..11fd516 100644 --- a/apps/fib.brc +++ b/samples/fib.brc @@ -21,7 +21,7 @@ printNum fun: number sint32 ; ; -// Print 20 first fibonacci numbers +// Print first 20 fibonaci numbers main fun -> sint32 rep i sint32 <- 0, i < 20: res sint32 <- fib(i) diff --git a/src/Compiler/ModuleBuilder.cpp b/src/Compiler/ModuleBuilder.cpp index ecc9281..4e94401 100644 --- a/src/Compiler/ModuleBuilder.cpp +++ b/src/Compiler/ModuleBuilder.cpp @@ -33,9 +33,9 @@ moduleName(moduleName), sourceFileName(sourceFileName), statements(statements) { } shared_ptr ModuleBuilder::getModule() { - for (shared_ptr &statement : statements) { + scopes.push(Scope()); + for (shared_ptr &statement : statements) buildStatement(statement); - } return module; } @@ -80,12 +80,15 @@ void ModuleBuilder::buildFunctionDeclaration(shared_ptr state // build function declaration llvm::FunctionType *funType = llvm::FunctionType::get(typeForValueType(statement->getReturnValueType()), types, false); llvm::Function *fun = llvm::Function::Create(funType, llvm::GlobalValue::ExternalLinkage, statement->getName(), module.get()); - funMap[statement->getName()] = fun; + if (!setFun(statement->getName(), fun)) + return; // define function body llvm::BasicBlock *block = llvm::BasicBlock::Create(*context, statement->getName(), fun); builder->SetInsertPoint(block); + scopes.push(Scope()); + // build arguments int i=0; for (auto &arg : fun->args()) { @@ -94,7 +97,8 @@ void ModuleBuilder::buildFunctionDeclaration(shared_ptr state arg.setName(name); llvm::AllocaInst *alloca = builder->CreateAlloca(type, nullptr, name); - allocaMap[name] = alloca; + if (!setAlloca(name, alloca)) + return; builder->CreateStore(&arg, alloca); i++; @@ -103,6 +107,8 @@ void ModuleBuilder::buildFunctionDeclaration(shared_ptr state // build function body buildStatement(statement->getStatementBlock()); + scopes.pop(); + // verify string errorMessage; llvm::raw_string_ostream llvmErrorMessage(errorMessage); @@ -113,14 +119,16 @@ void ModuleBuilder::buildFunctionDeclaration(shared_ptr state void ModuleBuilder::buildVarDeclaration(shared_ptr statement) { llvm::Value *value = valueForExpression(statement->getExpression()); llvm::AllocaInst *alloca = builder->CreateAlloca(typeForValueType(statement->getValueType()), nullptr, statement->getName()); - allocaMap[statement->getName()] = alloca; + + if (!setAlloca(statement->getName(), alloca)) + return; builder->CreateStore(value, alloca); } void ModuleBuilder::buildAssignment(shared_ptr statement) { - llvm::AllocaInst *alloca = allocaMap[statement->getName()]; + llvm::AllocaInst *alloca = getAlloca(statement->getName()); if (alloca == nullptr) - failWithMessage("Variable " + statement->getName() + " not defined"); + return; llvm::Value *value = valueForExpression(statement->getExpression()); builder->CreateStore(value, alloca); @@ -151,6 +159,8 @@ void ModuleBuilder::buildLoop(shared_ptr statement) { llvm::BasicBlock *bodyBlock = llvm::BasicBlock::Create(*context, "loopBody"); llvm::BasicBlock *afterBlock = llvm::BasicBlock::Create(*context, "loopPost"); + scopes.push(Scope()); + // loop init if (initStatement != nullptr) buildStatement(statement->getInitStatement()); @@ -181,6 +191,8 @@ void ModuleBuilder::buildLoop(shared_ptr statement) { // loop post fun->insert(fun->end(), afterBlock); builder->SetInsertPoint(afterBlock); + + scopes.pop(); } void ModuleBuilder::buildMetaExternFunction(shared_ptr statement) { @@ -193,7 +205,8 @@ void ModuleBuilder::buildMetaExternFunction(shared_ptrgetReturnValueType()), types, false); llvm::Function *fun = llvm::Function::Create(funType, llvm::GlobalValue::ExternalLinkage, statement->getName(), module.get()); - funMap[statement->getName()] = fun; + if (!setFun(statement->getName(), fun)) + return; // build arguments int i=0; @@ -343,13 +356,16 @@ llvm::Value *ModuleBuilder::valueForIfElse(shared_ptr expressi builder->CreateCondBr(conditionValue, thenBlock, elseBlock); // Then + scopes.push(Scope()); builder->SetInsertPoint(thenBlock); buildStatement(expression->getThenBlock()->getStatementBlock()); llvm::Value *thenValue = valueForExpression(expression->getThenBlock()->getResultStatementExpression()->getExpression()); builder->CreateBr(mergeBlock); thenBlock = builder->GetInsertBlock(); + scopes.pop(); // Else + scopes.push(Scope()); fun->insert(fun->end(), elseBlock); builder->SetInsertPoint(elseBlock); llvm::Value *elseValue = nullptr; @@ -360,6 +376,7 @@ llvm::Value *ModuleBuilder::valueForIfElse(shared_ptr expressi } builder->CreateBr(mergeBlock); elseBlock = builder->GetInsertBlock(); + scopes.pop(); // Merge fun->insert(fun->end(), mergeBlock); @@ -378,17 +395,17 @@ llvm::Value *ModuleBuilder::valueForIfElse(shared_ptr expressi } llvm::Value *ModuleBuilder::valueForVar(shared_ptr expression) { - llvm::AllocaInst *alloca = allocaMap[expression->getName()]; + llvm::AllocaInst *alloca = getAlloca(expression->getName()); if (alloca == nullptr) - failWithMessage("Variable " + expression->getName() + " not defined"); + return nullptr; return builder->CreateLoad(alloca->getAllocatedType(), alloca, expression->getName()); } llvm::Value *ModuleBuilder::valueForCall(shared_ptr expression) { - llvm::Function *fun = funMap[expression->getName()]; + llvm::Function *fun = getFun(expression->getName()); if (fun == nullptr) - failWithMessage("Function " + expression->getName() + " not defined"); + return nullptr; llvm::FunctionType *funType = fun->getFunctionType(); vector argValues; for (shared_ptr &argumentExpression : expression->getArgumentExpressions()) { @@ -398,6 +415,48 @@ llvm::Value *ModuleBuilder::valueForCall(shared_ptr expression) return builder->CreateCall(funType, fun, llvm::ArrayRef(argValues)); } +bool ModuleBuilder::setAlloca(string name, llvm::AllocaInst *alloca) { + if (scopes.top().allocaMap[name] != nullptr) + return false; + + scopes.top().allocaMap[name] = alloca; + return true; +} + +llvm::AllocaInst* ModuleBuilder::getAlloca(string name) { + stack scopes = this->scopes; + + while (!scopes.empty()) { + llvm::AllocaInst *alloca = scopes.top().allocaMap[name]; + if (alloca != nullptr) + return alloca; + scopes.pop(); + } + + return nullptr; +} + +bool ModuleBuilder::setFun(string name, llvm::Function *fun) { + if (scopes.top().funMap[name] != nullptr) + return false; + + scopes.top().funMap[name] = fun; + return true; +} + +llvm::Function* ModuleBuilder::getFun(string name) { + stack scopes = this->scopes; + + while (!scopes.empty()) { + llvm::Function *fun = scopes.top().funMap[name]; + if (fun != nullptr) + return fun; + scopes.pop(); + } + + return nullptr; +} + llvm::Type *ModuleBuilder::typeForValueType(shared_ptr valueType) { switch (valueType->getKind()) { case ValueTypeKind::NONE: diff --git a/src/Compiler/ModuleBuilder.h b/src/Compiler/ModuleBuilder.h index 1850951..fc75511 100644 --- a/src/Compiler/ModuleBuilder.h +++ b/src/Compiler/ModuleBuilder.h @@ -2,6 +2,7 @@ #define MODULE_BUILDER_H #include +#include #include #include @@ -33,6 +34,11 @@ class StatementBlock; using namespace std; +typedef struct { + map allocaMap; + map funMap; +} Scope; + class ModuleBuilder { private: string moduleName; @@ -48,8 +54,7 @@ private: llvm::Type *typeReal32; vector> statements; - map allocaMap; - map funMap; + stack scopes; void buildStatement(shared_ptr statement); void buildFunctionDeclaration(shared_ptr statement); @@ -72,6 +77,12 @@ private: llvm::Value *valueForVar(shared_ptr expression); llvm::Value *valueForCall(shared_ptr expression); + bool setAlloca(string name, llvm::AllocaInst *alloca); + llvm::AllocaInst *getAlloca(string name); + + bool setFun(string name, llvm::Function *fun); + llvm::Function *getFun(string name); + llvm::Type *typeForValueType(shared_ptr valueType); void failWithMessage(string message);