[SystemZ] Emit EXRL target instructions before text section is ended.

SystemZ adds the EXRL target instructions in the end of each file. This must
be done before debug info emission since that may end the text section, and
therefore this is now done in emitConstantPools() (instead of in
emitEndOfAsmFile).

Review: Ulrich Weigand

Differential Revision: https://reviews.llvm.org/D109513
This commit is contained in:
Jonas Paulsson 2021-09-09 17:26:50 +02:00
parent ea27dd7497
commit a48b43f981
5 changed files with 103 additions and 45 deletions

View File

@ -11,6 +11,7 @@
#include "SystemZMCAsmInfo.h"
#include "SystemZTargetStreamer.h"
#include "TargetInfo/SystemZTargetInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
@ -183,6 +184,21 @@ static MCInstPrinter *createSystemZMCInstPrinter(const Triple &T,
return new SystemZInstPrinter(MAI, MII, MRI);
}
void SystemZTargetStreamer::emitConstantPools() {
// Emit EXRL target instructions.
if (EXRLTargets2Sym.empty())
return;
// Switch to the .text section.
const MCObjectFileInfo &OFI = *Streamer.getContext().getObjectFileInfo();
Streamer.SwitchSection(OFI.getTextSection());
for (auto &I : EXRLTargets2Sym) {
Streamer.emitLabel(I.second);
const MCInstSTIPair &MCI_STI = I.first;
Streamer.emitInstruction(MCI_STI.first, *MCI_STI.second);
}
EXRLTargets2Sym.clear();
}
namespace {
class SystemZTargetAsmStreamer : public SystemZTargetStreamer {
formatted_raw_ostream &OS;

View File

@ -549,15 +549,17 @@ void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
Register SrcReg = MI->getOperand(4).getReg();
int64_t SrcDisp = MI->getOperand(5).getImm();
SystemZTargetStreamer *TS = getTargetStreamer();
MCSymbol *DotSym = nullptr;
MCInst ET = MCInstBuilder(TargetInsOpc).addReg(DestReg)
.addImm(DestDisp).addImm(1).addReg(SrcReg).addImm(SrcDisp);
MCInstSTIPair ET_STI(ET, &MF->getSubtarget());
EXRLT2SymMap::iterator I = EXRLTargets2Sym.find(ET_STI);
if (I != EXRLTargets2Sym.end())
SystemZTargetStreamer::MCInstSTIPair ET_STI(ET, &MF->getSubtarget());
SystemZTargetStreamer::EXRLT2SymMap::iterator I =
TS->EXRLTargets2Sym.find(ET_STI);
if (I != TS->EXRLTargets2Sym.end())
DotSym = I->second;
else
EXRLTargets2Sym[ET_STI] = DotSym = OutContext.createTempSymbol();
TS->EXRLTargets2Sym[ET_STI] = DotSym = OutContext.createTempSymbol();
const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
EmitToStreamer(
*OutStreamer,
@ -722,19 +724,6 @@ void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
getSubtargetInfo());
}
void SystemZAsmPrinter::emitEXRLTargetInstructions() {
if (EXRLTargets2Sym.empty())
return;
// Switch to the .text section.
OutStreamer->SwitchSection(getObjFileLowering().getTextSection());
for (auto &I : EXRLTargets2Sym) {
OutStreamer->emitLabel(I.second);
const MCInstSTIPair &MCI_STI = I.first;
OutStreamer->emitInstruction(MCI_STI.first, *MCI_STI.second);
}
EXRLTargets2Sym.clear();
}
// Convert a SystemZ-specific constant pool modifier into the associated
// MCSymbolRefExpr variant kind.
static MCSymbolRefExpr::VariantKind
@ -793,7 +782,6 @@ bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
}
void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
emitEXRLTargetInstructions();
emitStackMaps(SM);
}

View File

@ -11,6 +11,7 @@
#include "SystemZMCInstLower.h"
#include "SystemZTargetMachine.h"
#include "SystemZTargetStreamer.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/StackMaps.h"
#include "llvm/MC/MCInstBuilder.h"
@ -27,32 +28,11 @@ class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
private:
StackMaps SM;
typedef std::pair<MCInst, const MCSubtargetInfo *> MCInstSTIPair;
struct CmpMCInst {
bool operator()(const MCInstSTIPair &MCI_STI_A,
const MCInstSTIPair &MCI_STI_B) const {
if (MCI_STI_A.second != MCI_STI_B.second)
return uintptr_t(MCI_STI_A.second) < uintptr_t(MCI_STI_B.second);
const MCInst &A = MCI_STI_A.first;
const MCInst &B = MCI_STI_B.first;
assert(A.getNumOperands() == B.getNumOperands() &&
A.getNumOperands() == 5 && A.getOperand(2).getImm() == 1 &&
B.getOperand(2).getImm() == 1 && "Unexpected EXRL target MCInst");
if (A.getOpcode() != B.getOpcode())
return A.getOpcode() < B.getOpcode();
if (A.getOperand(0).getReg() != B.getOperand(0).getReg())
return A.getOperand(0).getReg() < B.getOperand(0).getReg();
if (A.getOperand(1).getImm() != B.getOperand(1).getImm())
return A.getOperand(1).getImm() < B.getOperand(1).getImm();
if (A.getOperand(3).getReg() != B.getOperand(3).getReg())
return A.getOperand(3).getReg() < B.getOperand(3).getReg();
if (A.getOperand(4).getImm() != B.getOperand(4).getImm())
return A.getOperand(4).getImm() < B.getOperand(4).getImm();
return false;
}
};
typedef std::map<MCInstSTIPair, MCSymbol *, CmpMCInst> EXRLT2SymMap;
EXRLT2SymMap EXRLTargets2Sym;
SystemZTargetStreamer *getTargetStreamer() {
MCTargetStreamer *TS = OutStreamer->getTargetStreamer();
assert(TS && "do not have a target streamer");
return static_cast<SystemZTargetStreamer *>(TS);
}
public:
SystemZAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
@ -77,7 +57,6 @@ private:
void LowerFENTRY_CALL(const MachineInstr &MI, SystemZMCInstLower &MCIL);
void LowerSTACKMAP(const MachineInstr &MI);
void LowerPATCHPOINT(const MachineInstr &MI, SystemZMCInstLower &Lower);
void emitEXRLTargetInstructions();
};
} // end namespace llvm

View File

@ -18,6 +18,35 @@ class SystemZTargetStreamer : public MCTargetStreamer {
public:
SystemZTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}
typedef std::pair<MCInst, const MCSubtargetInfo *> MCInstSTIPair;
struct CmpMCInst {
bool operator()(const MCInstSTIPair &MCI_STI_A,
const MCInstSTIPair &MCI_STI_B) const {
if (MCI_STI_A.second != MCI_STI_B.second)
return uintptr_t(MCI_STI_A.second) < uintptr_t(MCI_STI_B.second);
const MCInst &A = MCI_STI_A.first;
const MCInst &B = MCI_STI_B.first;
assert(A.getNumOperands() == B.getNumOperands() &&
A.getNumOperands() == 5 && A.getOperand(2).getImm() == 1 &&
B.getOperand(2).getImm() == 1 && "Unexpected EXRL target MCInst");
if (A.getOpcode() != B.getOpcode())
return A.getOpcode() < B.getOpcode();
if (A.getOperand(0).getReg() != B.getOperand(0).getReg())
return A.getOperand(0).getReg() < B.getOperand(0).getReg();
if (A.getOperand(1).getImm() != B.getOperand(1).getImm())
return A.getOperand(1).getImm() < B.getOperand(1).getImm();
if (A.getOperand(3).getReg() != B.getOperand(3).getReg())
return A.getOperand(3).getReg() < B.getOperand(3).getReg();
if (A.getOperand(4).getImm() != B.getOperand(4).getImm())
return A.getOperand(4).getImm() < B.getOperand(4).getImm();
return false;
}
};
typedef std::map<MCInstSTIPair, MCSymbol *, CmpMCInst> EXRLT2SymMap;
EXRLT2SymMap EXRLTargets2Sym;
void emitConstantPools() override;
virtual void emitMachine(StringRef CPU) = 0;
};

View File

@ -0,0 +1,46 @@
; RUN: llc < %s -mtriple=s390x-linux-gnu -generate-arange-section
;
; Test that the EXRL target instruction is emitted successfully (before text
; section is closed).
@a = dso_local global i32* null, align 8, !dbg !0
@j = dso_local global i32 0, align 4, !dbg !5
define void @fun() !dbg !14 {
entry:
%0 = load i32*, i32** @a, align 8, !dbg !18
%1 = bitcast i32* %0 to i8*, !dbg !19
%2 = load i32, i32* @j, align 4, !dbg !20
%conv = sext i32 %2 to i64, !dbg !20
call void @llvm.memset.p0i8.i64(i8* align 4 %1, i8 0, i64 %conv, i1 false), !dbg !19
ret void, !dbg !21
}
declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg) #1
!llvm.dbg.cu = !{!2}
!llvm.module.flags = !{!9, !10, !11, !12}
!llvm.ident = !{!13}
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !8, isLocal: false, isDefinition: true)
!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None)
!3 = !DIFile(filename: "file.c", directory: "")
!4 = !{!0, !5}
!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression())
!6 = distinct !DIGlobalVariable(name: "j", scope: !2, file: !3, line: 2, type: !7, isLocal: false, isDefinition: true)
!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64)
!9 = !{i32 7, !"Dwarf Version", i32 4}
!10 = !{i32 2, !"Debug Info Version", i32 3}
!11 = !{i32 1, !"wchar_size", i32 4}
!12 = !{i32 7, !"frame-pointer", i32 2}
!13 = !{!"clang version 14.0.0"}
!14 = distinct !DISubprogram(name: "fun", scope: !3, file: !3, line: 3, type: !15, scopeLine: 3, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !17)
!15 = !DISubroutineType(types: !16)
!16 = !{null}
!17 = !{}
!18 = !DILocation(line: 4, column: 11, scope: !14)
!19 = !DILocation(line: 4, column: 4, scope: !14)
!20 = !DILocation(line: 4, column: 15, scope: !14)
!21 = !DILocation(line: 5, column: 1, scope: !14)