#include #include #include #include #include #include #include #include using namespace willow; TEST_CASE("valid arithmetic instructions") { WillowContext ctx; DiagnosticEngine eng; TypeContext &types = ctx.types(); ConstantPool &consts = ctx.constants(); Type i64Ty = types.IntType(64); Type i34Ty = types.IntType(34); Type voidTy = types.VoidType(); Type voidFnTy = types.FunctionType(voidTy, {}); Value *one64 = consts.getInt(i64Ty, 1); Value *two64 = consts.getInt(i64Ty, 2); Value *twelve34 = consts.getInt(i34Ty, 12); Module *m = ctx.addModule("testmod"); Function *fn = m->emplaceFunction("fn", m, voidFnTy); eng.setHandler([](const Diagnostic& d) { std::cout << d << "\n"; }); BasicBlock *bb = fn->addBlock(std::make_unique(fn, types.BasicBlockType())); IRBuilder builder{ctx, *bb, bb->begin()}; SECTION("Valid add instruction") { auto &inst = *builder.buildAdd(i64Ty, one64, two64); REQUIRE(inst.opcode() == Instruction::Opcode::Add); REQUIRE(succeeded(verifyInst(ctx, inst, eng))); } SECTION("Valid mul instruction") { auto &inst = *builder.buildMul(i34Ty, twelve34, twelve34); REQUIRE(inst.opcode() == Instruction::Opcode::Mul); REQUIRE(succeeded(verifyInst(ctx, inst, eng))); } SECTION("Valid sub instruction") { auto &inst = *builder.buildSub(i64Ty, one64, two64); REQUIRE(inst.opcode() == Instruction::Opcode::Sub); REQUIRE(succeeded(verifyInst(ctx, inst, eng))); } SECTION("Valid div instruction") { auto &inst = *builder.buildDiv(i64Ty, one64, two64); REQUIRE(inst.opcode() == Instruction::Opcode::Div); REQUIRE(succeeded(verifyInst(ctx, inst, eng))); } SECTION("Valid mod instruction") { auto &inst = *builder.buildMod(i64Ty, one64, two64); REQUIRE(inst.opcode() == Instruction::Opcode::Mod); REQUIRE(succeeded(verifyInst(ctx, inst, eng))); } SECTION("Valid shl instruction") { auto &inst = *builder.buildShl(i64Ty, one64, two64); REQUIRE(inst.opcode() == Instruction::Opcode::Shl); REQUIRE(succeeded(verifyInst(ctx, inst, eng))); } SECTION("Valid shr instruction") { auto &inst = *builder.buildShr(i64Ty, one64, two64); REQUIRE(inst.opcode() == Instruction::Opcode::Shr); REQUIRE(succeeded(verifyInst(ctx, inst, eng))); } SECTION("Valid ashl instruction") { auto &inst = *builder.buildAshl(i64Ty, one64, two64); REQUIRE(inst.opcode() == Instruction::Opcode::Ashl); REQUIRE(succeeded(verifyInst(ctx, inst, eng))); } SECTION("Valid ashr instruction") { auto &inst = *builder.buildAshr(i64Ty, one64, two64); REQUIRE(inst.opcode() == Instruction::Opcode::Ashr); REQUIRE(succeeded(verifyInst(ctx, inst, eng))); } SECTION("Valid and instruction") { auto &inst = *builder.buildAnd(i64Ty, one64, two64); REQUIRE(inst.opcode() == Instruction::Opcode::And); REQUIRE(succeeded(verifyInst(ctx, inst, eng))); } SECTION("Valid not instruction") { auto &inst = *builder.buildNot(i34Ty, twelve34); REQUIRE(inst.opcode() == Instruction::Opcode::Not); REQUIRE(succeeded(verifyInst(ctx, inst, eng))); } SECTION("Valid or instruction") { auto &inst = *builder.buildOr(i64Ty, one64, two64); REQUIRE(inst.opcode() == Instruction::Opcode::Or); REQUIRE(succeeded(verifyInst(ctx, inst, eng))); } SECTION("Valid eq Instruction") { auto &inst = *builder.buildEq(one64, two64); REQUIRE(inst.opcode() == Instruction::Opcode::Eq); REQUIRE(succeeded(verifyInst(ctx, inst, eng))); } SECTION("Valid lt Instruction") { auto &inst = *builder.buildEq(one64, two64); REQUIRE(inst.opcode() == Instruction::Opcode::Eq); REQUIRE(succeeded(verifyInst(ctx, inst, eng))); } SECTION("Valid gt instruction") { auto &inst = *builder.buildGt(one64, two64); REQUIRE(inst.opcode() == Instruction::Opcode::Gt); REQUIRE(succeeded(verifyInst(ctx, inst, eng))); } SECTION("Valid le instruction") { auto &inst = *builder.buildLe(one64, two64); REQUIRE(inst.opcode() == Instruction::Opcode::Le); REQUIRE(succeeded(verifyInst(ctx, inst, eng))); } SECTION("Valid ge instruction") { auto &inst = *builder.buildGe(one64, two64); REQUIRE(inst.opcode() == Instruction::Opcode::Ge); REQUIRE(succeeded(verifyInst(ctx, inst, eng))); } }