diff --git a/src/codegen.cpp b/src/codegen.cpp index f6c1ae3..009ba8e 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6,6 +6,12 @@ #include #include +namespace codegen { + Scope Scope::with_lvalue() { + return Scope{ this->values, true }; + } +} + namespace AST { llvm::Value* IntLiteralExpression::codegen(codegen::Builder& builder, codegen::Scope& scope) { auto ty = builder.builder->getInt32Ty(); @@ -15,7 +21,12 @@ namespace AST { llvm::Value* ValueReferenceExpression::codegen(codegen::Builder& builder, codegen::Scope& scope) { auto value = scope.values.find(this->m_name); if (value != scope.values.end()) { - return builder.builder->CreateLoad(value->second.ty, value->second.value); + if (scope.is_lvalue) { + return value->second.value; + } + else { + return builder.builder->CreateLoad(value->second.ty, value->second.value); + } } else { throw new std::runtime_error("Value " + this->m_name + " not found"); @@ -23,12 +34,18 @@ namespace AST { } llvm::Value* BinaryOperationExpression::codegen(codegen::Builder& builder, codegen::Scope& scope) { - auto lhs = this->m_lhs->codegen(builder, scope); + auto lvalued = scope.with_lvalue(); + auto lhs = this->m_lhs->codegen(builder, lvalued); auto rhs = this->m_rhs->codegen(builder, scope); switch (this->m_binop) { case BinOp::Assignment: builder.builder->CreateStore(rhs, lhs, false); - return lhs; + if (scope.is_lvalue) { + return lhs; + } + else { + return rhs; + } default: throw std::runtime_error("invalid binop"); } diff --git a/src/codegen.h b/src/codegen.h index 7b38782..14846be 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -21,6 +21,9 @@ namespace codegen { struct Scope { std::map values; + bool is_lvalue; + + Scope with_lvalue(); }; }