| //===- llvm/unittest/CodeGen/X86MCInstLowerTest.cpp |
| //-------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "TestAsmPrinter.h" |
| #include "llvm/AsmParser/Parser.h" |
| #include "llvm/CodeGen/AsmPrinter.h" |
| #include "llvm/CodeGen/MachineModuleInfo.h" |
| #include "llvm/CodeGen/TargetLowering.h" |
| #include "llvm/CodeGen/TargetPassConfig.h" |
| #include "llvm/IR/LegacyPassManager.h" |
| #include "llvm/IR/MDBuilder.h" |
| #include "llvm/IR/Module.h" |
| #include "llvm/MC/MCStreamer.h" |
| #include "llvm/MC/TargetRegistry.h" |
| #include "llvm/Support/SourceMgr.h" |
| #include "llvm/Support/TargetSelect.h" |
| #include "llvm/Target/TargetLoweringObjectFile.h" |
| #include "llvm/Target/TargetMachine.h" |
| #include "gtest/gtest.h" |
| |
| namespace llvm { |
| |
| class X86MCInstLowerTest : public testing::Test { |
| protected: |
| static void SetUpTestCase() { |
| InitializeAllTargetMCs(); |
| InitializeAllTargetInfos(); |
| InitializeAllTargets(); |
| InitializeAllAsmPrinters(); |
| } |
| |
| // Function to setup codegen pipeline and returns the AsmPrinter. |
| AsmPrinter *addPassesToEmitFile(llvm::legacy::PassManagerBase &PM, |
| llvm::raw_pwrite_stream &Out, |
| llvm::CodeGenFileType FileType, |
| llvm::MachineModuleInfoWrapperPass *MMIWP) { |
| TargetPassConfig *PassConfig = TM->createPassConfig(PM); |
| |
| PassConfig->setDisableVerify(true); |
| PM.add(PassConfig); |
| PM.add(MMIWP); |
| |
| if (PassConfig->addISelPasses()) |
| return nullptr; |
| |
| PassConfig->addMachinePasses(); |
| PassConfig->setInitialized(); |
| |
| MC.reset(new MCContext(TM->getTargetTriple(), TM->getMCAsmInfo(), |
| TM->getMCRegisterInfo(), TM->getMCSubtargetInfo())); |
| MC->setObjectFileInfo(TM->getObjFileLowering()); |
| TM->getObjFileLowering()->Initialize(*MC, *TM); |
| MC->setObjectFileInfo(TM->getObjFileLowering()); |
| |
| // Use a new MCContext for AsmPrinter for testing. |
| // AsmPrinter.OutContext will be different from |
| // MachineFunction's MCContext in MMIWP. |
| Expected<std::unique_ptr<MCStreamer>> MCStreamerOrErr = |
| TM->createMCStreamer(Out, nullptr, FileType, *MC); |
| |
| if (auto Err = MCStreamerOrErr.takeError()) |
| return nullptr; |
| |
| AsmPrinter *Printer = |
| TM->getTarget().createAsmPrinter(*TM, std::move(*MCStreamerOrErr)); |
| |
| if (!Printer) |
| return nullptr; |
| |
| PM.add(Printer); |
| |
| return Printer; |
| } |
| |
| void SetUp() override { |
| // Module to compile. |
| const char *FooStr = R""""( |
| @G = external global i32 |
| |
| define i32 @foo() { |
| %1 = load i32, i32* @G; load the global variable |
| %2 = call i32 @f() |
| %3 = mul i32 %1, %2 |
| ret i32 %3 |
| } |
| |
| declare i32 @f() #0 |
| )""""; |
| StringRef AssemblyF(FooStr); |
| |
| // Get target triple for X86_64 |
| Triple TargetTriple("x86_64--"); |
| std::string Error; |
| const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error); |
| // Skip the test if target is not built. |
| if (!T) |
| GTEST_SKIP(); |
| |
| // Get TargetMachine. |
| // Use Reloc::Model::PIC_ and CodeModel::Model::Large |
| // to get GOT during codegen as MO_ExternalSymbol. |
| TargetOptions Options; |
| TM = std::unique_ptr<TargetMachine>(T->createTargetMachine( |
| TargetTriple, "", "", Options, Reloc::Model::PIC_, |
| CodeModel::Model::Large, CodeGenOptLevel::Default)); |
| if (!TM) |
| GTEST_SKIP(); |
| |
| SMDiagnostic SMError; |
| |
| // Parse the module. |
| M = parseAssemblyString(AssemblyF, SMError, Context); |
| if (!M) |
| report_fatal_error(SMError.getMessage()); |
| M->setDataLayout(TM->createDataLayout()); |
| |
| // Get llvm::Function from M |
| Foo = M->getFunction("foo"); |
| if (!Foo) |
| report_fatal_error("foo?"); |
| |
| // Prepare the MCContext for codegen M. |
| // MachineFunction for Foo will have this MCContext. |
| MCFoo.reset(new MCContext(TargetTriple, TM->getMCAsmInfo(), |
| TM->getMCRegisterInfo(), |
| TM->getMCSubtargetInfo())); |
| MCFoo->setObjectFileInfo(TM->getObjFileLowering()); |
| TM->getObjFileLowering()->Initialize(*MCFoo, *TM); |
| MCFoo->setObjectFileInfo(TM->getObjFileLowering()); |
| } |
| |
| LLVMContext Context; |
| std::unique_ptr<TargetMachine> TM; |
| std::unique_ptr<Module> M; |
| |
| std::unique_ptr<MCContext> MC; |
| std::unique_ptr<MCContext> MCFoo; |
| |
| Function *Foo; |
| std::unique_ptr<MachineFunction> MFFoo; |
| }; |
| |
| TEST_F(X86MCInstLowerTest, moExternalSymbol_MCSYMBOL) { |
| |
| MachineModuleInfoWrapperPass *MMIWP = |
| new MachineModuleInfoWrapperPass(TM.get(), &*MCFoo); |
| |
| SmallString<1024> Buf; |
| llvm::raw_svector_ostream OS(Buf); |
| legacy::PassManager PassMgrF; |
| |
| AsmPrinter *Printer = |
| addPassesToEmitFile(PassMgrF, OS, CodeGenFileType::AssemblyFile, MMIWP); |
| PassMgrF.run(*M); |
| |
| // Check GOT MCSymbol is from Printer.OutContext. |
| MCSymbol *GOTPrinterPtr = |
| Printer->OutContext.lookupSymbol("_GLOBAL_OFFSET_TABLE_"); |
| |
| // Check GOT MCSymbol is NOT from MachineFunction's MCContext. |
| MCSymbol *GOTMFCtxPtr = |
| MMIWP->getMMI().getMachineFunction(*Foo)->getContext().lookupSymbol( |
| "_GLOBAL_OFFSET_TABLE_"); |
| |
| EXPECT_NE(GOTPrinterPtr, nullptr); |
| EXPECT_EQ(GOTMFCtxPtr, nullptr); |
| } |
| |
| } // end namespace llvm |