Skip to content

Commit 25bc8fc

Browse files
committed
LLVMCodeBuilder: Implement mod operator
1 parent 6b1c764 commit 25bc8fc

File tree

5 files changed

+87
-0
lines changed

5 files changed

+87
-0
lines changed

src/dev/engine/internal/icodebuilder.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ class ICodeBuilder
3737
virtual void createOr() = 0;
3838
virtual void createNot() = 0;
3939

40+
virtual void createMod() = 0;
41+
4042
virtual void beginIfStatement() = 0;
4143
virtual void beginElseBranch() = 0;
4244
virtual void endIf() = 0;

src/dev/engine/internal/llvmcodebuilder.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,20 @@ std::shared_ptr<ExecutableCode> LLVMCodeBuilder::finalize()
180180
break;
181181
}
182182

183+
case Step::Type::Mod: {
184+
assert(step.args.size() == 2);
185+
const auto &arg1 = step.args[0];
186+
const auto &arg2 = step.args[1];
187+
// rem(a, b) / b < 0.0 ? rem(a, b) + b : rem(a, b)
188+
llvm::Constant *zero = llvm::ConstantFP::get(m_ctx, llvm::APFloat(0.0));
189+
llvm::Value *num1 = removeNaN(castValue(arg1.second, arg1.first));
190+
llvm::Value *num2 = removeNaN(castValue(arg2.second, arg2.first));
191+
llvm::Value *value = m_builder.CreateFRem(num1, num2); // rem(a, b)
192+
llvm::Value *cond = m_builder.CreateFCmpOLT(m_builder.CreateFDiv(value, num2), zero); // rem(a, b) / b < 0.0 // rem(a, b)
193+
step.functionReturnReg->value = m_builder.CreateSelect(cond, m_builder.CreateFAdd(value, num2), value);
194+
break;
195+
}
196+
183197
case Step::Type::Yield:
184198
if (!m_warp) {
185199
freeHeap();
@@ -548,6 +562,11 @@ void LLVMCodeBuilder::createNot()
548562
createOp(Step::Type::Not, Compiler::StaticType::Bool, Compiler::StaticType::Bool, 1);
549563
}
550564

565+
void LLVMCodeBuilder::createMod()
566+
{
567+
createOp(Step::Type::Mod, Compiler::StaticType::Number, Compiler::StaticType::Number, 2);
568+
}
569+
551570
void LLVMCodeBuilder::beginIfStatement()
552571
{
553572
Step step(Step::Type::BeginIf);

src/dev/engine/internal/llvmcodebuilder.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ class LLVMCodeBuilder : public ICodeBuilder
3939
void createOr() override;
4040
void createNot() override;
4141

42+
void createMod() override;
43+
4244
void beginIfStatement() override;
4345
void beginElseBranch() override;
4446
void endIf() override;
@@ -81,6 +83,7 @@ class LLVMCodeBuilder : public ICodeBuilder
8183
And,
8284
Or,
8385
Not,
86+
Mod,
8487
Yield,
8588
BeginIf,
8689
BeginElse,

test/dev/llvm/llvmcodebuilder_test.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,6 +1024,67 @@ TEST_F(LLVMCodeBuilderTest, Not)
10241024
addOpTest("nan");
10251025
}
10261026

1027+
TEST_F(LLVMCodeBuilderTest, Mod)
1028+
{
1029+
std::string expected;
1030+
1031+
auto addOpTest = [this, &expected](Value v1, Value v2) {
1032+
createBuilder(true);
1033+
1034+
m_builder->addConstValue(v1);
1035+
m_builder->addConstValue(v2);
1036+
m_builder->createMod();
1037+
m_builder->addFunctionCall("test_print_string", Compiler::StaticType::Void, { Compiler::StaticType::String });
1038+
1039+
m_builder->addConstValue(v1);
1040+
m_builder->addFunctionCall("test_const_number", Compiler::StaticType::Number, { Compiler::StaticType::Number });
1041+
m_builder->addConstValue(v2);
1042+
m_builder->addFunctionCall("test_const_number", Compiler::StaticType::Number, { Compiler::StaticType::Number });
1043+
m_builder->createMod();
1044+
m_builder->addFunctionCall("test_print_string", Compiler::StaticType::Void, { Compiler::StaticType::String });
1045+
1046+
std::string str = (v1 % v2).toString() + '\n';
1047+
std::string expected = str + str;
1048+
1049+
auto code = m_builder->finalize();
1050+
auto ctx = code->createExecutionContext(&m_target);
1051+
1052+
testing::internal::CaptureStdout();
1053+
code->run(ctx.get());
1054+
const std::string quotes1 = v1.isString() ? "\"" : "";
1055+
const std::string quotes2 = v2.isString() ? "\"" : "";
1056+
ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1 << " " << quotes2 << v2.toString() << quotes2;
1057+
};
1058+
1059+
addOpTest(4, 3);
1060+
addOpTest(3, 3);
1061+
addOpTest(2, 3);
1062+
addOpTest(1, 3);
1063+
addOpTest(0, 3);
1064+
addOpTest(-1, 3);
1065+
addOpTest(-2, 3);
1066+
addOpTest(-3, 3);
1067+
addOpTest(-4, 3);
1068+
addOpTest(4.75, 2);
1069+
addOpTest(-4.75, 2);
1070+
addOpTest(-4.75, -2);
1071+
addOpTest(4.75, -2);
1072+
addOpTest(5, 0);
1073+
addOpTest(-5, 0);
1074+
addOpTest(-2.5, "Infinity");
1075+
addOpTest(-1.2, "-Infinity");
1076+
addOpTest(2.5, "Infinity");
1077+
addOpTest(1.2, "-Infinity");
1078+
addOpTest("Infinity", 2);
1079+
addOpTest("-Infinity", 2);
1080+
addOpTest("Infinity", -2);
1081+
addOpTest("-Infinity", -2);
1082+
addOpTest(3, "NaN");
1083+
addOpTest(-3, "NaN");
1084+
addOpTest("NaN", 5);
1085+
addOpTest("NaN", -5);
1086+
}
1087+
10271088
TEST_F(LLVMCodeBuilderTest, Yield)
10281089
{
10291090
auto build = [this]() {

test/mocks/codebuildermock.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class CodeBuilderMock : public ICodeBuilder
2727
MOCK_METHOD(void, createOr, (), (override));
2828
MOCK_METHOD(void, createNot, (), (override));
2929

30+
MOCK_METHOD(void, createMod, (), (override));
31+
3032
MOCK_METHOD(void, beginIfStatement, (), (override));
3133
MOCK_METHOD(void, beginElseBranch, (), (override));
3234
MOCK_METHOD(void, endIf, (), (override));

0 commit comments

Comments
 (0)