diff options
Diffstat (limited to 'backend/unittests/Target')
| -rw-r--r-- | backend/unittests/Target/CMakeLists.txt | 17 | ||||
| -rw-r--r-- | backend/unittests/Target/TestTarget.cpp | 177 | ||||
| -rw-r--r-- | backend/unittests/Target/TestTarget.h | 64 |
3 files changed, 258 insertions, 0 deletions
diff --git a/backend/unittests/Target/CMakeLists.txt b/backend/unittests/Target/CMakeLists.txt new file mode 100644 index 0000000..514cb97 --- /dev/null +++ b/backend/unittests/Target/CMakeLists.txt @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +add_library(RCCBackendTestTarget TestTarget.cpp) +add_library(RCCBackend::TestTarget ALIAS RCCBackendTestTarget) + +rcc_backend_configure_target(RCCBackendTestTarget) +target_include_directories( + RCCBackendTestTarget + PUBLIC "${RCC_BACKEND_SOURCE_DIR}/unittests" +) +target_link_libraries(RCCBackendTestTarget PUBLIC RCCBackend::CodeGen) + +rcc_backend_register_format_files( + "${CMAKE_CURRENT_SOURCE_DIR}/TestTarget.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/TestTarget.h" +) +rcc_backend_register_tidy_files("${CMAKE_CURRENT_SOURCE_DIR}/TestTarget.cpp") diff --git a/backend/unittests/Target/TestTarget.cpp b/backend/unittests/Target/TestTarget.cpp new file mode 100644 index 0000000..30fa22f --- /dev/null +++ b/backend/unittests/Target/TestTarget.cpp @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "Target/TestTarget.h" + +#include <cstdint> +#include <memory> +#include <utility> +#include <vector> + +namespace rcc::test { +namespace { + +[[nodiscard]] PhysicalRegister phys(std::uint32_t Number) { + return *PhysicalRegister::create(Number); +} + +[[nodiscard]] RegisterUnitDesc unit(std::uint32_t ID, const char *Name) { + return RegisterUnitDesc{RegisterUnitID::fromValue(ID), Name}; +} + +[[nodiscard]] RegisterUnitLane unitLane(std::uint32_t ID, std::uint64_t Lanes) { + return RegisterUnitLane{RegisterUnitID::fromValue(ID), LaneMask::fromRaw(Lanes)}; +} + +[[nodiscard]] PhysicalRegisterDesc physicalRegister(std::uint32_t Number, const char *Name, + std::uint32_t Encoding, + std::vector<RegisterUnitLane> Units) { + return PhysicalRegisterDesc{phys(Number), Name, Encoding, std::move(Units)}; +} + +[[nodiscard]] RegisterClassDesc +registerClass(RegisterClassID ID, const char *Name, std::vector<PhysicalRegister> Registers, + std::vector<PhysicalRegister> AllocationOrder, std::uint32_t SizeInBits, + LaneMask Lanes, RegisterBankID DefaultBank, + std::vector<SubRegIndex> SupportedSubRegs = {}, + std::vector<RegisterClassID> SuperClasses = {}, bool Allocatable = true, + bool CoveredBySubRegs = false) { + return RegisterClassDesc{ + ID, + Name, + std::move(Registers), + std::move(AllocationOrder), + SizeInBits, + SizeInBits, + SizeInBits, + Lanes, + std::move(SupportedSubRegs), + std::move(SuperClasses), + DefaultBank, + Allocatable, + 1, + CoveredBySubRegs, + }; +} + +} // namespace + +TargetRegisterInfoDesc createTestTargetRegisterInfoDescription() { + TargetRegisterInfoDesc Description; + Description.RegisterUnits = { + unit(1, "g0.lo16"), unit(2, "g0.bits16_31"), unit(3, "g0.bits32_47"), unit(4, "g0.hi16"), + unit(5, "g1.lo16"), unit(6, "g1.bits16_31"), unit(7, "g1.bits32_47"), unit(8, "g1.hi16"), + unit(9, "sp"), unit(10, "f0"), unit(11, "f1"), + }; + + Description.PhysicalRegisters = { + physicalRegister(TestRegister::G0, "g0", 0, + {unitLane(1, 0x1), unitLane(2, 0x2), unitLane(3, 0x4), unitLane(4, 0x8)}), + physicalRegister(TestRegister::G0Low32, "g0l", 0, {unitLane(1, 0x1), unitLane(2, 0x2)}), + physicalRegister(TestRegister::G0High32, "g0h", 0, {unitLane(3, 0x1), unitLane(4, 0x2)}), + physicalRegister(TestRegister::G0Low16, "g0w", 0, {unitLane(1, 0x1)}), + physicalRegister(TestRegister::G1, "g1", 1, + {unitLane(5, 0x1), unitLane(6, 0x2), unitLane(7, 0x4), unitLane(8, 0x8)}), + physicalRegister(TestRegister::G1Low32, "g1l", 1, {unitLane(5, 0x1), unitLane(6, 0x2)}), + physicalRegister(TestRegister::G1High32, "g1h", 1, {unitLane(7, 0x1), unitLane(8, 0x2)}), + physicalRegister(TestRegister::G1Low16, "g1w", 1, {unitLane(5, 0x1)}), + physicalRegister(TestRegister::StackPointer, "sp", 2, {unitLane(9, 0xF)}), + physicalRegister(TestRegister::F0, "f0", 0, {unitLane(10, 0x1)}), + physicalRegister(TestRegister::F1, "f1", 1, {unitLane(11, 0x1)}), + }; + + Description.SubRegIndices = { + SubRegIndexDesc{TestSubReg::Low32, "low32", LaneMask::fromRaw(0x3), 32, 0}, + SubRegIndexDesc{TestSubReg::High32, "high32", LaneMask::fromRaw(0xC), 32, 32}, + SubRegIndexDesc{TestSubReg::Low16, "low16", LaneMask::fromRaw(0x1), 16, 0}, + }; + Description.PhysicalSubRegisters = { + {phys(TestRegister::G0), TestSubReg::Low32, phys(TestRegister::G0Low32)}, + {phys(TestRegister::G0), TestSubReg::High32, phys(TestRegister::G0High32)}, + {phys(TestRegister::G0), TestSubReg::Low16, phys(TestRegister::G0Low16)}, + {phys(TestRegister::G0Low32), TestSubReg::Low16, phys(TestRegister::G0Low16)}, + {phys(TestRegister::G1), TestSubReg::Low32, phys(TestRegister::G1Low32)}, + {phys(TestRegister::G1), TestSubReg::High32, phys(TestRegister::G1High32)}, + {phys(TestRegister::G1), TestSubReg::Low16, phys(TestRegister::G1Low16)}, + {phys(TestRegister::G1Low32), TestSubReg::Low16, phys(TestRegister::G1Low16)}, + }; + Description.SubRegCompositions = { + {TestSubReg::Low32, TestSubReg::Low16, TestSubReg::Low16}, + }; + + const auto G0 = phys(TestRegister::G0); + const auto G0Low32 = phys(TestRegister::G0Low32); + const auto G0High32 = phys(TestRegister::G0High32); + const auto G0Low16 = phys(TestRegister::G0Low16); + const auto G1 = phys(TestRegister::G1); + const auto G1Low32 = phys(TestRegister::G1Low32); + const auto G1High32 = phys(TestRegister::G1High32); + const auto G1Low16 = phys(TestRegister::G1Low16); + const auto StackPointer = phys(TestRegister::StackPointer); + const auto F0 = phys(TestRegister::F0); + const auto F1 = phys(TestRegister::F1); + + Description.RegisterClasses = { + registerClass(TestRegisterClass::GPR64, "GPR64", {G0, G1}, {G0, G1}, 64, + LaneMask::fromRaw(0xF), TestRegisterBank::GPR, + {TestSubReg::Low32, TestSubReg::High32, TestSubReg::Low16}, {}, true, true), + registerClass(TestRegisterClass::GPR64Alloc, "GPR64Alloc", {G0, G1}, {G1, G0}, 64, + LaneMask::fromRaw(0xF), TestRegisterBank::GPR, {}, {TestRegisterClass::GPR64}), + registerClass(TestRegisterClass::GPR32, "GPR32", {G0Low32, G0High32, G1Low32, G1High32}, + {G0Low32, G1Low32, G0High32, G1High32}, 32, LaneMask::fromRaw(0x3), + TestRegisterBank::GPR), + registerClass(TestRegisterClass::GPR32Low, "GPR32Low", {G0Low32, G1Low32}, {G0Low32, G1Low32}, + 32, LaneMask::fromRaw(0x3), TestRegisterBank::GPR, {TestSubReg::Low16}, + {TestRegisterClass::GPR32}), + registerClass(TestRegisterClass::GPR32High, "GPR32High", {G0High32, G1High32}, + {G0High32, G1High32}, 32, LaneMask::fromRaw(0x3), TestRegisterBank::GPR, {}, + {TestRegisterClass::GPR32}), + registerClass(TestRegisterClass::GPR16, "GPR16", {G0Low16, G1Low16}, {G0Low16, G1Low16}, 16, + LaneMask::fromRaw(0x1), TestRegisterBank::GPR), + registerClass(TestRegisterClass::FPR64, "FPR64", {F0, F1}, {F0, F1}, 64, + LaneMask::fromRaw(0x1), TestRegisterBank::FPR), + registerClass(TestRegisterClass::SpecialGPR64, "SpecialGPR64", {StackPointer}, {}, 64, + LaneMask::fromRaw(0xF), TestRegisterBank::GPR, {}, {}, false), + }; + + Description.SubRegClassMappings = { + {TestRegisterClass::GPR64, TestSubReg::Low32, TestRegisterClass::GPR32Low}, + {TestRegisterClass::GPR64, TestSubReg::High32, TestRegisterClass::GPR32High}, + {TestRegisterClass::GPR64, TestSubReg::Low16, TestRegisterClass::GPR16}, + {TestRegisterClass::GPR32Low, TestSubReg::Low16, TestRegisterClass::GPR16}, + }; + Description.RegisterBanks = { + {TestRegisterBank::GPR, + "GPR", + 64, + {TestRegisterClass::GPR64, TestRegisterClass::GPR64Alloc, TestRegisterClass::GPR32, + TestRegisterClass::GPR32Low, TestRegisterClass::GPR32High, TestRegisterClass::GPR16, + TestRegisterClass::SpecialGPR64}}, + {TestRegisterBank::FPR, "FPR", 64, {TestRegisterClass::FPR64}}, + }; + + return Description; +} + +Expected<TargetRegisterInfo> createTestTargetRegisterInfo() { + return TargetRegisterInfo::create(createTestTargetRegisterInfoDescription()); +} + +Expected<TargetDescription> createTestTargetDescription(InstructionSet Instructions) { + auto Registers = createTestTargetRegisterInfo(); + if (!Registers) + return std::unexpected(Registers.error()); + return TargetDescription::create(std::move(Instructions), std::move(*Registers)); +} + +std::shared_ptr<const RegisterMask> createTestCallPreservedMask() { + std::uint64_t Preserved = 0; + Preserved |= std::uint64_t{1} << TestRegister::G1; + Preserved |= std::uint64_t{1} << TestRegister::G1Low32; + Preserved |= std::uint64_t{1} << TestRegister::G1High32; + Preserved |= std::uint64_t{1} << TestRegister::G1Low16; + Preserved |= std::uint64_t{1} << TestRegister::StackPointer; + Preserved |= std::uint64_t{1} << TestRegister::F1; + return std::make_shared<const RegisterMask>(std::vector<std::uint64_t>{Preserved}); +} + +} // namespace rcc::test diff --git a/backend/unittests/Target/TestTarget.h b/backend/unittests/Target/TestTarget.h new file mode 100644 index 0000000..3c2aa51 --- /dev/null +++ b/backend/unittests/Target/TestTarget.h @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef HOME_RICHARD_CODE_RCC_PROJECT_BACKEND_UNITTESTS_TARGET_TESTTARGET_H +#define HOME_RICHARD_CODE_RCC_PROJECT_BACKEND_UNITTESTS_TARGET_TESTTARGET_H + +#include "rcc/CodeGen/InstructionDescriptor.h" +#include "rcc/CodeGen/RegisterMask.h" +#include "rcc/CodeGen/TargetDescription.h" +#include "rcc/CodeGen/TargetRegisterInfo.h" +#include "rcc/Support/Error.h" + +#include <cstdint> +#include <memory> + +namespace rcc::test { + +struct TestRegister final { + + static constexpr std::uint32_t G0 = 1; + static constexpr std::uint32_t G0Low32 = 2; + static constexpr std::uint32_t G0High32 = 3; + static constexpr std::uint32_t G0Low16 = 4; + static constexpr std::uint32_t G1 = 5; + static constexpr std::uint32_t G1Low32 = 6; + static constexpr std::uint32_t G1High32 = 7; + static constexpr std::uint32_t G1Low16 = 8; + static constexpr std::uint32_t StackPointer = 9; + static constexpr std::uint32_t F0 = 10; + static constexpr std::uint32_t F1 = 11; +}; + +struct TestSubReg final { + + static constexpr SubRegIndex Low32 = SubRegIndex::fromValue(1); + static constexpr SubRegIndex High32 = SubRegIndex::fromValue(2); + static constexpr SubRegIndex Low16 = SubRegIndex::fromValue(3); +}; + +struct TestRegisterBank final { + + static constexpr RegisterBankID GPR = RegisterBankID::fromValue(1); + static constexpr RegisterBankID FPR = RegisterBankID::fromValue(2); +}; + +struct TestRegisterClass final { + + static constexpr RegisterClassID GPR64 = RegisterClassID::fromValue(1); + static constexpr RegisterClassID GPR64Alloc = RegisterClassID::fromValue(2); + static constexpr RegisterClassID GPR32 = RegisterClassID::fromValue(3); + static constexpr RegisterClassID GPR32Low = RegisterClassID::fromValue(4); + static constexpr RegisterClassID GPR32High = RegisterClassID::fromValue(5); + static constexpr RegisterClassID GPR16 = RegisterClassID::fromValue(6); + static constexpr RegisterClassID FPR64 = RegisterClassID::fromValue(7); + static constexpr RegisterClassID SpecialGPR64 = RegisterClassID::fromValue(8); +}; + +[[nodiscard]] TargetRegisterInfoDesc createTestTargetRegisterInfoDescription(); +[[nodiscard]] Expected<TargetRegisterInfo> createTestTargetRegisterInfo(); +[[nodiscard]] Expected<TargetDescription> createTestTargetDescription(InstructionSet Instructions); +[[nodiscard]] std::shared_ptr<const RegisterMask> createTestCallPreservedMask(); + +} // namespace rcc::test + +#endif // HOME_RICHARD_CODE_RCC_PROJECT_BACKEND_UNITTESTS_TARGET_TESTTARGET_H |
