176 lines · cpp
1//===- llvm/unittest/CodeGen/X86MCInstLowerTest.cpp2//-------------------------===//3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//9 10#include "TestAsmPrinter.h"11#include "llvm/AsmParser/Parser.h"12#include "llvm/CodeGen/AsmPrinter.h"13#include "llvm/CodeGen/MachineModuleInfo.h"14#include "llvm/CodeGen/TargetLowering.h"15#include "llvm/CodeGen/TargetPassConfig.h"16#include "llvm/IR/LegacyPassManager.h"17#include "llvm/IR/MDBuilder.h"18#include "llvm/IR/Module.h"19#include "llvm/MC/MCStreamer.h"20#include "llvm/MC/TargetRegistry.h"21#include "llvm/Support/SourceMgr.h"22#include "llvm/Support/TargetSelect.h"23#include "llvm/Target/TargetLoweringObjectFile.h"24#include "llvm/Target/TargetMachine.h"25#include "gtest/gtest.h"26 27namespace llvm {28 29class X86MCInstLowerTest : public testing::Test {30protected:31 static void SetUpTestCase() {32 InitializeAllTargetMCs();33 InitializeAllTargetInfos();34 InitializeAllTargets();35 InitializeAllAsmPrinters();36 }37 38 // Function to setup codegen pipeline and returns the AsmPrinter.39 AsmPrinter *addPassesToEmitFile(llvm::legacy::PassManagerBase &PM,40 llvm::raw_pwrite_stream &Out,41 llvm::CodeGenFileType FileType,42 llvm::MachineModuleInfoWrapperPass *MMIWP) {43 TargetPassConfig *PassConfig = TM->createPassConfig(PM);44 45 PassConfig->setDisableVerify(true);46 PM.add(PassConfig);47 PM.add(MMIWP);48 49 if (PassConfig->addISelPasses())50 return nullptr;51 52 PassConfig->addMachinePasses();53 PassConfig->setInitialized();54 55 MC.reset(new MCContext(TM->getTargetTriple(), TM->getMCAsmInfo(),56 TM->getMCRegisterInfo(), TM->getMCSubtargetInfo()));57 MC->setObjectFileInfo(TM->getObjFileLowering());58 TM->getObjFileLowering()->Initialize(*MC, *TM);59 MC->setObjectFileInfo(TM->getObjFileLowering());60 61 // Use a new MCContext for AsmPrinter for testing.62 // AsmPrinter.OutContext will be different from63 // MachineFunction's MCContext in MMIWP.64 Expected<std::unique_ptr<MCStreamer>> MCStreamerOrErr =65 TM->createMCStreamer(Out, nullptr, FileType, *MC);66 67 if (auto Err = MCStreamerOrErr.takeError())68 return nullptr;69 70 AsmPrinter *Printer =71 TM->getTarget().createAsmPrinter(*TM, std::move(*MCStreamerOrErr));72 73 if (!Printer)74 return nullptr;75 76 PM.add(Printer);77 78 return Printer;79 }80 81 void SetUp() override {82 // Module to compile.83 const char *FooStr = R""""(84 @G = external global i3285 86 define i32 @foo() {87 %1 = load i32, i32* @G; load the global variable88 %2 = call i32 @f()89 %3 = mul i32 %1, %290 ret i32 %391 }92 93 declare i32 @f() #094 )"""";95 StringRef AssemblyF(FooStr);96 97 // Get target triple for X86_6498 Triple TargetTriple("x86_64--");99 std::string Error;100 const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error);101 // Skip the test if target is not built.102 if (!T)103 GTEST_SKIP();104 105 // Get TargetMachine.106 // Use Reloc::Model::PIC_ and CodeModel::Model::Large107 // to get GOT during codegen as MO_ExternalSymbol.108 TargetOptions Options;109 TM = std::unique_ptr<TargetMachine>(T->createTargetMachine(110 TargetTriple, "", "", Options, Reloc::Model::PIC_,111 CodeModel::Model::Large, CodeGenOptLevel::Default));112 if (!TM)113 GTEST_SKIP();114 115 SMDiagnostic SMError;116 117 // Parse the module.118 M = parseAssemblyString(AssemblyF, SMError, Context);119 if (!M)120 report_fatal_error(SMError.getMessage());121 M->setDataLayout(TM->createDataLayout());122 123 // Get llvm::Function from M124 Foo = M->getFunction("foo");125 if (!Foo)126 report_fatal_error("foo?");127 128 // Prepare the MCContext for codegen M.129 // MachineFunction for Foo will have this MCContext.130 MCFoo.reset(new MCContext(TargetTriple, TM->getMCAsmInfo(),131 TM->getMCRegisterInfo(),132 TM->getMCSubtargetInfo()));133 MCFoo->setObjectFileInfo(TM->getObjFileLowering());134 TM->getObjFileLowering()->Initialize(*MCFoo, *TM);135 MCFoo->setObjectFileInfo(TM->getObjFileLowering());136 }137 138 LLVMContext Context;139 std::unique_ptr<TargetMachine> TM;140 std::unique_ptr<Module> M;141 142 std::unique_ptr<MCContext> MC;143 std::unique_ptr<MCContext> MCFoo;144 145 Function *Foo;146 std::unique_ptr<MachineFunction> MFFoo;147};148 149TEST_F(X86MCInstLowerTest, moExternalSymbol_MCSYMBOL) {150 151 MachineModuleInfoWrapperPass *MMIWP =152 new MachineModuleInfoWrapperPass(TM.get(), &*MCFoo);153 154 SmallString<1024> Buf;155 llvm::raw_svector_ostream OS(Buf);156 legacy::PassManager PassMgrF;157 158 AsmPrinter *Printer =159 addPassesToEmitFile(PassMgrF, OS, CodeGenFileType::AssemblyFile, MMIWP);160 PassMgrF.run(*M);161 162 // Check GOT MCSymbol is from Printer.OutContext.163 MCSymbol *GOTPrinterPtr =164 Printer->OutContext.lookupSymbol("_GLOBAL_OFFSET_TABLE_");165 166 // Check GOT MCSymbol is NOT from MachineFunction's MCContext.167 MCSymbol *GOTMFCtxPtr =168 MMIWP->getMMI().getMachineFunction(*Foo)->getContext().lookupSymbol(169 "_GLOBAL_OFFSET_TABLE_");170 171 EXPECT_NE(GOTPrinterPtr, nullptr);172 EXPECT_EQ(GOTMFCtxPtr, nullptr);173}174 175} // end namespace llvm176