Add rest of the binops, nearly
This commit is contained in:
parent
905c9ce9a5
commit
c232fc3d43
156
src/binops.cpp
156
src/binops.cpp
@ -47,6 +47,91 @@ namespace types {
|
|||||||
return builder.builder->CreateSub(lhs, rhs, "sub");
|
return builder.builder->CreateSub(lhs, rhs, "sub");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
definitions.push_back(BinopDefinition{
|
||||||
|
ty, types::BinOp::Mul, ty, ty, false,
|
||||||
|
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
return builder.builder->CreateMul(lhs, rhs, "mul");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
definitions.push_back(BinopDefinition{
|
||||||
|
ty, types::BinOp::BitAnd, ty, ty, false,
|
||||||
|
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
return builder.builder->CreateAnd(lhs, rhs, "and");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
definitions.push_back(BinopDefinition{
|
||||||
|
ty, types::BinOp::BitOr, ty, ty, false,
|
||||||
|
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
return builder.builder->CreateOr(lhs, rhs, "or");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
definitions.push_back(BinopDefinition{
|
||||||
|
ty, types::BinOp::BitXor, ty, ty, false,
|
||||||
|
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
return builder.builder->CreateXor(lhs, rhs, "xor");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
definitions.push_back(BinopDefinition{
|
||||||
|
ty, types::BinOp::BitShiftLeft, ty, ty, false,
|
||||||
|
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
return builder.builder->CreateShl(lhs, rhs, "shl");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
definitions.push_back(BinopDefinition{
|
||||||
|
ty, types::BinOp::BitShiftRight, ty, ty, false,
|
||||||
|
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
return builder.builder->CreateAShr(lhs, rhs, "shr");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signed Integer arithmetic binops
|
||||||
|
for (auto& ty : {
|
||||||
|
short_int_ty, int_ty, long_int_ty, long_long_int_ty, char_ty,
|
||||||
|
}) {
|
||||||
|
definitions.push_back(BinopDefinition{
|
||||||
|
ty, types::BinOp::Div, ty, ty, false,
|
||||||
|
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
return builder.builder->CreateSDiv(lhs, rhs, "sdiv");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
definitions.push_back(BinopDefinition{
|
||||||
|
ty, types::BinOp::Modulo, ty, ty, false,
|
||||||
|
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
auto div_trunc = builder.builder->CreateSDiv(lhs, rhs, "mod.sdiv");
|
||||||
|
auto div_mul = builder.builder->CreateMul(div_trunc, rhs, "mod.mul");
|
||||||
|
return builder.builder->CreateSub(lhs, div_mul, "mod.value");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unsigned Integer arithmetic binops
|
||||||
|
for (auto& ty : {
|
||||||
|
ushort_int_ty, uint_ty, ulong_int_ty, ulong_long_int_ty, uchar_ty,
|
||||||
|
bool_ty
|
||||||
|
}) {
|
||||||
|
definitions.push_back(BinopDefinition{
|
||||||
|
ty, types::BinOp::Div, ty, ty, false,
|
||||||
|
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
return builder.builder->CreateUDiv(lhs, rhs, "udiv");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
definitions.push_back(BinopDefinition{
|
||||||
|
ty, types::BinOp::Modulo, ty, ty, false,
|
||||||
|
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
auto div_trunc = builder.builder->CreateUDiv(lhs, rhs, "mod.udiv");
|
||||||
|
auto div_mul = builder.builder->CreateMul(div_trunc, rhs, "mod.mul");
|
||||||
|
return builder.builder->CreateSub(lhs, div_mul, "mod.value");
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Signed comparisons
|
// Signed comparisons
|
||||||
@ -66,6 +151,34 @@ namespace types {
|
|||||||
return builder.builder->CreateICmpSGT(lhs, rhs, "icmpsgt");
|
return builder.builder->CreateICmpSGT(lhs, rhs, "icmpsgt");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
definitions.push_back(BinopDefinition{
|
||||||
|
ty, types::BinOp::LessThanEquals, ty, bool_ty, false,
|
||||||
|
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
return builder.builder->CreateICmpSLE(lhs, rhs, "icmpsle");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
definitions.push_back(BinopDefinition{
|
||||||
|
ty, types::BinOp::GreaterThanEquals, ty, bool_ty, false,
|
||||||
|
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
return builder.builder->CreateICmpSGE(lhs, rhs, "icmpsge");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
definitions.push_back(BinopDefinition{
|
||||||
|
ty, types::BinOp::Equals, ty, bool_ty, false,
|
||||||
|
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
return builder.builder->CreateICmpEQ(lhs, rhs, "icmpeq");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
definitions.push_back(BinopDefinition{
|
||||||
|
ty, types::BinOp::NotEquals, ty, bool_ty, false,
|
||||||
|
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
return builder.builder->CreateICmpNE(lhs, rhs, "icmpne");
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unsigned comparisons
|
// Unsigned comparisons
|
||||||
@ -86,8 +199,51 @@ namespace types {
|
|||||||
return builder.builder->CreateICmpUGT(lhs, rhs, "icmpugt");
|
return builder.builder->CreateICmpUGT(lhs, rhs, "icmpugt");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
definitions.push_back(BinopDefinition{
|
||||||
|
ty, types::BinOp::LessThanEquals, ty, bool_ty, false,
|
||||||
|
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
return builder.builder->CreateICmpULE(lhs, rhs, "icmpule");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
definitions.push_back(BinopDefinition{
|
||||||
|
ty, types::BinOp::GreaterThanEquals, ty, bool_ty, false,
|
||||||
|
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
return builder.builder->CreateICmpUGE(lhs, rhs, "icmpuge");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
definitions.push_back(BinopDefinition{
|
||||||
|
ty, types::BinOp::Equals, ty, bool_ty, false,
|
||||||
|
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
return builder.builder->CreateICmpEQ(lhs, rhs, "icmpeq");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
definitions.push_back(BinopDefinition{
|
||||||
|
ty, types::BinOp::NotEquals, ty, bool_ty, false,
|
||||||
|
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
return builder.builder->CreateICmpNE(lhs, rhs, "icmpne");
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
definitions.push_back(BinopDefinition{
|
||||||
|
bool_ty, types::BinOp::And, bool_ty, bool_ty, false,
|
||||||
|
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
return builder.builder->CreateAnd(lhs, rhs, "and");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
definitions.push_back(BinopDefinition{
|
||||||
|
bool_ty, types::BinOp::Or, bool_ty, bool_ty, false,
|
||||||
|
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
|
return builder.builder->CreateOr(lhs, rhs, "or");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
return definitions;
|
return definitions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
18
src/binops.h
18
src/binops.h
@ -9,10 +9,28 @@
|
|||||||
namespace types {
|
namespace types {
|
||||||
enum class BinOp {
|
enum class BinOp {
|
||||||
Assignment,
|
Assignment,
|
||||||
|
|
||||||
Add,
|
Add,
|
||||||
Sub,
|
Sub,
|
||||||
|
Mul,
|
||||||
|
Div,
|
||||||
|
Modulo,
|
||||||
|
|
||||||
|
BitAnd,
|
||||||
|
BitOr,
|
||||||
|
BitXor,
|
||||||
|
BitShiftLeft,
|
||||||
|
BitShiftRight,
|
||||||
|
|
||||||
|
And,
|
||||||
|
Or,
|
||||||
|
|
||||||
LessThan,
|
LessThan,
|
||||||
|
LessThanEquals,
|
||||||
GreaterThan,
|
GreaterThan,
|
||||||
|
GreaterThanEquals,
|
||||||
|
Equals,
|
||||||
|
NotEquals,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Unary {
|
enum class Unary {
|
||||||
|
|||||||
@ -469,13 +469,41 @@ namespace parsing {
|
|||||||
token::TokenStream inner{ stream };
|
token::TokenStream inner{ stream };
|
||||||
try {
|
try {
|
||||||
auto token = inner.next();
|
auto token = inner.next();
|
||||||
|
auto peeked = inner.peek();
|
||||||
if (token.type != token::Type::Symbol) {
|
if (token.type != token::Type::Symbol) {
|
||||||
throw std::runtime_error("Expected binop");
|
throw std::runtime_error("Expected binop");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (token.content == "<" && peeked.content == "<") {
|
||||||
|
stream.m_position = inner.m_position;
|
||||||
|
return types::BinOp{ types::BinOp::BitShiftLeft };
|
||||||
|
}
|
||||||
|
else if (token.content == ">" && peeked.content == ">") {
|
||||||
|
stream.m_position = inner.m_position;
|
||||||
|
return types::BinOp{ types::BinOp::BitShiftRight };
|
||||||
|
}
|
||||||
|
else if (token.content == "<" && peeked.content == "=") {
|
||||||
|
stream.m_position = inner.m_position;
|
||||||
|
return types::BinOp{ types::BinOp::LessThanEquals };
|
||||||
|
}
|
||||||
|
else if (token.content == ">" && peeked.content == "=") {
|
||||||
|
stream.m_position = inner.m_position;
|
||||||
|
return types::BinOp{ types::BinOp::GreaterThanEquals };
|
||||||
|
}
|
||||||
|
else if (token.content == "=" && peeked.content == "=") {
|
||||||
|
stream.m_position = inner.m_position;
|
||||||
|
return types::BinOp{ types::BinOp::Equals };
|
||||||
|
}
|
||||||
|
else if (token.content == "!" && peeked.content == "=") {
|
||||||
|
stream.m_position = inner.m_position;
|
||||||
|
return types::BinOp{ types::BinOp::NotEquals };
|
||||||
|
}
|
||||||
|
|
||||||
else if (token.content == "=") {
|
else if (token.content == "=") {
|
||||||
stream.m_position = inner.m_position;
|
stream.m_position = inner.m_position;
|
||||||
return types::BinOp{ types::BinOp::Assignment };
|
return types::BinOp{ types::BinOp::Assignment };
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (token.content == "+") {
|
else if (token.content == "+") {
|
||||||
stream.m_position = inner.m_position;
|
stream.m_position = inner.m_position;
|
||||||
return types::BinOp{ types::BinOp::Add };
|
return types::BinOp{ types::BinOp::Add };
|
||||||
@ -484,6 +512,32 @@ namespace parsing {
|
|||||||
stream.m_position = inner.m_position;
|
stream.m_position = inner.m_position;
|
||||||
return types::BinOp{ types::BinOp::Sub };
|
return types::BinOp{ types::BinOp::Sub };
|
||||||
}
|
}
|
||||||
|
else if (token.content == "*") {
|
||||||
|
stream.m_position = inner.m_position;
|
||||||
|
return types::BinOp{ types::BinOp::Mul };
|
||||||
|
}
|
||||||
|
else if (token.content == "/") {
|
||||||
|
stream.m_position = inner.m_position;
|
||||||
|
return types::BinOp{ types::BinOp::Div };
|
||||||
|
}
|
||||||
|
else if (token.content == "%") {
|
||||||
|
stream.m_position = inner.m_position;
|
||||||
|
return types::BinOp{ types::BinOp::Modulo };
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (token.content == "&") {
|
||||||
|
stream.m_position = inner.m_position;
|
||||||
|
return types::BinOp{ types::BinOp::BitAnd };
|
||||||
|
}
|
||||||
|
else if (token.content == "|") {
|
||||||
|
stream.m_position = inner.m_position;
|
||||||
|
return types::BinOp{ types::BinOp::BitOr };
|
||||||
|
}
|
||||||
|
else if (token.content == "^") {
|
||||||
|
stream.m_position = inner.m_position;
|
||||||
|
return types::BinOp{ types::BinOp::BitXor };
|
||||||
|
}
|
||||||
|
|
||||||
else if (token.content == "<") {
|
else if (token.content == "<") {
|
||||||
stream.m_position = inner.m_position;
|
stream.m_position = inner.m_position;
|
||||||
return types::BinOp{ types::BinOp::LessThan };
|
return types::BinOp{ types::BinOp::LessThan };
|
||||||
|
|||||||
@ -7,15 +7,43 @@
|
|||||||
#include "builder.h"
|
#include "builder.h"
|
||||||
|
|
||||||
namespace types {
|
namespace types {
|
||||||
|
/// @brief https://en.cppreference.com/c/language/operator_precedence
|
||||||
int operator_precedence(BinOp& op) {
|
int operator_precedence(BinOp& op) {
|
||||||
switch (op) {
|
switch (op) {
|
||||||
|
case BinOp::Mul:
|
||||||
|
case BinOp::Div:
|
||||||
|
case BinOp::Modulo:
|
||||||
|
return 3;
|
||||||
|
|
||||||
case BinOp::Add:
|
case BinOp::Add:
|
||||||
case BinOp::Sub:
|
case BinOp::Sub:
|
||||||
return 10;
|
return 4;
|
||||||
|
|
||||||
|
case BinOp::BitShiftLeft:
|
||||||
|
case BinOp::BitShiftRight:
|
||||||
|
return 5;
|
||||||
|
|
||||||
case BinOp::LessThan:
|
case BinOp::LessThan:
|
||||||
case BinOp::GreaterThan:
|
case BinOp::GreaterThan:
|
||||||
return 20;
|
case BinOp::LessThanEquals:
|
||||||
|
case BinOp::GreaterThanEquals:
|
||||||
|
return 6;
|
||||||
|
|
||||||
|
case BinOp::Equals:
|
||||||
|
case BinOp::NotEquals:
|
||||||
|
return 7;
|
||||||
|
|
||||||
|
case BinOp::BitAnd:
|
||||||
|
return 8;
|
||||||
|
case BinOp::BitXor:
|
||||||
|
return 9;
|
||||||
|
case BinOp::BitOr:
|
||||||
|
return 10;
|
||||||
|
|
||||||
|
case BinOp::And:
|
||||||
|
return 11;
|
||||||
|
case BinOp::Or:
|
||||||
|
return 12;
|
||||||
|
|
||||||
case BinOp::Assignment:
|
case BinOp::Assignment:
|
||||||
return 1000;
|
return 1000;
|
||||||
@ -28,14 +56,41 @@ namespace types {
|
|||||||
switch (op) {
|
switch (op) {
|
||||||
case BinOp::Assignment:
|
case BinOp::Assignment:
|
||||||
return "=";
|
return "=";
|
||||||
|
|
||||||
case BinOp::Add:
|
case BinOp::Add:
|
||||||
return "+";
|
return "+";
|
||||||
case BinOp::Sub:
|
case BinOp::Sub:
|
||||||
return "-";
|
return "-";
|
||||||
|
case BinOp::Mul:
|
||||||
|
return "*";
|
||||||
|
case BinOp::Div:
|
||||||
|
return "/";
|
||||||
|
case BinOp::Modulo:
|
||||||
|
return "%";
|
||||||
|
|
||||||
|
case BinOp::BitAnd:
|
||||||
|
return "&";
|
||||||
|
case BinOp::BitOr:
|
||||||
|
return "|";
|
||||||
|
case BinOp::BitXor:
|
||||||
|
return "^";
|
||||||
|
case BinOp::BitShiftLeft:
|
||||||
|
return "<<";
|
||||||
|
case BinOp::BitShiftRight:
|
||||||
|
return ">>";
|
||||||
|
|
||||||
case BinOp::LessThan:
|
case BinOp::LessThan:
|
||||||
return "<";
|
return "<";
|
||||||
case BinOp::GreaterThan:
|
case BinOp::GreaterThan:
|
||||||
return ">";
|
return ">";
|
||||||
|
case BinOp::LessThanEquals:
|
||||||
|
return "<=";
|
||||||
|
case BinOp::GreaterThanEquals:
|
||||||
|
return ">=";
|
||||||
|
case BinOp::Equals:
|
||||||
|
return "==";
|
||||||
|
case BinOp::NotEquals:
|
||||||
|
return "!=";
|
||||||
default:
|
default:
|
||||||
return "??";
|
return "??";
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user