Added scopes

This commit is contained in:
Rafał Grodziński
2025-07-05 18:42:58 +09:00
parent 2e0015c9be
commit da1b5852ff
3 changed files with 85 additions and 15 deletions

View File

@@ -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)

View File

@@ -33,9 +33,9 @@ moduleName(moduleName), sourceFileName(sourceFileName), statements(statements) {
}
shared_ptr<llvm::Module> ModuleBuilder::getModule() {
for (shared_ptr<Statement> &statement : statements) {
scopes.push(Scope());
for (shared_ptr<Statement> &statement : statements)
buildStatement(statement);
}
return module;
}
@@ -80,12 +80,15 @@ void ModuleBuilder::buildFunctionDeclaration(shared_ptr<StatementFunction> 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<StatementFunction> 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<StatementFunction> 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<StatementFunction> state
void ModuleBuilder::buildVarDeclaration(shared_ptr<StatementVariable> 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<StatementAssignment> 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<StatementRepeat> 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<StatementRepeat> statement) {
// loop post
fun->insert(fun->end(), afterBlock);
builder->SetInsertPoint(afterBlock);
scopes.pop();
}
void ModuleBuilder::buildMetaExternFunction(shared_ptr<StatementMetaExternFunction> statement) {
@@ -193,7 +205,8 @@ void ModuleBuilder::buildMetaExternFunction(shared_ptr<StatementMetaExternFuncti
// 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;
// build arguments
int i=0;
@@ -343,13 +356,16 @@ llvm::Value *ModuleBuilder::valueForIfElse(shared_ptr<ExpressionIfElse> 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<ExpressionIfElse> 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<ExpressionIfElse> expressi
}
llvm::Value *ModuleBuilder::valueForVar(shared_ptr<ExpressionVariable> 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<ExpressionCall> 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<llvm::Value*> argValues;
for (shared_ptr<Expression> &argumentExpression : expression->getArgumentExpressions()) {
@@ -398,6 +415,48 @@ llvm::Value *ModuleBuilder::valueForCall(shared_ptr<ExpressionCall> 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<Scope> 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<Scope> 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> valueType) {
switch (valueType->getKind()) {
case ValueTypeKind::NONE:

View File

@@ -2,6 +2,7 @@
#define MODULE_BUILDER_H
#include <map>
#include <stack>
#include <llvm/IR/Module.h>
#include <llvm/IR/IRBuilder.h>
@@ -33,6 +34,11 @@ class StatementBlock;
using namespace std;
typedef struct {
map<string, llvm::AllocaInst*> allocaMap;
map<string, llvm::Function*> funMap;
} Scope;
class ModuleBuilder {
private:
string moduleName;
@@ -48,8 +54,7 @@ private:
llvm::Type *typeReal32;
vector<shared_ptr<Statement>> statements;
map<string, llvm::AllocaInst*> allocaMap;
map<string, llvm::Function*> funMap;
stack<Scope> scopes;
void buildStatement(shared_ptr<Statement> statement);
void buildFunctionDeclaration(shared_ptr<StatementFunction> statement);
@@ -72,6 +77,12 @@ private:
llvm::Value *valueForVar(shared_ptr<ExpressionVariable> expression);
llvm::Value *valueForCall(shared_ptr<ExpressionCall> 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> valueType);
void failWithMessage(string message);