
Reordering `OS` and `PassMgrF` should fix the asan failure that's caused by OS being destroyed before `PassMgrF` deletes the AsmPrinter. As shown in[ this asan run ](https://lab.llvm.org/buildbot/#/builders/52/builds/7340/steps/12/logs/stdio) ``` This frame has 15 object(s): [32, 48) 'PassMgrF' (line 154) [64, 1112) 'Buf' (line 155) [1248, 1304) 'OS' (line 156) <== Memory access at offset 1280 is inside this variable ``` which indicates an ordering problem. This should help to fix all the sanitizer failures caused by the test `X86MCInstLowerTest.cpp` that's introduced by [this PR](https://github.com/llvm/llvm-project/pull/133352#issuecomment-2780173791).
176 lines
5.4 KiB
C++
176 lines
5.4 KiB
C++
//===- 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
|