chore: flat out the file structure
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
// NOLINTBEGIN(readability-identifier-naming)
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace {} // namespace
|
||||
|
||||
// NOLINTEND(readability-identifier-naming)
|
||||
@@ -0,0 +1,141 @@
|
||||
// NOLINTBEGIN(readability-identifier-naming)
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include <furc/middle/ir.hpp>
|
||||
#include <furc/middle/ssa.hpp>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace furc::test {
|
||||
|
||||
class SsaCfg : public testing::Test {
|
||||
public:
|
||||
SsaCfg()
|
||||
: p_context(&p_function) {}
|
||||
protected:
|
||||
void compute() { ssa::compute_cfg(p_function.blocks, p_cfgBlocks); }
|
||||
protected:
|
||||
std::vector<ssa::cfg_block> p_cfgBlocks;
|
||||
|
||||
ir_function p_function;
|
||||
ir_context p_context;
|
||||
};
|
||||
|
||||
TEST_F(SsaCfg, Diamond) {
|
||||
ir_operand null = { ir_operand::Integer, static_cast<std::uint64_t>(0) };
|
||||
|
||||
// Entry
|
||||
p_context.terminate(null, 1, 2);
|
||||
p_context.new_next();
|
||||
// A
|
||||
p_context.terminate(3);
|
||||
p_context.new_next();
|
||||
// B
|
||||
p_context.terminate(3);
|
||||
p_context.new_next();
|
||||
// C
|
||||
p_context.terminate(4);
|
||||
p_context.new_next();
|
||||
// Exit
|
||||
p_context.terminate();
|
||||
|
||||
compute();
|
||||
|
||||
EXPECT_EQ(p_cfgBlocks[0].sucs.size(), 2);
|
||||
EXPECT_NE(p_cfgBlocks[0].sucs.find(1), p_cfgBlocks[0].sucs.end());
|
||||
EXPECT_NE(p_cfgBlocks[0].sucs.find(2), p_cfgBlocks[0].sucs.end());
|
||||
EXPECT_EQ(p_cfgBlocks[3].preds, p_cfgBlocks[0].sucs);
|
||||
EXPECT_EQ(p_cfgBlocks[3].sucs.size(), 1);
|
||||
EXPECT_NE(p_cfgBlocks[3].sucs.find(4), p_cfgBlocks[3].sucs.end());
|
||||
}
|
||||
|
||||
class SsaDom : public testing::Test {
|
||||
public:
|
||||
SsaDom()
|
||||
: p_context(&p_function) {}
|
||||
protected:
|
||||
void compute() {
|
||||
ssa::compute_cfg(p_function.blocks, p_cfgBlocks);
|
||||
p_ssaRegisters.resize(p_function.regCount);
|
||||
ssa::collect_registers(p_function.blocks, p_ssaRegisters, p_ssaGlobals);
|
||||
|
||||
std::vector<std::uint64_t> order;
|
||||
ssa::compute_rpo(p_cfgBlocks, p_ssaBlocks, order);
|
||||
|
||||
ssa::build_dtree(p_cfgBlocks, p_ssaBlocks, order);
|
||||
ssa::compute_dfrontiers(p_cfgBlocks, p_ssaBlocks);
|
||||
|
||||
ssa::ssaification(p_function.blocks, p_cfgBlocks, p_ssaBlocks, p_ssaRegisters, p_ssaGlobals);
|
||||
ssa::rename(p_function.blocks, p_function.regCount, p_cfgBlocks, p_ssaBlocks, order);
|
||||
}
|
||||
protected:
|
||||
std::vector<ssa::cfg_block> p_cfgBlocks;
|
||||
std::vector<ssa::ssa_block> p_ssaBlocks;
|
||||
std::vector<ssa::register_info> p_ssaRegisters;
|
||||
std::unordered_set<std::uint64_t> p_ssaGlobals;
|
||||
|
||||
ir_function p_function;
|
||||
ir_context p_context;
|
||||
};
|
||||
|
||||
TEST_F(SsaDom, Diamond) {
|
||||
ir_operand null = { ir_operand::Integer, static_cast<std::uint64_t>(0) };
|
||||
|
||||
// Entry
|
||||
p_context.terminate(null, 1, 2);
|
||||
p_context.new_next();
|
||||
// A
|
||||
p_context.add_instr(ir_instruction{ ir_instruction::Move,
|
||||
ir_operand{ ir_operand::Register, static_cast<std::uint64_t>(0) },
|
||||
{ null } });
|
||||
p_context.terminate(3);
|
||||
p_context.new_next();
|
||||
// B
|
||||
p_context.add_instr(ir_instruction{ ir_instruction::Move,
|
||||
ir_operand{ ir_operand::Register, static_cast<std::uint64_t>(0) },
|
||||
{ null } });
|
||||
p_context.terminate(3);
|
||||
p_context.new_next();
|
||||
// C
|
||||
p_context.add_instr(ir_instruction{ ir_instruction::Add,
|
||||
ir_operand{ ir_operand::Register, static_cast<std::uint64_t>(0) },
|
||||
{ ir_operand{ ir_operand::Register, static_cast<std::uint64_t>(0) } } });
|
||||
p_context.new_next();
|
||||
// Exit
|
||||
p_context.terminate();
|
||||
|
||||
p_function.regCount = 1;
|
||||
|
||||
compute();
|
||||
|
||||
EXPECT_TRUE(p_ssaBlocks[0].df.empty());
|
||||
|
||||
EXPECT_EQ(p_ssaBlocks[1].idom, 0);
|
||||
EXPECT_EQ(p_ssaBlocks[1].df.size(), 1);
|
||||
EXPECT_NE(p_ssaBlocks[1].df.find(3), p_ssaBlocks[1].df.end());
|
||||
|
||||
EXPECT_EQ(p_ssaBlocks[2].idom, 0);
|
||||
EXPECT_EQ(p_ssaBlocks[2].df.size(), 1);
|
||||
EXPECT_NE(p_ssaBlocks[2].df.find(3), p_ssaBlocks[2].df.end());
|
||||
|
||||
EXPECT_EQ(p_ssaBlocks[3].idom, 0);
|
||||
EXPECT_TRUE(p_ssaBlocks[3].df.empty());
|
||||
|
||||
EXPECT_EQ(p_ssaBlocks[4].idom, 3);
|
||||
EXPECT_TRUE(p_ssaBlocks[4].df.empty());
|
||||
|
||||
// Renaming
|
||||
EXPECT_EQ(p_function.blocks[1].instructions.front(),
|
||||
(ir_instruction{ ir_instruction::Move, ir_operand::reg(0, 3), { null } }));
|
||||
EXPECT_EQ(p_function.blocks[2].instructions.front(),
|
||||
(ir_instruction{ ir_instruction::Move, ir_operand::reg(0, 2), { null } }));
|
||||
EXPECT_EQ(p_function.blocks[3].instructions.front(),
|
||||
(ir_instruction{ ir_instruction::Phi,
|
||||
ir_operand::reg(0, 0),
|
||||
{ ir_operand{ ir_operand::PhiPair, ir_operand::value_u::register_s{ 0, 2 }, 2 },
|
||||
ir_operand{ ir_operand::PhiPair, ir_operand::value_u::register_s{ 0, 3 }, 1 } } }));
|
||||
}
|
||||
|
||||
} // namespace furc::test
|
||||
|
||||
// NOLINTEND(readability-identifier-naming)
|
||||
@@ -0,0 +1,110 @@
|
||||
#include "furvm/exceptions.hpp"
|
||||
#include "furvm/furvm.hpp"
|
||||
#include "furvm/thing.hpp"
|
||||
|
||||
#include "gtest/gtest.h" // IWYU pragma: keep
|
||||
#include <array>
|
||||
|
||||
namespace {
|
||||
|
||||
// TODO: Basic program tests (e.g. for loops)
|
||||
|
||||
TEST(ThingOps, Add) {
|
||||
furvm::thing lhs{ furvm::thing_type{ furvm::thing_type::U32 } };
|
||||
lhs.get<furvm::u32>() = 6;
|
||||
furvm::thing rhs{ furvm::thing_type{ furvm::thing_type::U32 } };
|
||||
rhs.get<furvm::u32>() = 7;
|
||||
|
||||
auto res = lhs.add(rhs);
|
||||
ASSERT_EQ(res.type().type, furvm::thing_type::U32);
|
||||
EXPECT_EQ(lhs.get<furvm::u32>(), 6);
|
||||
EXPECT_EQ(rhs.get<furvm::u32>(), 7);
|
||||
EXPECT_EQ(res.get<furvm::u32>(), 6 + 7);
|
||||
}
|
||||
|
||||
TEST(ThingOps, Array) {
|
||||
furvm::thing_type innerType = { furvm::thing_type::U32 };
|
||||
|
||||
static constexpr std::size_t LENGTH = 10;
|
||||
static constexpr std::array<furvm::u32, LENGTH> values = { 0, 1, 2, 3, 4, 5, 6, 7, 6, 7 };
|
||||
|
||||
furvm::thing array{ furvm::thing_type{ furvm::thing_type::Array, { &innerType, LENGTH } } };
|
||||
EXPECT_EQ(array.length(), LENGTH);
|
||||
for (std::size_t i = 0; i < LENGTH; ++i) {
|
||||
auto el = array.at(i);
|
||||
el.get<furvm::u32>() = values[i];
|
||||
EXPECT_EQ(array.at(i).integer(), values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ThingOps, Slice) {
|
||||
furvm::thing_type innerType = { furvm::thing_type::U32 };
|
||||
|
||||
static constexpr std::size_t LENGTH = 10;
|
||||
static constexpr std::array<furvm::u32, LENGTH> values = { 0, 1, 2, 3, 4, 5, 6, 7, 6, 7 };
|
||||
|
||||
furvm::thing array{ furvm::thing_type{ furvm::thing_type::Array, { &innerType, LENGTH } } };
|
||||
EXPECT_EQ(array.length(), LENGTH);
|
||||
furvm::thing slice = array.slice(0, LENGTH);
|
||||
EXPECT_EQ(slice.length(), LENGTH);
|
||||
for (std::size_t i = 0; i < LENGTH; ++i) {
|
||||
auto el = slice.at(i);
|
||||
el.get<furvm::u32>() = values[i];
|
||||
EXPECT_EQ(array.at(i).integer(), values[i]);
|
||||
EXPECT_EQ(slice.at(i).integer(), array.at(i).integer());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ThingOps, String) {
|
||||
static constexpr std::string_view STRING = "femboje na topie";
|
||||
static constexpr auto LENGTH = STRING.length();
|
||||
|
||||
furvm::thing string{ furvm::thing_type{ furvm::thing_type::String } };
|
||||
string.assign(STRING);
|
||||
EXPECT_EQ(string.length(), LENGTH);
|
||||
furvm::thing slice = string.slice(0, LENGTH);
|
||||
EXPECT_EQ(slice.length(), LENGTH);
|
||||
for (std::size_t i = 0; i < LENGTH; ++i) {
|
||||
auto el = slice.at(i);
|
||||
EXPECT_EQ(slice.at(i).get<furvm::u8>(), STRING[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ThingOps, Iterators) {
|
||||
furvm::thing_type innerType = { furvm::thing_type::U32 };
|
||||
|
||||
static constexpr std::size_t LENGTH = 10;
|
||||
static constexpr std::array<furvm::u32, LENGTH> values = { 0, 1, 2, 3, 4, 5, 6, 7, 6, 7 };
|
||||
|
||||
furvm::thing array{ furvm::thing_type{ furvm::thing_type::Array, { &innerType, LENGTH } } };
|
||||
EXPECT_EQ(array.length(), LENGTH);
|
||||
for (std::size_t i = 0; i < LENGTH; ++i) {
|
||||
auto el = array.at(i);
|
||||
el.get<furvm::u32>() = values[i];
|
||||
EXPECT_EQ(array.at(i).integer(), values[i]);
|
||||
}
|
||||
|
||||
std::size_t itCount = 0;
|
||||
for (auto it = array.begin(); it != array.end(); ++it, ++itCount) {
|
||||
auto idx = it - array.begin();
|
||||
ASSERT_EQ(idx, itCount);
|
||||
ASSERT_LT(idx, LENGTH);
|
||||
EXPECT_EQ(it->integer(), values[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ThingOps, Access) {
|
||||
furvm::thing thing{ furvm::thing_type{ furvm::thing_type::U8 } };
|
||||
EXPECT_NO_THROW(thing.get<furvm::u8>());
|
||||
EXPECT_THROW(thing.get<furvm::s8>(), furvm::bad_thing_access);
|
||||
EXPECT_THROW(thing.get<furvm::s32>(), furvm::bad_thing_access);
|
||||
EXPECT_THROW(thing.get<void*>(), furvm::bad_thing_access);
|
||||
|
||||
EXPECT_NO_THROW(thing.assign<furvm::u8>(67));
|
||||
EXPECT_THROW(thing.assign<furvm::s32>(1337), furvm::bad_thing_access);
|
||||
EXPECT_EQ(thing.get<furvm::u8>(), 67);
|
||||
EXPECT_NO_THROW(thing.set<furvm::u8>(67)); // He talkin' 'bout sum 6-7 while I want sixty ni-
|
||||
EXPECT_THROW(thing.set<furvm::s32>(1337), furvm::bad_thing_access);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
Reference in New Issue
Block a user