diff options
| author | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-03 19:24:30 +0800 |
|---|---|---|
| committer | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-03 19:24:30 +0800 |
| commit | 432efe39315ed5ad0162f9c08dbf10941bc21dc1 (patch) | |
| tree | 46622290cabfaeb8f4db1729aca6f0725739e08c /backend/unittests/CodeGen | |
| parent | 6580ac1c05bd1cbccd2dcd71fd9c2a384ae3db56 (diff) | |
| download | rcc-project-432efe39315ed5ad0162f9c08dbf10941bc21dc1.tar.gz rcc-project-432efe39315ed5ad0162f9c08dbf10941bc21dc1.tar.xz | |
[CodeGen] Add target MIR text schema
Diffstat (limited to 'backend/unittests/CodeGen')
| -rw-r--r-- | backend/unittests/CodeGen/CMakeLists.txt | 15 | ||||
| -rw-r--r-- | backend/unittests/CodeGen/MachineFrameInfoTest.cpp | 21 | ||||
| -rw-r--r-- | backend/unittests/CodeGen/MachineFunctionClonerTest.cpp | 7 | ||||
| -rw-r--r-- | backend/unittests/CodeGen/TargetMIRTextInfoTest.cpp | 371 |
4 files changed, 406 insertions, 8 deletions
diff --git a/backend/unittests/CodeGen/CMakeLists.txt b/backend/unittests/CodeGen/CMakeLists.txt index 69f3646..ef96358 100644 --- a/backend/unittests/CodeGen/CMakeLists.txt +++ b/backend/unittests/CodeGen/CMakeLists.txt @@ -22,6 +22,7 @@ set( MachineValueTypesTest.cpp TargetConstantTest.cpp TargetFunctionStateTest.cpp + TargetMIRTextInfoTest.cpp TargetRegisterInfoTest.cpp ) @@ -253,6 +254,18 @@ add_test( COMMAND RCCBackendCodeGenTargetFunctionStateTests ) +add_executable(RCCBackendCodeGenTargetMIRTextInfoTests TargetMIRTextInfoTest.cpp) +rcc_backend_configure_target(RCCBackendCodeGenTargetMIRTextInfoTests) +target_link_libraries( + RCCBackendCodeGenTargetMIRTextInfoTests + PRIVATE RCCBackend::CodeGen RCCBackend::TestTarget +) + +add_test( + NAME RCCBackend.CodeGen.TargetMIRTextInfo + COMMAND RCCBackendCodeGenTargetMIRTextInfoTests +) + add_executable(RCCBackendCodeGenTargetRegisterInfoTests TargetRegisterInfoTest.cpp) rcc_backend_configure_target(RCCBackendCodeGenTargetRegisterInfoTests) target_link_libraries( @@ -286,6 +299,7 @@ rcc_backend_register_format_files( "${CMAKE_CURRENT_SOURCE_DIR}/MachineValueTypesTest.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/TargetConstantTest.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/TargetFunctionStateTest.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/TargetMIRTextInfoTest.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/TargetRegisterInfoTest.cpp" ) rcc_backend_register_tidy_files( @@ -309,5 +323,6 @@ rcc_backend_register_tidy_files( "${CMAKE_CURRENT_SOURCE_DIR}/MachineValueTypesTest.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/TargetConstantTest.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/TargetFunctionStateTest.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/TargetMIRTextInfoTest.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/TargetRegisterInfoTest.cpp" ) diff --git a/backend/unittests/CodeGen/MachineFrameInfoTest.cpp b/backend/unittests/CodeGen/MachineFrameInfoTest.cpp index c9289c7..c67339d 100644 --- a/backend/unittests/CodeGen/MachineFrameInfoTest.cpp +++ b/backend/unittests/CodeGen/MachineFrameInfoTest.cpp @@ -149,15 +149,24 @@ void testInvalidDescriptions(TestContext &Context) { Frame.object(*DebugIndex)->description()->DebugInfo == DebugObject.DebugInfo, "stack object debug information must remain structured"); - Context.expect(!rcc::StackID::targetStack(4), "target stack IDs must not overlap built-in IDs"); - auto TargetStack = rcc::StackID::targetStack(256); + Context.expect( + rcc::StackID::fromValue(0) && rcc::StackID::fromValue(4) && rcc::StackID::fromValue(255) && + !rcc::StackID::fromValue(5) && !rcc::StackID::fromValue(256) && + rcc::parseStackIDName("sgpr-spill") == rcc::StackID::sgprSpillStack() && + rcc::parseStackIDName("scalable-vector") == rcc::StackID::scalableVectorStack() && + rcc::parseStackIDName("scalable-predicate-vector") == + rcc::StackID::scalablePredicateVectorStack() && + rcc::parseStackIDName("wasm-local") == rcc::StackID::wasmLocalStack() && + rcc::parseStackIDName("noalloc") == rcc::StackID::noAllocStack() && + !rcc::parseStackIDName("safe") && + rcc::getStackIDName(rcc::StackID::noAllocStack()) == "noalloc", + "stack IDs and names must match the fixed LLVM MIR enumeration"); + auto Target = fixedObject(8, 8); Target.Kind = rcc::StackObjectKind::Target; - if (TargetStack) - Target.Stack = *TargetStack; + Target.Stack = rcc::StackID::sgprSpillStack(); auto TargetIndex = Frame.createObject(Target); - Context.expect(TargetStack && TargetIndex, - "target stack identity must admit target stack objects"); + Context.expect(TargetIndex.has_value(), "special stack identity must admit target stack objects"); auto Unresolved = Frame.createObject(fixedObject(8, 8)); Context.expect(Unresolved && !Frame.freeze(16, *rcc::Alignment::create(8)) && !Frame.isFrozen() && diff --git a/backend/unittests/CodeGen/MachineFunctionClonerTest.cpp b/backend/unittests/CodeGen/MachineFunctionClonerTest.cpp index d330f6a..a019c8b 100644 --- a/backend/unittests/CodeGen/MachineFunctionClonerTest.cpp +++ b/backend/unittests/CodeGen/MachineFunctionClonerTest.cpp @@ -268,6 +268,7 @@ createFunction(TestContext &Context, std::string Name, std::uint64_t ID) { Description.Align = *rcc::Alignment::create(8); Description.Base = std::move(Base); Description.Offset = -8; + Description.TargetFlags = 0x3; return Description; } @@ -383,7 +384,8 @@ struct SourceFixture final { const auto RegClass = rcc::RegisterClassID::fromValue(2); for (const rcc::Register Reg : {Fixture.Value, Fixture.CopyValue}) { Context.expect(Function.registerInfo().setRegisterBank(Reg, Bank).has_value() && - Function.registerInfo().setRegisterClass(Reg, RegClass).has_value(), + Function.registerInfo().setRegisterClass(Reg, RegClass).has_value() && + Function.registerInfo().setTargetRegisterFlags(Reg, 0x3).has_value(), "source vreg constraints must be recorded"); } @@ -591,7 +593,8 @@ void testDeepClone(TestContext &Context) { SourceInfo->get().Type == DestinationInfo->get().Type && SourceInfo->get().Bank == DestinationInfo->get().Bank && SourceInfo->get().RegClass == DestinationInfo->get().RegClass && - SourceInfo->get().AllocationHints == DestinationInfo->get().AllocationHints, + SourceInfo->get().AllocationHints == DestinationInfo->get().AllocationHints && + SourceInfo->get().TargetFlags == DestinationInfo->get().TargetFlags, "clone must preserve vreg type and allocation constraints"); Context.expect(Destination.registerInfo().liveIns().size() == 1 && Destination.registerInfo().liveIns()[0].InitialVirtualRegister == NewValue && diff --git a/backend/unittests/CodeGen/TargetMIRTextInfoTest.cpp b/backend/unittests/CodeGen/TargetMIRTextInfoTest.cpp new file mode 100644 index 0000000..d7e2f13 --- /dev/null +++ b/backend/unittests/CodeGen/TargetMIRTextInfoTest.cpp @@ -0,0 +1,371 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "rcc/CodeGen/TargetMIRTextInfo.h" + +#include "Target/TestTarget.h" +#include "rcc/CodeGen/InstructionDescriptor.h" +#include "rcc/CodeGen/MachineCFIInfo.h" +#include "rcc/CodeGen/MachineFunction.h" +#include "rcc/CodeGen/MachineMemOperand.h" +#include "rcc/CodeGen/MachineOperand.h" +#include "rcc/CodeGen/MachineRegisterInfo.h" +#include "rcc/CodeGen/TargetDescription.h" +#include "rcc/CodeGen/TargetRegisterInfo.h" + +#include <array> +#include <cstdint> +#include <iostream> +#include <memory> +#include <span> +#include <string_view> +#include <utility> +#include <vector> + +namespace { + +class TestContext final { +public: + void expect(bool Condition, std::string_view Message) { + if (Condition) + return; + std::cerr << Message << '\n'; + ++FailureCount; + } + + [[nodiscard]] int result() const noexcept { + return FailureCount == 0 ? 0 : 1; + } + +private: + int FailureCount = 0; +}; + +[[nodiscard]] rcc::PhysicalRegister phys(std::uint32_t Number) { + return *rcc::PhysicalRegister::create(Number); +} + +void testTargetRegisterNames(TestContext &Context) { + auto Registers = rcc::test::createTestTargetRegisterInfo(); + Context.expect(Registers.has_value(), "TestTarget register schema must be valid"); + if (!Registers) + return; + + const auto G0 = phys(rcc::test::TestRegister::G0); + Context.expect(Registers->physicalRegister("g0") != nullptr && + Registers->physicalRegister("G0") == nullptr && + Registers->physicalRegisterMIRName(G0) == "g0", + "physical register MIR names must be canonical lowercase names"); + Context.expect(Registers->subRegIndex("low32") != nullptr && + Registers->subRegIndex("LOW32") == nullptr, + "subregister MIR names must retain their exact target spelling"); + Context.expect(Registers->registerClass("gpr64") != nullptr && + Registers->registerClass("GPR64") == nullptr && + Registers->registerClassMIRName(rcc::test::TestRegisterClass::GPR64) == + "gpr64", + "register class MIR names must be canonical lowercase names"); + Context.expect(Registers->registerBank("gpr") != nullptr && + Registers->registerBank("GPR") == nullptr && + Registers->registerBankMIRName(rcc::test::TestRegisterBank::GPR) == "gpr", + "register bank MIR names must be canonical lowercase names"); +} + +void testTextSchemaQueries(TestContext &Context) { + auto Registers = rcc::test::createTestTargetRegisterInfo(); + if (!Registers) + return; + auto Text = rcc::TargetMIRTextInfo::create(rcc::test::createTestTargetMIRTextInfoDescription(), + *Registers); + Context.expect(Text.has_value(), "TestTarget MIR text schema must be valid"); + if (!Text) + return; + + const auto Preserved = rcc::test::createTestCallPreservedMask(); + const auto NamedMask = Text->registerMask("test-preserved"); + Context.expect(NamedMask && *NamedMask == *Preserved && !Text->registerMask("Test-Preserved") && + Text->registerMaskName(*Preserved) == "test-preserved", + "named register masks must use one canonical lowercase spelling"); + + Context.expect(Text->targetIndex("test-index") == rcc::TargetIndex::fromValue(0) && + Text->targetIndexName(rcc::TargetIndex::fromValue(0)) == "test-index", + "target index zero must remain a valid named target index"); + Context.expect(Text->directOperandFlag("test-direct-three") == 0x3 && + Text->bitmaskOperandFlag("test-bit-four") == 0x4, + "direct and bitmask target flags must retain distinct registries"); + + auto OperandNames = Text->operandFlagNames(0xD); + Context.expect(OperandNames && + *OperandNames == std::vector<std::string_view>( + {"test-direct-one", "test-bit-four", "test-bit-eight"}), + "operand flag decomposition must be canonical and declaration ordered"); + Context.expect(!Text->operandFlagNames(0x10), + "operand flag decomposition must reject unknown bits"); + + auto MMONames = Text->machineMemOperandFlagNames(0x3); + auto VRegNames = Text->virtualRegisterFlagNames(0x3); + Context.expect( + MMONames && *MMONames == std::vector<std::string_view>({"test-mmo-one", "test-mmo-two"}) && + VRegNames && + *VRegNames == std::vector<std::string_view>({"test-vreg-one", "test-vreg-two"}) && + !Text->machineMemOperandFlagNames(0x4) && !Text->virtualRegisterFlagNames(0x4), + "MMO and virtual-register flags must reject every unregistered bit"); + + Context.expect(Text->intrinsic("llvm.test.seven") == rcc::IntrinsicID::fromValue(7) && + Text->intrinsicName(rcc::IntrinsicID::fromValue(17)) == "llvm.test.seventeen", + "intrinsic names and strong IDs must round-trip"); + + const auto G0 = phys(rcc::test::TestRegister::G0); + Context.expect(Text->dwarfRegister(G0) == rcc::test::TestRegister::G0 && + Text->physicalRegister(rcc::test::TestRegister::G0) == G0, + "CFI register mappings must support both physical and DWARF lookup"); + Context.expect(Text->supportsStackID(rcc::StackID::defaultStack()) && + Text->supportsStackID(rcc::StackID::noAllocStack()) && + !Text->supportsStackID(rcc::StackID::sgprSpillStack()), + "target stack support must be explicit and include fixed baseline defaults"); +} + +void testTextSchemaRejection(TestContext &Context) { + auto Registers = rcc::test::createTestTargetRegisterInfo(); + if (!Registers) + return; + auto Reject = [&Context, &Registers](rcc::TargetMIRTextInfoDesc Description, + std::string_view Message) { + Context.expect(!rcc::TargetMIRTextInfo::create(std::move(Description), *Registers), Message); + }; + + { + auto Description = rcc::test::createTestTargetMIRTextInfoDescription(); + Description.RegisterMasks.push_back( + {"TEST-PRESERVED", + std::make_shared<const rcc::RegisterMask>(std::vector<std::uint64_t>{})}); + Reject(std::move(Description), "register mask names must be unique case-insensitively"); + } + { + auto Description = rcc::test::createTestTargetMIRTextInfoDescription(); + Description.RegisterMasks.push_back({"other-mask", rcc::test::createTestCallPreservedMask()}); + Reject(std::move(Description), "register mask values must have one canonical name"); + } + { + auto Description = rcc::test::createTestTargetMIRTextInfoDescription(); + Description.RegisterMasks.front().Mask = std::make_shared<const rcc::RegisterMask>( + std::vector<std::uint64_t>{std::uint64_t{1} << 63U}); + Reject(std::move(Description), "named masks must reject unknown physical registers"); + } + { + auto Description = rcc::test::createTestTargetMIRTextInfoDescription(); + Description.TargetIndices.push_back({"other-index", rcc::TargetIndex::fromValue(0)}); + Reject(std::move(Description), "target index values must be unique"); + } + { + auto Description = rcc::test::createTestTargetMIRTextInfoDescription(); + Description.DirectOperandFlagMask = 0; + Reject(std::move(Description), "direct flags require a direct flag mask"); + } + { + auto Description = rcc::test::createTestTargetMIRTextInfoDescription(); + Description.DirectOperandFlags.front().Value = 0x4; + Reject(std::move(Description), "direct flags must remain inside their direct field"); + } + { + auto Description = rcc::test::createTestTargetMIRTextInfoDescription(); + Description.BitmaskOperandFlags.front().Value = 0xC; + Reject(std::move(Description), "bitmask operand flags must contain one bit"); + } + { + auto Description = rcc::test::createTestTargetMIRTextInfoDescription(); + Description.MachineMemOperandFlags.front().Value = 0x3; + Reject(std::move(Description), "MMO target flags must contain one bit"); + } + { + auto Description = rcc::test::createTestTargetMIRTextInfoDescription(); + Description.VirtualRegisterFlags.back().Value = Description.VirtualRegisterFlags.front().Value; + Reject(std::move(Description), "virtual-register target flag values must be unique"); + } + { + auto Description = rcc::test::createTestTargetMIRTextInfoDescription(); + Description.Intrinsics.front().Name = "test.not-an-intrinsic"; + Reject(std::move(Description), "intrinsic names must use the llvm namespace"); + } + { + auto Description = rcc::test::createTestTargetMIRTextInfoDescription(); + Description.CFIRegisters[1].DwarfRegister = Description.CFIRegisters[0].DwarfRegister; + Reject(std::move(Description), + "a DWARF register must not have multiple canonical physical registers"); + } + { + auto Description = rcc::test::createTestTargetMIRTextInfoDescription(); + Description.CFIRegisters.front().IsCanonical = false; + Reject(std::move(Description), + "every referenced DWARF register must have a canonical physical register"); + } + { + auto Description = rcc::test::createTestTargetMIRTextInfoDescription(); + Description.CFIRegisters.front().Register = phys(99); + Reject(std::move(Description), "CFI mappings must reject unknown physical registers"); + } + { + auto Description = rcc::test::createTestTargetMIRTextInfoDescription(); + Description.FunctionStateType = rcc::TargetFunctionStateTypeID{}; + Reject(std::move(Description), "target function state schemas require a nonzero TypeID"); + } + { + auto Description = rcc::test::createTestTargetMIRTextInfoDescription(); + Description.SupportedStackIDs.pop_back(); + Reject(std::move(Description), "targets must support the noalloc stack ID"); + } + { + auto Description = rcc::test::createTestTargetMIRTextInfoDescription(); + Description.SupportedStackIDs.push_back(rcc::StackID::defaultStack()); + Reject(std::move(Description), "supported stack IDs must be unique"); + } + + { + auto Description = rcc::test::createTestTargetMIRTextInfoDescription(); + Description.CFIRegisters[1].DwarfRegister = Description.CFIRegisters[0].DwarfRegister; + Description.CFIRegisters[1].IsCanonical = false; + auto Text = rcc::TargetMIRTextInfo::create(std::move(Description), *Registers); + Context.expect(Text && + Text->dwarfRegister(phys(rcc::test::TestRegister::G0Low32)) == + rcc::test::TestRegister::G0 && + Text->physicalRegister(rcc::test::TestRegister::G0) == + phys(rcc::test::TestRegister::G0), + "noncanonical physical aliases must map to one canonical DWARF register"); + } + + { + auto Description = rcc::test::createTestTargetRegisterInfoDescription(); + Description.PhysicalRegisters[1].Name = "G0"; + Context.expect(!rcc::TargetRegisterInfo::create(std::move(Description)), + "physical register names must be case-insensitively unique"); + } + { + auto Description = rcc::test::createTestTargetRegisterInfoDescription(); + Description.RegisterClasses[1].Name = "gpr64"; + Context.expect(!rcc::TargetRegisterInfo::create(std::move(Description)), + "register class names must be case-insensitively unique"); + } + { + auto Description = rcc::test::createTestTargetRegisterInfoDescription(); + Description.RegisterBanks[1].Name = "gpr"; + Context.expect(!rcc::TargetRegisterInfo::create(std::move(Description)), + "register bank names must be case-insensitively unique"); + } +} + +void testSemanticValidation(TestContext &Context) { + rcc::OperandDescriptor Operand; + Operand.Kinds = {rcc::MachineOperand::Kind::Immediate}; + Operand.AllowedTargetFlags = 0xF; + + rcc::InstructionDescriptor Instruction; + Instruction.InstructionOpcode = rcc::Opcode::fromValue(1); + Instruction.Name = "TEST_LOAD_IMM"; + Instruction.Operands.push_back(Operand); + Instruction.Flags = { + rcc::InstructionFlag::ProducesCode, + rcc::InstructionFlag::MayLoad, + }; + Instruction.RequiresMemoryOperands = true; + + auto Instructions = rcc::InstructionSet::create({std::move(Instruction)}); + if (!Instructions) + return; + auto Target = rcc::test::createTestTargetDescription(std::move(*Instructions)); + auto Function = + rcc::MachineFunction::create("schema_validation", rcc::MachineFunctionStableID::fromValue(1)); + Context.expect(Target.has_value() && Function.has_value(), + "semantic target schema fixture must be constructible"); + if (!Target || !Function) + return; + + auto Reg = (*Function)->registerInfo().createVirtualRegister(); + Context.expect(Reg && (*Function)->registerInfo().setTargetRegisterFlags(*Reg, 0x3).has_value() && + Target->validateRegisterInfo((*Function)->registerInfo()).has_value(), + "registered virtual-register target flags must pass target validation"); + if (Reg) { + Context.expect((*Function)->registerInfo().setTargetRegisterFlags(*Reg, 0x4).has_value() && + !Target->validateRegisterInfo((*Function)->registerInfo()), + "unregistered virtual-register target flags must fail target validation"); + Context.expect( + (*Function)->registerInfo().clearTargetRegisterFlags(*Reg).has_value(), + "semantic validation fixture must restore registered virtual-register target flags"); + } + + const rcc::MachineOperand ValidOperand = rcc::MachineOperand::immediate(7, 0x5); + const rcc::MachineOperand InvalidOperand = rcc::MachineOperand::immediate(7, 0x10); + Context.expect( + Target->validateExplicitOperands(rcc::Opcode::fromValue(1), + std::span<const rcc::MachineOperand>(&ValidOperand, 1), + (*Function)->registerInfo()) + .has_value() && + !Target->validateExplicitOperands( + rcc::Opcode::fromValue(1), std::span<const rcc::MachineOperand>(&InvalidOperand, 1), + (*Function)->registerInfo()), + "machine operands must use only descriptor-allowed serializable target flags"); + + rcc::MachineMemOperandDesc MemoryDescription; + MemoryDescription.Accesses = {rcc::MemoryAccessFlag::Load}; + MemoryDescription.Size = *rcc::MemorySize::fixed(8); + MemoryDescription.Align = *rcc::Alignment::create(8); + MemoryDescription.TargetFlags = 0x3; + auto ValidMemory = rcc::MachineMemOperand::create(MemoryDescription); + MemoryDescription.TargetFlags = 0x4; + auto InvalidMemory = rcc::MachineMemOperand::create(MemoryDescription); + if (ValidMemory && InvalidMemory) { + const std::array<const rcc::MachineMemOperand *, 1> ValidOperands{&*ValidMemory}; + const std::array<const rcc::MachineMemOperand *, 1> InvalidOperands{&*InvalidMemory}; + Context.expect( + Target->validateMemOperands(rcc::Opcode::fromValue(1), ValidOperands).has_value() && + !Target->validateMemOperands(rcc::Opcode::fromValue(1), InvalidOperands), + "machine memory operands must use only registered target flags"); + } + + rcc::MachineCFIInfo CFI; + auto CFIIndex = CFI.addInstruction( + rcc::MachineCFIInstruction::sameValue(rcc::DwarfRegisterNumber::fromValue(99))); + Context.expect(CFIIndex && !Target->validateCFIInfo(CFI), + "CFI instructions must reject unmapped DWARF registers"); + + rcc::MachineFrameInfo Frame; + rcc::StackObjectDesc StackObject; + StackObject.Kind = rcc::StackObjectKind::Target; + StackObject.Size = 8; + StackObject.Align = *rcc::Alignment::create(8); + StackObject.Stack = rcc::StackID::sgprSpillStack(); + auto StackIndex = Frame.createObject(StackObject); + Context.expect(StackIndex && !Target->validateFrameInfo(Frame), + "frame objects must reject stack IDs unsupported by the target"); + + rcc::OperandDescriptor BadOperand; + BadOperand.Kinds = {rcc::MachineOperand::Kind::Immediate}; + BadOperand.AllowedTargetFlags = 0x10; + rcc::InstructionDescriptor BadInstruction; + BadInstruction.InstructionOpcode = rcc::Opcode::fromValue(2); + BadInstruction.Name = "TEST_BAD_FLAGS"; + BadInstruction.Operands.push_back(BadOperand); + BadInstruction.Flags = {rcc::InstructionFlag::ProducesCode}; + auto BadInstructions = rcc::InstructionSet::create({std::move(BadInstruction)}); + Context.expect(BadInstructions && + !rcc::test::createTestTargetDescription(std::move(*BadInstructions)), + "target construction must reject operand flag bits outside its text schema"); + + auto PartialDescription = rcc::test::createTestTargetMIRTextInfoDescription(); + PartialDescription.DirectOperandFlags.erase(PartialDescription.DirectOperandFlags.begin() + 1, + PartialDescription.DirectOperandFlags.end()); + auto Registers = rcc::test::createTestTargetRegisterInfo(); + auto PartialText = + Registers ? rcc::TargetMIRTextInfo::create(std::move(PartialDescription), *Registers) + : rcc::Expected<rcc::TargetMIRTextInfo>(std::unexpected(Registers.error())); + Context.expect(PartialText && !PartialText->validateOperandFlags(0x2), + "unused direct-field encodings must remain invalid"); +} + +} // namespace + +int main() { + TestContext Context; + testTargetRegisterNames(Context); + testTextSchemaQueries(Context); + testTextSchemaRejection(Context); + testSemanticValidation(Context); + return Context.result(); +} |
