//===- 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> 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(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 TM; std::unique_ptr M; std::unique_ptr MC; std::unique_ptr MCFoo; Function *Foo; std::unique_ptr 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