diff --git a/src/codegen.cpp b/src/codegen.cpp index d07b054..0f00f4d 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -56,6 +56,21 @@ namespace AST { lhs.ty->add(builder, lhs.value, rhs.value), lhs.ty }; + case types::BinOp::Sub: + return codegen::StackValue{ + lhs.ty->sub(builder, lhs.value, rhs.value), + lhs.ty + }; + case types::BinOp::LessThan: + return codegen::StackValue{ + lhs.ty->lt(builder, lhs.value, rhs.value), + std::make_shared(types::FundamentalTypeKind::Bool), + }; + case types::BinOp::GreaterThan: + return codegen::StackValue{ + lhs.ty->gt(builder, lhs.value, rhs.value), + std::make_shared(types::FundamentalTypeKind::Bool), + }; default: throw std::runtime_error("invalid binop"); } @@ -127,6 +142,8 @@ namespace types { switch (this->m_ty) { case FundamentalTypeKind::Int: return builder.builder->getInt32Ty(); + case FundamentalTypeKind::Bool: + return builder.builder->getInt1Ty(); default: return builder.builder->getVoidTy(); } diff --git a/src/types.cpp b/src/types.cpp index edb7859..2e3f9d1 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -5,10 +5,16 @@ namespace types { int operator_precedence(BinOp& op) { switch (op) { + case BinOp::Add: + case BinOp::Sub: + return 10; + + case BinOp::LessThan: + case BinOp::GreaterThan: + return 20; + case BinOp::Assignment: return 1000; - case BinOp::Add: - return 10; default: return 1000; } @@ -20,6 +26,12 @@ namespace types { return "="; case BinOp::Add: return "+"; + case BinOp::Sub: + return "-"; + case BinOp::LessThan: + return "<"; + case BinOp::GreaterThan: + return ">"; default: return "??"; } @@ -42,4 +54,31 @@ namespace types { throw std::runtime_error("Invalid type for add"); } } + + llvm::Value* FundamentalType::sub(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) { + switch (this->m_ty) { + case FundamentalTypeKind::Int: + return builder.builder->CreateSub(lhs, rhs); + default: + throw std::runtime_error("Invalid type"); + } + } + + llvm::Value* FundamentalType::lt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) { + switch (this->m_ty) { + case FundamentalTypeKind::Int: + return builder.builder->CreateCmp(llvm::CmpInst::Predicate::ICMP_SLT, lhs, rhs); + default: + throw std::runtime_error("Invalid type"); + } + } + + llvm::Value* FundamentalType::gt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) { + switch (this->m_ty) { + case FundamentalTypeKind::Int: + return builder.builder->CreateCmp(llvm::CmpInst::Predicate::ICMP_SGT, lhs, rhs); + default: + throw std::runtime_error("Invalid type"); + } + } } \ No newline at end of file diff --git a/src/types.h b/src/types.h index 1eeeead..f10a01d 100644 --- a/src/types.h +++ b/src/types.h @@ -10,6 +10,9 @@ namespace types { enum class BinOp { Assignment, Add, + Sub, + LessThan, + GreaterThan, }; int operator_precedence(BinOp& op); @@ -17,6 +20,7 @@ namespace types { enum FundamentalTypeKind { Int, + Bool }; class Type { @@ -25,6 +29,9 @@ namespace types { virtual std::string formatted() = 0; virtual llvm::Type* codegen(codegen::Builder& builder) = 0; virtual llvm::Value* add(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) = 0; + virtual llvm::Value* sub(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) = 0; + virtual llvm::Value* lt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) = 0; + virtual llvm::Value* gt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) = 0; }; class FundamentalType : public Type { @@ -36,6 +43,9 @@ namespace types { virtual std::string formatted() override; virtual llvm::Type* codegen(codegen::Builder& builder) override; virtual llvm::Value* add(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override; + virtual llvm::Value* sub(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override; + virtual llvm::Value* lt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override; + virtual llvm::Value* gt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override; }; }