Index: unittests/CodeGen/CMakeLists.txt =================================================================== --- unittests/CodeGen/CMakeLists.txt +++ unittests/CodeGen/CMakeLists.txt @@ -1,14 +1,18 @@ set(LLVM_LINK_COMPONENTS + ${LLVM_TARGETS_TO_BUILD} AsmPrinter CodeGen Core + MIRParser Support + Target ) set(CodeGenSources DIEHashTest.cpp LowLevelTypeTest.cpp MachineInstrBundleIteratorTest.cpp + MachineInstrTest.cpp ) add_llvm_unittest(CodeGenTests Index: unittests/CodeGen/MachineInstrTest.cpp =================================================================== --- /dev/null +++ unittests/CodeGen/MachineInstrTest.cpp @@ -0,0 +1,133 @@ +//===- MachineInstrTest.cpp -----------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MIRParser/MIRParser.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +/// Create a TargetMachine. As we lack a dedicated always available target for +/// unittests, pick one of the registered targets. +static std::unique_ptr createTargetMachine() { + InitializeAllTargets(); + InitializeAllTargetMCs(); + + // Pick the first target available; we don't need target-specific behavior. + const Target &T = *TargetRegistry::targets().begin(); + return std::unique_ptr( + T.createTargetMachine(/*TT=*/"", /*CPU=*/"", /*Features=*/"", + TargetOptions(), /*RelocModel=*/None)); +} + +class MachineInstrTest : public testing::Test { + LLVMContext Context; + std::unique_ptr TM; + +protected: + MachineInstrTest() : TM(createTargetMachine()) {} + + /// Run a test on a single MI, parsed from the MIR string \p MI, and, + /// optionally, the IR string \p IR. + void runTestOnMI(StringRef IR, StringRef MI, + std::function TestFTor) { + SmallString<160> S; + StringRef MIRCode = (R"IR( +--- | + declare void @f() +)IR" + IR + R"MIR( +... +name: f +body: | + bb.0: + )MIR" + MI + "\n...\n").toNullTerminatedStringRef(S); + + std::unique_ptr MBuffer = MemoryBuffer::getMemBuffer(MIRCode); + std::unique_ptr MIR = + createMIRParser(std::move(MBuffer), Context); + assert(MIR); + + std::unique_ptr M = MIR->parseLLVMModule(); + assert(M && "Failed to parse the MIR!"); + + M->setDataLayout(TM->createDataLayout()); + + auto MMI = make_unique(TM.get()); + MMI->setMachineFunctionInitializer(MIR.get()); + + MachineFunction &MF = MMI->getMachineFunction(*M->getFunction("f")); + assert(MF.size() == 1); + + MachineBasicBlock &MBB = MF.front(); + assert(MBB.size() == 1); + + TestFTor(MBB.front()); + } + + void runTestOnMI(StringRef MI, std::function TestFTor) { + runTestOnMI("", MI, TestFTor); + } +}; + +//===- Tests --------------------------------------------------------------===// + +/// Flush the stream \p OS, clear it, and return its current value. +static std::string takeContent(raw_string_ostream &OS) { + return std::move(OS.str()); +} + +/// Test the variants of MachineInstr::print. +TEST_F(MachineInstrTest, Print) { + std::string Buffer; + raw_string_ostream OS(Buffer); + + runTestOnMI("%0:_(s32) = IMPLICIT_DEF", [&](MachineInstr &MI) { + MI.print(OS); + EXPECT_EQ(takeContent(OS), "%vreg0(s32) = IMPLICIT_DEF;\n"); + + MI.print(OS, /*SkipOps=*/true); + EXPECT_EQ(takeContent(OS), "%vreg0(s32) = IMPLICIT_DEF"); + }); + + runTestOnMI(R"IR( + !llvm.dbg.cu = !{!1} + !llvm.module.flags = !{!0} + !0 = !{i32 2, !"Debug Info Version", i32 3} + + !1 = distinct !DICompileUnit(language: DW_LANG_C, file: !3, runtimeVersion: 1, enums: !2, retainedTypes: !2, globals: !2, imports: !2) + !2 = !{} + !3 = !DIFile(filename: "test.mir", directory: "/foo/bar") + !4 = distinct !DISubprogram(name: "f", scope: !3, file: !3, line: 1, type: !5, unit: !1, variables: !2) + !5 = !DISubroutineType(types: !2) + !6 = !DILocation(line: 72, scope: !4) +)IR", + "%0:_(s32) = G_CONSTANT 123, debug-location !6", [&](MachineInstr &MI) { + MI.print(OS); + EXPECT_EQ(takeContent(OS), + "%vreg0(s32) = G_CONSTANT 123; dbg:test.mir:72\n"); + + MI.print(OS, /*SkipOps=*/false, /*SkipDebugLoc=*/true); + EXPECT_EQ(takeContent(OS), "%vreg0(s32) = G_CONSTANT 123;"); + + MI.print(OS, /*SkipOps=*/true); + EXPECT_EQ(takeContent(OS), "%vreg0(s32) = G_CONSTANT"); + }); +} + +} // end namespace