mirror of
https://github.com/open-goal/jak-project
synced 2026-06-25 02:02:08 -04:00
5093b97cda
* wip decompiler ir * add AtomicOp stuff * fix windows build and warnings * add instruction parser * include * make minilzo shared * odr fix * a * fix merge conflicts * move decompiler into namespace * update the code coverage to include the decompiler * add demo test * add register use test to example test
57 lines
2.3 KiB
C++
57 lines
2.3 KiB
C++
#include "gtest/gtest.h"
|
|
#include "decompiler/IR2/AtomicOp.h"
|
|
#include "decompiler/IR2/AtomicOpBuilder.h"
|
|
#include "decompiler/Disasm/InstructionParser.h"
|
|
|
|
using namespace decompiler;
|
|
TEST(DecompilerAtomicOpBuilder, Example) {
|
|
InstructionParser parser;
|
|
|
|
// some MIPS instructions. Can be a sequence of instructions, possibly with labels.
|
|
std::string input_program =
|
|
"and v0, v1, a3\n"
|
|
"and a1, a2, a2";
|
|
|
|
// convert to Instructions:
|
|
ParsedProgram prg = parser.parse_program(input_program);
|
|
|
|
// this verifies we can convert from a string to an instruction, and back to a string again.
|
|
// the instruction printer will add two leading spaces and a newline.
|
|
EXPECT_EQ(prg.print(), " and v0, v1, a3\n and a1, a2, a2\n");
|
|
|
|
// next, set up a test environment for the conversion. The FunctionAtomicOps will hold
|
|
// the result of the conversion
|
|
FunctionAtomicOps container;
|
|
|
|
// treat the entire program as a single basic block, and convert!
|
|
convert_block_to_atomic_ops(0, prg.instructions.begin(), prg.instructions.end(), prg.labels,
|
|
&container);
|
|
|
|
// we should get back a single and operation:
|
|
EXPECT_EQ(2, container.ops.size());
|
|
|
|
// for now, we create an empty environment. The environment will be used in the future to
|
|
// rename register to variables, but for now, we just leave it empty and the printing will
|
|
// use register names
|
|
Env env;
|
|
|
|
// check the we get the right result:
|
|
EXPECT_EQ(container.ops.at(0)->to_string(prg.labels, &env), "(set! v0 (logand v1 a3))");
|
|
EXPECT_EQ(container.ops.at(1)->to_string(prg.labels, &env), "(set! a1 (logand a2 a2))");
|
|
|
|
// check that the registers read/written are identified for the first op (and v0, v1, a3)
|
|
auto& first_op = container.ops.at(0);
|
|
|
|
// two registers read (v1 and a3)
|
|
EXPECT_EQ(first_op->read_regs().size(), 2);
|
|
// one register written (v0)
|
|
EXPECT_EQ(first_op->write_regs().size(), 1);
|
|
// no clobber registers (register which ends up with a garbage value in it)
|
|
EXPECT_EQ(first_op->clobber_regs().size(), 0);
|
|
|
|
// the ordering of the two read registers doesn't matter. It happens to be in the same order
|
|
// as the opcode here, but it may not always be the case.
|
|
EXPECT_EQ(first_op->read_regs().at(0).to_string(), "v1");
|
|
EXPECT_EQ(first_op->read_regs().at(1).to_string(), "a3");
|
|
EXPECT_EQ(first_op->write_regs().at(0).to_string(), "v0");
|
|
} |