|
@@ -1,25 +1,31 @@
|
|
#include "CodegenVisitor.h"
|
|
#include "CodegenVisitor.h"
|
|
#include "CodeGeneration.h"
|
|
#include "CodeGeneration.h"
|
|
|
|
|
|
|
|
+#include "Type.h"
|
|
|
|
+
|
|
#include <llvm/IR/Constants.h>
|
|
#include <llvm/IR/Constants.h>
|
|
#include <llvm/IR/IRBuilder.h>
|
|
#include <llvm/IR/IRBuilder.h>
|
|
|
|
|
|
|
|
|
|
using namespace qlow;
|
|
using namespace qlow;
|
|
|
|
|
|
-llvm::Value* ExpressionVisitor::visit(sem::LocalVariableExpression& lve, llvm::IRBuilder<>& builder)
|
|
|
|
|
|
+std::pair<llvm::Value*, sem::Type> ExpressionVisitor::visit(sem::LocalVariableExpression& lve, llvm::IRBuilder<>& builder)
|
|
{
|
|
{
|
|
llvm::Value* val = builder.CreateLoad(lve.var->allocaInst);
|
|
llvm::Value* val = builder.CreateLoad(lve.var->allocaInst);
|
|
- return val;
|
|
|
|
|
|
+ return { val, lve.var->type };
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-
|
|
|
|
-llvm::Value* ExpressionVisitor::visit(sem::BinaryOperation& binop, llvm::IRBuilder<>& builder)
|
|
|
|
|
|
+std::pair<llvm::Value*, sem::Type> ExpressionVisitor::visit(sem::BinaryOperation& binop, llvm::IRBuilder<>& builder)
|
|
{
|
|
{
|
|
using llvm::Value;
|
|
using llvm::Value;
|
|
- Value* left = binop.left->accept(*this, builder);
|
|
|
|
- Value* right = binop.right->accept(*this, builder);
|
|
|
|
|
|
+ using sem::Type;
|
|
|
|
+ auto [left, leftType] = binop.left->accept(*this, builder);
|
|
|
|
+ auto [right, rightType] = binop.right->accept(*this, builder);
|
|
|
|
+
|
|
|
|
+ if (leftType != Type::INTEGER || rightType != Type::INTEGER)
|
|
|
|
+ throw "invalid types in BinaryOperation";
|
|
|
|
+
|
|
if (left == nullptr) {
|
|
if (left == nullptr) {
|
|
printf("WOW: %s\n", binop.left->toString().c_str());
|
|
printf("WOW: %s\n", binop.left->toString().c_str());
|
|
}
|
|
}
|
|
@@ -27,25 +33,28 @@ llvm::Value* ExpressionVisitor::visit(sem::BinaryOperation& binop, llvm::IRBuild
|
|
|
|
|
|
switch (binop.op) {
|
|
switch (binop.op) {
|
|
case ast::Operation::Operator::PLUS:
|
|
case ast::Operation::Operator::PLUS:
|
|
- return builder.CreateAdd(left, right, "add");
|
|
|
|
|
|
+ return { builder.CreateAdd(left, right, "add"), Type::INTEGER };
|
|
case ast::Operation::Operator::MINUS:
|
|
case ast::Operation::Operator::MINUS:
|
|
- return builder.CreateSub(left, right, "sub");
|
|
|
|
|
|
+ return { builder.CreateSub(left, right, "sub"), Type::INTEGER };
|
|
case ast::Operation::Operator::ASTERISK:
|
|
case ast::Operation::Operator::ASTERISK:
|
|
- return builder.CreateMul(left, right, "mul");
|
|
|
|
|
|
+ return { builder.CreateMul(left, right, "mul"), Type::INTEGER };
|
|
case ast::Operation::Operator::SLASH:
|
|
case ast::Operation::Operator::SLASH:
|
|
- return builder.CreateSDiv(left, right, "add");
|
|
|
|
|
|
+ return { builder.CreateSDiv(left, right, "add"), Type::INTEGER };
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-llvm::Value* ExpressionVisitor::visit(sem::UnaryOperation& unop, llvm::IRBuilder<>& builder)
|
|
|
|
|
|
+std::pair<llvm::Value*, sem::Type> ExpressionVisitor::visit(sem::UnaryOperation& unop, llvm::IRBuilder<>& builder)
|
|
{
|
|
{
|
|
using llvm::Value;
|
|
using llvm::Value;
|
|
- Value* value = unop.arg->accept(*this, builder);
|
|
|
|
|
|
+ auto [value, type] = unop.arg->accept(*this, builder);
|
|
|
|
+
|
|
|
|
+ if (type != sem::Type::INTEGER)
|
|
|
|
+ throw "invalid type to negate";
|
|
|
|
|
|
switch (unop.op) {
|
|
switch (unop.op) {
|
|
case ast::Operation::Operator::MINUS:
|
|
case ast::Operation::Operator::MINUS:
|
|
- return builder.CreateNeg(value, "negate");
|
|
|
|
|
|
+ return { builder.CreateNeg(value, "negate"), sem::Type::INTEGER };
|
|
|
|
|
|
case ast::Operation::Operator::PLUS:
|
|
case ast::Operation::Operator::PLUS:
|
|
[[fallthrough]];
|
|
[[fallthrough]];
|
|
@@ -56,20 +65,25 @@ llvm::Value* ExpressionVisitor::visit(sem::UnaryOperation& unop, llvm::IRBuilder
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-llvm::Value* ExpressionVisitor::visit(sem::FeatureCallExpression& call, llvm::IRBuilder<>& builder)
|
|
|
|
|
|
+std::pair<llvm::Value*, sem::Type> ExpressionVisitor::visit(sem::FeatureCallExpression& call, llvm::IRBuilder<>& builder)
|
|
{
|
|
{
|
|
using llvm::Value;
|
|
using llvm::Value;
|
|
std::vector<Value*> arguments;
|
|
std::vector<Value*> arguments;
|
|
for (auto& arg : call.arguments) {
|
|
for (auto& arg : call.arguments) {
|
|
- arguments.push_back(arg->accept(*this, builder));
|
|
|
|
|
|
+ auto [value, type] = arg->accept(*this, builder);
|
|
|
|
+ // TODO implement type check
|
|
|
|
+ arguments.push_back(value);
|
|
}
|
|
}
|
|
//return builder.CreateCall(nullptr, arguments);
|
|
//return builder.CreateCall(nullptr, arguments);
|
|
- return nullptr;
|
|
|
|
|
|
+ return { nullptr, sem::Type::NULL_TYPE };
|
|
}
|
|
}
|
|
|
|
|
|
-llvm::Value* ExpressionVisitor::visit(sem::IntConst& node, llvm::IRBuilder<>& builder)
|
|
|
|
|
|
+std::pair<llvm::Value*, sem::Type> ExpressionVisitor::visit(sem::IntConst& node, llvm::IRBuilder<>& builder)
|
|
{
|
|
{
|
|
- return llvm::ConstantInt::get(builder.getContext(), llvm::APInt(32, std::to_string(node.value), 10));
|
|
|
|
|
|
+ return {
|
|
|
|
+ llvm::ConstantInt::get(builder.getContext(), llvm::APInt(32, std::to_string(node.value), 10)),
|
|
|
|
+ sem::Type::INTEGER
|
|
|
|
+ };
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -78,7 +92,7 @@ llvm::Value* StatementVisitor::visit(sem::AssignmentStatement& assignment,
|
|
{
|
|
{
|
|
llvm::IRBuilder<> builder(fg.getContext());
|
|
llvm::IRBuilder<> builder(fg.getContext());
|
|
builder.SetInsertPoint(fg.getCurrentBlock());
|
|
builder.SetInsertPoint(fg.getCurrentBlock());
|
|
- llvm::Value* val = assignment.value->accept(fg.expressionVisitor, builder);
|
|
|
|
|
|
+ auto [val, type] = assignment.value->accept(fg.expressionVisitor, builder);
|
|
//builder.CreateRet(val);
|
|
//builder.CreateRet(val);
|
|
return llvm::ConstantFP::get(fg.getContext(), llvm::APFloat(5.0));
|
|
return llvm::ConstantFP::get(fg.getContext(), llvm::APFloat(5.0));
|
|
}
|
|
}
|