Compare commits
No commits in common. "de702514d93c4659648ef2b3199064250bd91749" and "a90259eccc640e99cd0efe73eaca7f711f62c459" have entirely different histories.
de702514d9
...
a90259eccc
@ -119,7 +119,7 @@ namespace types {
|
||||
[](codegen::Builder& builder, std::shared_ptr<Type> ty, llvm::Value* ptr) {
|
||||
codegen::TypeMap structs {};
|
||||
auto llvm_ty = ty->codegen(builder, structs);
|
||||
auto loaded = builder.builder->CreateLoad(llvm_ty, ptr, "load");
|
||||
auto loaded = builder.builder->CreateLoad(llvm_ty, ptr);
|
||||
auto const_1 = llvm::ConstantInt::get(llvm_ty, 1);
|
||||
auto result = builder.builder->CreateAdd(loaded, const_1, "add");
|
||||
builder.builder->CreateStore(result, ptr);
|
||||
@ -132,7 +132,7 @@ namespace types {
|
||||
[](codegen::Builder& builder, std::shared_ptr<Type> ty, llvm::Value* ptr) {
|
||||
codegen::TypeMap structs {};
|
||||
auto llvm_ty = ty->codegen(builder, structs);
|
||||
auto loaded = builder.builder->CreateLoad(llvm_ty, ptr, "load");
|
||||
auto loaded = builder.builder->CreateLoad(llvm_ty, ptr);
|
||||
auto const_1 = llvm::ConstantInt::get(llvm_ty, 1);
|
||||
auto result = builder.builder->CreateAdd(loaded, const_1, "add");
|
||||
builder.builder->CreateStore(result, ptr);
|
||||
@ -145,7 +145,7 @@ namespace types {
|
||||
[](codegen::Builder& builder, std::shared_ptr<Type> ty, llvm::Value* ptr) {
|
||||
codegen::TypeMap structs {};
|
||||
auto llvm_ty = ty->codegen(builder, structs);
|
||||
auto loaded = builder.builder->CreateLoad(llvm_ty, ptr, "load");
|
||||
auto loaded = builder.builder->CreateLoad(llvm_ty, ptr);
|
||||
auto const_1 = llvm::ConstantInt::get(llvm_ty, 1);
|
||||
auto result = builder.builder->CreateSub(loaded, const_1, "sub");
|
||||
builder.builder->CreateStore(result, ptr);
|
||||
@ -158,7 +158,7 @@ namespace types {
|
||||
[](codegen::Builder& builder, std::shared_ptr<Type> ty, llvm::Value* ptr) {
|
||||
codegen::TypeMap structs {};
|
||||
auto llvm_ty = ty->codegen(builder, structs);
|
||||
auto loaded = builder.builder->CreateLoad(llvm_ty, ptr, "load");
|
||||
auto loaded = builder.builder->CreateLoad(llvm_ty, ptr);
|
||||
auto const_1 = llvm::ConstantInt::get(llvm_ty, 1);
|
||||
auto result = builder.builder->CreateSub(loaded, const_1, "sub");
|
||||
builder.builder->CreateStore(result, ptr);
|
||||
|
||||
@ -11,16 +11,7 @@
|
||||
|
||||
namespace codegen {
|
||||
Scope Scope::with_lvalue() {
|
||||
return Scope{
|
||||
.binops = this->binops,
|
||||
.unops = this->unops,
|
||||
.casts = this->casts,
|
||||
.structs = this->structs,
|
||||
.values = this->values,
|
||||
.is_lvalue = true,
|
||||
.continue_bb = this->continue_bb,
|
||||
.break_bb = this->break_bb,
|
||||
};
|
||||
return Scope{ this->binops, this->unops, this->casts, this->structs, this->values, true };
|
||||
}
|
||||
}
|
||||
|
||||
@ -367,7 +358,7 @@ namespace AST {
|
||||
}
|
||||
|
||||
auto gep = builder.builder->CreateStructGEP(
|
||||
ptr_ty->m_inner->codegen(builder, scope.structs), struct_ptr.value, idx, "struct_gep");
|
||||
ptr_ty->m_inner->codegen(builder, scope.structs), struct_ptr.value, idx);
|
||||
|
||||
|
||||
if (scope.is_lvalue) {
|
||||
@ -553,15 +544,13 @@ namespace AST {
|
||||
builder.block = then_block;
|
||||
builder.builder->SetInsertPoint(then_block);
|
||||
this->m_then->codegen(builder, scope, allocator);
|
||||
if (builder.block->getTerminator() == nullptr)
|
||||
builder.builder->CreateBr(after_block);
|
||||
builder.builder->CreateBr(after_block);
|
||||
|
||||
if (else_block.has_value()) {
|
||||
builder.block = *else_block;
|
||||
builder.builder->SetInsertPoint(*else_block);
|
||||
this->m_else->get()->codegen(builder, scope, allocator);
|
||||
if (builder.block->getTerminator() == nullptr)
|
||||
builder.builder->CreateBr(after_block);
|
||||
builder.builder->CreateBr(after_block);
|
||||
}
|
||||
|
||||
builder.block = after_block;
|
||||
@ -581,19 +570,14 @@ namespace AST {
|
||||
auto cond_bb = llvm::BasicBlock::Create(*builder.context, "for-cond", function);
|
||||
auto inner_bb = llvm::BasicBlock::Create(*builder.context, "for-inner", function);
|
||||
auto after_bb = llvm::BasicBlock::Create(*builder.context, "for-after", function);
|
||||
auto done_bb = llvm::BasicBlock::Create(*builder.context, "for-done", function);
|
||||
|
||||
builder.builder->CreateBr(cond_bb);
|
||||
|
||||
codegen::Scope inner_scope{ scope };
|
||||
inner_scope.continue_bb = after_bb;
|
||||
inner_scope.break_bb = done_bb;
|
||||
|
||||
// Loop conditional
|
||||
builder.builder->SetInsertPoint(cond_bb);
|
||||
if (this->m_cond) {
|
||||
auto cond_res = (*this->m_cond)->codegen(builder, inner_scope, allocator);
|
||||
builder.builder->CreateCondBr(cond_res.value, inner_bb, done_bb);
|
||||
auto cond_res = (*this->m_cond)->codegen(builder, scope, allocator);
|
||||
builder.builder->CreateCondBr(cond_res.value, inner_bb, after_bb);
|
||||
}
|
||||
else {
|
||||
builder.builder->CreateBr(inner_bb);
|
||||
@ -602,19 +586,14 @@ namespace AST {
|
||||
// Loop inner block
|
||||
builder.block = inner_bb;
|
||||
builder.builder->SetInsertPoint(inner_bb);
|
||||
this->m_loop->codegen(builder, inner_scope, allocator);
|
||||
builder.builder->CreateBr(after_bb);
|
||||
|
||||
// Loop after-part
|
||||
builder.block = after_bb;
|
||||
builder.builder->SetInsertPoint(after_bb);
|
||||
this->m_loop->codegen(builder, scope, allocator);
|
||||
if (this->m_after)
|
||||
(*this->m_after)->codegen(builder, inner_scope, allocator);
|
||||
(*this->m_after)->codegen(builder, scope, allocator);
|
||||
builder.builder->CreateBr(cond_bb);
|
||||
|
||||
// Loop after
|
||||
builder.block = done_bb;
|
||||
builder.builder->SetInsertPoint(done_bb);
|
||||
builder.block = after_bb;
|
||||
builder.builder->SetInsertPoint(after_bb);
|
||||
}
|
||||
|
||||
void WhileStatement::codegen(codegen::Builder& builder, codegen::Scope& scope, codegen::StackAllocator& allocator) {
|
||||
@ -630,14 +609,10 @@ namespace AST {
|
||||
|
||||
builder.builder->CreateBr(cond_bb);
|
||||
|
||||
codegen::Scope inner_scope{ scope };
|
||||
inner_scope.continue_bb = cond_bb;
|
||||
inner_scope.break_bb = after_bb;
|
||||
|
||||
// While condition
|
||||
builder.builder->SetInsertPoint(cond_bb);
|
||||
if (this->m_cond) {
|
||||
auto cond_value = (*this->m_cond)->codegen(builder, inner_scope, allocator);
|
||||
auto cond_value = (*this->m_cond)->codegen(builder, scope, allocator);
|
||||
builder.builder->CreateCondBr(cond_value.value, inner_bb, after_bb);
|
||||
}
|
||||
else {
|
||||
@ -647,7 +622,7 @@ namespace AST {
|
||||
// While loop
|
||||
builder.builder->SetInsertPoint(inner_bb);
|
||||
builder.block = inner_bb;
|
||||
this->m_loop->codegen(builder, inner_scope, allocator);
|
||||
this->m_loop->codegen(builder, scope, allocator);
|
||||
builder.builder->CreateBr(cond_bb);
|
||||
|
||||
// After
|
||||
@ -655,35 +630,31 @@ namespace AST {
|
||||
builder.block = after_bb;
|
||||
}
|
||||
|
||||
void CompoundStatement::codegen(codegen::Builder& builder, codegen::Scope& scope, codegen::StackAllocator& allocator) {
|
||||
void CompoundStatement::codegen(codegen::Builder& builder, codegen::Scope&, codegen::StackAllocator&) {
|
||||
if (!builder.block)
|
||||
return;
|
||||
|
||||
builder.builder->SetInsertPoint(builder.block);
|
||||
|
||||
codegen::Scope inner{ scope };
|
||||
for (auto& statement : this->m_statements)
|
||||
statement->codegen(builder, inner, allocator);
|
||||
throw CompileError("TODO", this->m_meta);
|
||||
}
|
||||
|
||||
void BreakStatement::codegen(codegen::Builder& builder, codegen::Scope& scope, codegen::StackAllocator&) {
|
||||
void BreakStatement::codegen(codegen::Builder& builder, codegen::Scope&, codegen::StackAllocator&) {
|
||||
if (!builder.block)
|
||||
return;
|
||||
|
||||
builder.builder->SetInsertPoint(builder.block);
|
||||
if (scope.break_bb == nullptr)
|
||||
throw CompileError("No break_bb!", this->m_meta);
|
||||
builder.builder->CreateBr(scope.break_bb);
|
||||
|
||||
throw CompileError("TODO", this->m_meta);
|
||||
}
|
||||
|
||||
void ContinueStatement::codegen(codegen::Builder& builder, codegen::Scope& scope, codegen::StackAllocator&) {
|
||||
void ContinueStatement::codegen(codegen::Builder& builder, codegen::Scope&, codegen::StackAllocator&) {
|
||||
if (!builder.block)
|
||||
return;
|
||||
|
||||
builder.builder->SetInsertPoint(builder.block);
|
||||
if (scope.continue_bb == nullptr)
|
||||
throw CompileError("No continue_bb!", this->m_meta);
|
||||
builder.builder->CreateBr(scope.continue_bb);
|
||||
|
||||
throw CompileError("TODO", this->m_meta);
|
||||
}
|
||||
|
||||
void Function::codegen(codegen::Builder& builder, codegen::Scope& scope) {
|
||||
|
||||
@ -28,9 +28,6 @@ namespace codegen {
|
||||
|
||||
bool is_lvalue;
|
||||
|
||||
llvm::BasicBlock* continue_bb;
|
||||
llvm::BasicBlock* break_bb;
|
||||
|
||||
Scope with_lvalue();
|
||||
};
|
||||
}
|
||||
|
||||
@ -140,8 +140,6 @@ std::optional<CompileOutput> compile(std::string_view in_filename) {
|
||||
.structs = {},
|
||||
.values = {},
|
||||
.is_lvalue = false,
|
||||
.continue_bb = nullptr,
|
||||
.break_bb = nullptr,
|
||||
};
|
||||
|
||||
try {
|
||||
|
||||
@ -523,35 +523,6 @@ namespace parsing {
|
||||
token::TokenStream inner{ stream };
|
||||
auto before_meta = inner.metadata();
|
||||
try {
|
||||
if (inner.peek().type == token::Type::BreakKeyword) {
|
||||
inner.next();
|
||||
stream.m_position = inner.m_position;
|
||||
auto ret = new AST::BreakStatement{ before_meta + stream.metadata() };
|
||||
return std::pair{ std::unique_ptr<AST::Statement>{ret}, true };
|
||||
}
|
||||
if (inner.peek().type == token::Type::ContinueKeyword) {
|
||||
inner.next();
|
||||
stream.m_position = inner.m_position;
|
||||
auto ret = new AST::ContinueStatement{ before_meta + stream.metadata() };
|
||||
return std::pair{ std::unique_ptr<AST::Statement>{ret}, true };
|
||||
}
|
||||
if (inner.peek().type == token::Type::Symbol && inner.peek().content == "{") {
|
||||
inner.expect(token::Type::Symbol, "{");
|
||||
std::vector<std::unique_ptr<AST::Statement>> statements{};
|
||||
Scope inner_scope{ scope };
|
||||
while (inner.peek().content != "}") {
|
||||
auto res = parse_statement(inner, inner_scope).unwrap();
|
||||
if (res.second)
|
||||
inner.expect(token::Type::Symbol, ";");
|
||||
statements.push_back(std::move(res.first));
|
||||
}
|
||||
inner.expect(token::Type::Symbol, "}");
|
||||
|
||||
stream.m_position = inner.m_position;
|
||||
|
||||
auto ret = new AST::CompoundStatement{ before_meta + stream.metadata(),std::move(statements) };
|
||||
return std::pair{ std::unique_ptr<AST::Statement>{ret}, false };
|
||||
}
|
||||
if (inner.peek().type == token::Type::ReturnKeyword) {
|
||||
inner.next();
|
||||
auto expression = parse_expression(inner, scope).unwrap();
|
||||
|
||||
@ -63,10 +63,6 @@ namespace token {
|
||||
return "For";
|
||||
case token::Type::WhileKeyword:
|
||||
return "While";
|
||||
case token::Type::BreakKeyword:
|
||||
return "Break";
|
||||
case token::Type::ContinueKeyword:
|
||||
return "Continue";
|
||||
|
||||
case token::Type::Whitespace:
|
||||
return "Whitespace";
|
||||
@ -261,12 +257,6 @@ namespace token {
|
||||
else if (content == "while") {
|
||||
type = token::Type::WhileKeyword;
|
||||
}
|
||||
else if (content == "break") {
|
||||
type = token::Type::BreakKeyword;
|
||||
}
|
||||
else if (content == "continue") {
|
||||
type = token::Type::ContinueKeyword;
|
||||
}
|
||||
tokens.push_back(token::Token{ type, content, meta + content.size() });
|
||||
}
|
||||
else if (iswhitespace(c)) {
|
||||
|
||||
@ -18,8 +18,6 @@ namespace token {
|
||||
ElseKeyword,
|
||||
ForKeyword,
|
||||
WhileKeyword,
|
||||
BreakKeyword,
|
||||
ContinueKeyword,
|
||||
|
||||
Whitespace,
|
||||
Comment,
|
||||
|
||||
@ -646,7 +646,6 @@ namespace AST {
|
||||
new types::FundamentalType{ false, types::FundamentalTypeKind::Bool } };
|
||||
|
||||
typecheck::Scope inner_scope{ scope };
|
||||
inner_scope.loop_depth += 1;
|
||||
|
||||
if (this->m_init)
|
||||
(*this->m_init)->typecheck(state, inner_scope);
|
||||
@ -675,7 +674,6 @@ namespace AST {
|
||||
new types::FundamentalType{ false, types::FundamentalTypeKind::Bool } };
|
||||
|
||||
typecheck::Scope inner_scope{ scope };
|
||||
inner_scope.loop_depth += 1;
|
||||
|
||||
if (this->m_cond) {
|
||||
auto cond_ty = (*this->m_cond)->typecheck(state, inner_scope, bool_ty).type;
|
||||
@ -702,18 +700,10 @@ namespace AST {
|
||||
}
|
||||
|
||||
void BreakStatement::typecheck_preprocess(typecheck::Scope&) {}
|
||||
void BreakStatement::typecheck(typecheck::State& state, typecheck::Scope& scope) {
|
||||
if (scope.loop_depth <= 0) {
|
||||
state.errors.push_back(CompileError("Can not use break outside of a loop", this->m_meta));
|
||||
}
|
||||
}
|
||||
void BreakStatement::typecheck(typecheck::State&, typecheck::Scope&) {}
|
||||
|
||||
void ContinueStatement::typecheck_preprocess(typecheck::Scope&) {}
|
||||
void ContinueStatement::typecheck(typecheck::State& state, typecheck::Scope& scope) {
|
||||
if (scope.loop_depth <= 0) {
|
||||
state.errors.push_back(CompileError("Can not use continue outside of a loop", this->m_meta));
|
||||
}
|
||||
}
|
||||
void ContinueStatement::typecheck(typecheck::State&, typecheck::Scope&) {}
|
||||
|
||||
void Function::typecheck_preprocess(typecheck::Scope& scope) {
|
||||
this->m_return_ty = refresh_type(scope, this->m_return_ty);
|
||||
|
||||
@ -13,7 +13,6 @@ namespace typecheck {
|
||||
std::map<std::string, std::shared_ptr<types::Type>> symbols;
|
||||
std::map<std::string, std::shared_ptr<types::Type>> structs;
|
||||
std::optional<std::shared_ptr<types::Type>> return_ty;
|
||||
int loop_depth;
|
||||
};
|
||||
|
||||
struct State {
|
||||
|
||||
@ -151,7 +151,7 @@ namespace types {
|
||||
|
||||
std::pair<llvm::Value*, std::shared_ptr<Type>> PointerType::load(codegen::Builder& builder, llvm::Value* ptr, codegen::TypeMap& structs) {
|
||||
return std::pair(
|
||||
builder.builder->CreateLoad(this->m_inner->codegen(builder, structs), ptr, "load"),
|
||||
builder.builder->CreateLoad(this->m_inner->codegen(builder, structs), ptr),
|
||||
this->m_inner
|
||||
);
|
||||
}
|
||||
|
||||
9
test.c
9
test.c
@ -57,17 +57,12 @@ int main() {
|
||||
printf("2d array: %d!\n", twod_array[0][0]);
|
||||
|
||||
// Test for-loops
|
||||
for (int counter = 0; counter < 10; counter++) {
|
||||
if (counter < 5)
|
||||
continue;
|
||||
for (int counter = 0; counter < 10; counter++)
|
||||
printf("for-counter: %d\n", counter);
|
||||
}
|
||||
|
||||
// Test while-loops
|
||||
int counter = 0;
|
||||
while (1) {
|
||||
if (counter > 10)
|
||||
break;
|
||||
while (counter < 10) {
|
||||
printf("while-counter: %d\n", counter++);
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user