aboutsummaryrefslogtreecommitdiff
path: root/backend/unittests/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'backend/unittests/CodeGen')
-rw-r--r--backend/unittests/CodeGen/CompilationUnitTest.cpp26
-rw-r--r--backend/unittests/CodeGen/MachineDebugInfoTest.cpp35
-rw-r--r--backend/unittests/CodeGen/MachineFunctionRecordsTest.cpp6
-rw-r--r--backend/unittests/CodeGen/MachineValueTypesTest.cpp35
4 files changed, 86 insertions, 16 deletions
diff --git a/backend/unittests/CodeGen/CompilationUnitTest.cpp b/backend/unittests/CodeGen/CompilationUnitTest.cpp
index a31c9a8..141d6db 100644
--- a/backend/unittests/CodeGen/CompilationUnitTest.cpp
+++ b/backend/unittests/CodeGen/CompilationUnitTest.cpp
@@ -19,29 +19,34 @@ int fail(const char *Message) {
int main() {
rcc::CompilationUnit Unit;
- auto Empty = Unit.createMachineFunction("");
- if (Empty || Unit.functionCount() != 0)
- return fail("CompilationUnit must reject an empty function name atomically");
+ auto FirstAnonymous = Unit.createMachineFunction("");
+ auto SecondAnonymous = Unit.createMachineFunction("");
+ if (!FirstAnonymous || !SecondAnonymous || Unit.functionCount() != 2 ||
+ (*FirstAnonymous)->stableID().value() != 1 || (*SecondAnonymous)->stableID().value() != 2 ||
+ Unit.function("") != nullptr)
+ return fail("CompilationUnit must retain anonymous functions by order and StableID");
auto First = Unit.createMachineFunction("first");
- if (!First || (*First)->stableID().value() != 1)
+ if (!First || (*First)->stableID().value() != 3)
return fail("CompilationUnit must allocate the first stable function identity");
auto Duplicate = Unit.createMachineFunction("first");
- if (Duplicate || Unit.functionCount() != 1)
+ if (Duplicate || Unit.functionCount() != 3)
return fail("CompilationUnit must reject duplicate function names atomically");
auto Second = Unit.createMachineFunction("second");
- if (!Second || (*Second)->stableID().value() != 2)
+ if (!Second || (*Second)->stableID().value() != 4)
return fail("Rejected function creation must not consume a StableID");
- if (Unit.functionCount() != 2 || Unit.functionAt(0) != *First || Unit.functionAt(1) != *Second)
+ if (Unit.functionCount() != 4 || Unit.functionAt(0) != *FirstAnonymous ||
+ Unit.functionAt(1) != *SecondAnonymous || Unit.functionAt(2) != *First ||
+ Unit.functionAt(3) != *Second)
return fail("CompilationUnit must preserve function document order");
if (Unit.function("first") != *First || Unit.function("missing") != nullptr)
return fail("CompilationUnit must provide exact name lookup");
if (Unit.function((*Second)->stableID()) != *Second ||
Unit.function(rcc::MachineFunctionStableID::fromValue(99)) != nullptr)
return fail("CompilationUnit must provide exact StableID lookup");
- if (Unit.functionAt(2) != nullptr)
+ if (Unit.functionAt(4) != nullptr)
return fail("CompilationUnit must reject an out-of-range ordered lookup");
auto Zero = rcc::GlobalInitializer::zeroFill(4);
@@ -58,7 +63,7 @@ int main() {
return fail("CompilationUnit must own and index global objects");
auto ConflictingFunction = Unit.createMachineFunction("global");
- if (ConflictingFunction || Unit.functionCount() != 2)
+ if (ConflictingFunction || Unit.functionCount() != 4)
return fail("CompilationUnit must reject function/global symbol conflicts atomically");
rcc::GlobalObjectDesc ConflictingGlobal;
@@ -88,7 +93,8 @@ int main() {
return fail("A valid CompilationUnit must pass verification");
rcc::CompilationUnit Moved = std::move(Unit);
- if (Moved.functionCount() != 2 || Moved.function("first") != *First ||
+ if (Moved.functionCount() != 4 || Moved.functionAt(0) != *FirstAnonymous ||
+ Moved.functionAt(1) != *SecondAnonymous || Moved.function("first") != *First ||
Moved.function("second") != *Second || Moved.globalObject("global") != *Global)
return fail("Moving a CompilationUnit must preserve owned object addresses and indices");
Verification = Moved.verify();
diff --git a/backend/unittests/CodeGen/MachineDebugInfoTest.cpp b/backend/unittests/CodeGen/MachineDebugInfoTest.cpp
index 80a83e0..ae4d539 100644
--- a/backend/unittests/CodeGen/MachineDebugInfoTest.cpp
+++ b/backend/unittests/CodeGen/MachineDebugInfoTest.cpp
@@ -3,6 +3,7 @@
#include "rcc/CodeGen/MachineDebugInfo.h"
#include "Target/TestTarget.h"
+#include "rcc/CodeGen/GenericOpcodes.h"
#include "rcc/CodeGen/InstructionDescriptor.h"
#include "rcc/CodeGen/MachineBasicBlock.h"
#include "rcc/CodeGen/MachineFrameInfo.h"
@@ -26,8 +27,8 @@
namespace {
-constexpr std::uint32_t ValueOpcode = 1;
-constexpr std::uint32_t MetaOpcode = 2;
+constexpr std::uint32_t ValueOpcode = 1024;
+constexpr std::uint32_t MetaOpcode = 1025;
class TestContext final {
public:
@@ -64,7 +65,11 @@ private:
std::vector<rcc::InstructionDescriptor> Descriptors;
Descriptors.push_back(std::move(Value));
Descriptors.push_back(std::move(Meta));
- auto Instructions = rcc::InstructionSet::create(std::move(Descriptors));
+ std::vector<rcc::ImmediatePredicate> Predicates;
+ auto Generic = rcc::appendGenericInstructionInfo(Descriptors, Predicates);
+ if (!Generic)
+ return std::unexpected(Generic.error());
+ auto Instructions = rcc::InstructionSet::create(std::move(Descriptors), std::move(Predicates));
if (!Instructions)
return std::unexpected(Instructions.error());
return rcc::test::createTestTargetDescription(std::move(*Instructions));
@@ -419,6 +424,30 @@ void testVerifierFailures(TestContext &Context) {
return;
{
+ auto Function = createFunction(Context, 9, "missing-debug-location");
+ if (Function == nullptr)
+ return;
+ rcc::MachineBasicBlock *Block = appendBlock(Context, *Function);
+ if (Block == nullptr)
+ return;
+ auto Instruction = Function->createInstruction(rcc::opcode(rcc::GenericOpcode::DBG_VALUE));
+ if (!Instruction)
+ return;
+ for (const std::int64_t Value : {1, 2, 3, 4}) {
+ if (!(*Instruction)->addOperand(rcc::MachineOperand::immediate(Value)))
+ return;
+ }
+ Context.expect(Block->appendInstruction(**Instruction).has_value(),
+ "four-operand DBG_VALUE must be linkable for verifier coverage");
+ auto Verification = rcc::MachineVerifier::verify(*Function, *Target);
+ Context.expect(!Verification &&
+ Verification.error().message().find(
+ "Bad machine code: Missing DebugLoc for debug instruction\n"
+ "- instruction: DBG_VALUE 1, 2, 3, 4") != std::string_view::npos,
+ "complete DBG_VALUE must require a DebugLoc with LLVM-compatible diagnostics");
+ }
+
+ {
auto Function = createFunction(Context, 10, "debug-meta");
if (Function == nullptr)
return;
diff --git a/backend/unittests/CodeGen/MachineFunctionRecordsTest.cpp b/backend/unittests/CodeGen/MachineFunctionRecordsTest.cpp
index 8ca6bf3..621bd21 100644
--- a/backend/unittests/CodeGen/MachineFunctionRecordsTest.cpp
+++ b/backend/unittests/CodeGen/MachineFunctionRecordsTest.cpp
@@ -301,7 +301,7 @@ void testCrossReferenceFailures(TestContext &Context) {
}
{
- auto Function = createFunction(Context, 13, "unknown-bbid");
+ auto Function = createFunction(Context, 13, "dangling-prefetch-target");
if (Function == nullptr)
return;
rcc::MachineBasicBlock *Block = appendBlock(Context, *Function);
@@ -313,8 +313,8 @@ void testCrossReferenceFailures(TestContext &Context) {
.CallsiteIndex = 0,
})
.has_value() &&
- !rcc::MachineVerifier::verify(*Function, *Target),
- "prefetch targets must reference a live block bb_id");
+ rcc::MachineVerifier::verify(*Function, *Target).has_value(),
+ "prefetch targets may reference a bb_id without a machine block");
}
{
diff --git a/backend/unittests/CodeGen/MachineValueTypesTest.cpp b/backend/unittests/CodeGen/MachineValueTypesTest.cpp
index 40f121b..50482ba 100644
--- a/backend/unittests/CodeGen/MachineValueTypesTest.cpp
+++ b/backend/unittests/CodeGen/MachineValueTypesTest.cpp
@@ -119,6 +119,21 @@ void testMemoryValueTypes(TestContext &Context) {
Context.expect(Symbol.kind() == rcc::MemoryBase::Kind::GlobalSymbol,
"global memory base must preserve its kind");
Context.expect(Symbol.symbolName() == "global", "global memory base must preserve its symbol");
+
+ rcc::GenericConstantData PoisonPointer;
+ PoisonPointer.Type = rcc::GenericConstantType::pointer();
+ PoisonPointer.Kind = rcc::GenericConstantKind::Poison;
+ auto ConstantBase = rcc::MemoryBase::irConstant(PoisonPointer);
+ Context.expect(ConstantBase && ConstantBase->kind() == rcc::MemoryBase::Kind::IRConstant &&
+ ConstantBase->constantValue() != nullptr &&
+ *ConstantBase->constantValue() == PoisonPointer,
+ "IR-constant memory base must preserve a structured pointer constant");
+
+ rcc::GenericConstantData InvalidIntegerBase;
+ InvalidIntegerBase.Type = *rcc::GenericConstantType::integer(8);
+ InvalidIntegerBase.Kind = rcc::GenericConstantKind::Poison;
+ Context.expect(!rcc::MemoryBase::irConstant(std::move(InvalidIntegerBase)),
+ "IR-constant memory base must reject a non-pointer constant");
}
void testMachineMemOperand(TestContext &Context) {
@@ -172,6 +187,26 @@ void testMachineMemOperand(TestContext &Context) {
EmptySymbol.Base = rcc::MemoryBase::externalSymbol("");
Context.expect(!rcc::MachineMemOperand::create(EmptySymbol),
"empty MMO symbol base must be rejected");
+
+ auto OffsetAlignment = makeBasicLoadDescription();
+ OffsetAlignment.Offset = 12;
+ OffsetAlignment.Align = *rcc::Alignment::create(4);
+ OffsetAlignment.BaseAlign = *rcc::Alignment::create(8);
+ auto OffsetAligned = rcc::MachineMemOperand::create(OffsetAlignment);
+ Context.expect(OffsetAligned && OffsetAligned->description().BaseAlign &&
+ OffsetAligned->description().BaseAlign->bytes() == 8,
+ "MMO base alignment must derive effective alignment through its offset");
+
+ OffsetAlignment.Align = *rcc::Alignment::create(8);
+ Context.expect(!rcc::MachineMemOperand::create(OffsetAlignment),
+ "MMO alignment inconsistent with its base and offset must be rejected");
+
+ OffsetAlignment.Offset = 16;
+ OffsetAlignment.Align = *rcc::Alignment::create(8);
+ OffsetAlignment.BaseAlign = *rcc::Alignment::create(8);
+ auto RedundantBase = rcc::MachineMemOperand::create(OffsetAlignment);
+ Context.expect(RedundantBase && !RedundantBase->description().BaseAlign,
+ "MMO base alignment equal to effective alignment must canonicalize away");
}
} // namespace