Add rest of the binops, nearly

This commit is contained in:
Sofia 2026-05-11 16:23:05 +03:00
parent 905c9ce9a5
commit c232fc3d43
5 changed files with 286 additions and 3 deletions

View File

@ -47,6 +47,91 @@ namespace types {
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
@ -66,6 +151,34 @@ namespace types {
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
@ -86,8 +199,51 @@ namespace types {
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;
}

View File

@ -9,10 +9,28 @@
namespace types {
enum class BinOp {
Assignment,
Add,
Sub,
Mul,
Div,
Modulo,
BitAnd,
BitOr,
BitXor,
BitShiftLeft,
BitShiftRight,
And,
Or,
LessThan,
LessThanEquals,
GreaterThan,
GreaterThanEquals,
Equals,
NotEquals,
};
enum class Unary {

View File

@ -469,13 +469,41 @@ namespace parsing {
token::TokenStream inner{ stream };
try {
auto token = inner.next();
auto peeked = inner.peek();
if (token.type != token::Type::Symbol) {
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 == "=") {
stream.m_position = inner.m_position;
return types::BinOp{ types::BinOp::Assignment };
}
else if (token.content == "+") {
stream.m_position = inner.m_position;
return types::BinOp{ types::BinOp::Add };
@ -484,6 +512,32 @@ namespace parsing {
stream.m_position = inner.m_position;
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 == "<") {
stream.m_position = inner.m_position;
return types::BinOp{ types::BinOp::LessThan };

View File

@ -7,15 +7,43 @@
#include "builder.h"
namespace types {
/// @brief https://en.cppreference.com/c/language/operator_precedence
int operator_precedence(BinOp& op) {
switch (op) {
case BinOp::Mul:
case BinOp::Div:
case BinOp::Modulo:
return 3;
case BinOp::Add:
case BinOp::Sub:
return 10;
return 4;
case BinOp::BitShiftLeft:
case BinOp::BitShiftRight:
return 5;
case BinOp::LessThan:
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:
return 1000;
@ -28,14 +56,41 @@ namespace types {
switch (op) {
case BinOp::Assignment:
return "=";
case BinOp::Add:
return "+";
case BinOp::Sub:
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:
return "<";
case BinOp::GreaterThan:
return ">";
case BinOp::LessThanEquals:
return "<=";
case BinOp::GreaterThanEquals:
return ">=";
case BinOp::Equals:
return "==";
case BinOp::NotEquals:
return "!=";
default:
return "??";
}

2
test.c
View File

@ -73,5 +73,5 @@ long long int main() {
short int sh = 123 + 5;
return sh;
return sh % 10;
}