Skip to content

Commit 69e2a67

Browse files
committed
[aarch64][win] Add support for import call optimization (equivalent to MSVC /d2ImportCallOptimization)
1 parent cbff02b commit 69e2a67

19 files changed

+471
-13
lines changed

llvm/include/llvm/CodeGen/MachineFunction.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,11 @@ class LLVM_ABI MachineFunction {
354354
/// a table of valid targets for Windows EHCont Guard.
355355
std::vector<MCSymbol *> CatchretTargets;
356356

357+
/// Mapping of call instruction to the global value and target flags that it
358+
/// calls, if applicable.
359+
DenseMap<const MachineInstr *, std::pair<const GlobalValue *, unsigned>>
360+
CalledGlobalsMap;
361+
357362
/// \name Exception Handling
358363
/// \{
359364

@@ -1182,6 +1187,19 @@ class LLVM_ABI MachineFunction {
11821187
CatchretTargets.push_back(Target);
11831188
}
11841189

1190+
/// Tries to get the global and target flags for a call site, if the
1191+
/// instruction is a call to a global.
1192+
std::pair<const GlobalValue *, unsigned>
1193+
tryGetCalledGlobal(const MachineInstr *MI) const {
1194+
return CalledGlobalsMap.lookup(MI);
1195+
}
1196+
1197+
/// Notes the global and target flags for a call site.
1198+
void addCalledGlobal(const MachineInstr *MI,
1199+
std::pair<const GlobalValue *, unsigned> Details) {
1200+
CalledGlobalsMap.insert({MI, Details});
1201+
}
1202+
11851203
/// \name Exception Handling
11861204
/// \{
11871205

llvm/include/llvm/CodeGen/SelectionDAG.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ class SelectionDAG {
293293
MDNode *HeapAllocSite = nullptr;
294294
MDNode *PCSections = nullptr;
295295
MDNode *MMRA = nullptr;
296+
std::pair<const GlobalValue *, unsigned> CalledGlobal{};
296297
bool NoMerge = false;
297298
};
298299
/// Out-of-line extra information for SDNodes.
@@ -2373,6 +2374,19 @@ class SelectionDAG {
23732374
auto It = SDEI.find(Node);
23742375
return It != SDEI.end() ? It->second.MMRA : nullptr;
23752376
}
2377+
/// Set CalledGlobal to be associated with Node.
2378+
void addCalledGlobal(const SDNode *Node, const GlobalValue *GV,
2379+
unsigned OpFlags) {
2380+
SDEI[Node].CalledGlobal = {GV, OpFlags};
2381+
}
2382+
/// Return CalledGlobal associated with Node, or a nullopt if none exists.
2383+
std::optional<std::pair<const GlobalValue *, unsigned>>
2384+
getCalledGlobal(const SDNode *Node) {
2385+
auto I = SDEI.find(Node);
2386+
return I != SDEI.end()
2387+
? std::make_optional(std::move(I->second).CalledGlobal)
2388+
: std::nullopt;
2389+
}
23762390
/// Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
23772391
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge) {
23782392
if (NoMerge)

llvm/include/llvm/MC/MCObjectFileInfo.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ class MCObjectFileInfo {
7373
/// to emit them into.
7474
MCSection *CompactUnwindSection = nullptr;
7575

76+
/// If import call optimization is supported by the target, this is the
77+
/// section to emit import call data to.
78+
MCSection *ImportCallSection = nullptr;
79+
7680
// Dwarf sections for debug info. If a target supports debug info, these must
7781
// be set.
7882
MCSection *DwarfAbbrevSection = nullptr;
@@ -269,6 +273,7 @@ class MCObjectFileInfo {
269273
MCSection *getBSSSection() const { return BSSSection; }
270274
MCSection *getReadOnlySection() const { return ReadOnlySection; }
271275
MCSection *getLSDASection() const { return LSDASection; }
276+
MCSection *getImportCallSection() const { return ImportCallSection; }
272277
MCSection *getCompactUnwindSection() const { return CompactUnwindSection; }
273278
MCSection *getDwarfAbbrevSection() const { return DwarfAbbrevSection; }
274279
MCSection *getDwarfInfoSection() const { return DwarfInfoSection; }

llvm/include/llvm/MC/MCStreamer.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,14 @@ class MCStreamer {
569569
/// \param Symbol - Symbol the image relative relocation should point to.
570570
virtual void emitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset);
571571

572+
/// Emits the physical number of the section containing the given symbol as
573+
/// assigned during object writing (i.e., this is not a runtime relocation).
574+
virtual void emitCOFFSecNumber(MCSymbol const *Symbol);
575+
576+
/// Emits the offset of the symbol from the beginning of the section during
577+
/// object writing (i.e., this is not a runtime relocation).
578+
virtual void emitCOFFSecOffset(MCSymbol const *Symbol);
579+
572580
/// Emits an lcomm directive with XCOFF csect information.
573581
///
574582
/// \param LabelSym - Label on the block of storage.

llvm/include/llvm/MC/MCWinCOFFObjectWriter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ class WinCOFFObjectWriter final : public MCObjectWriter {
7272
const MCFixup &Fixup, MCValue Target,
7373
uint64_t &FixedValue) override;
7474
uint64_t writeObject(MCAssembler &Asm) override;
75+
int getSectionNumber(const MCSection &Section) const;
7576
};
7677

7778
/// Construct a new Win COFF writer instance.

llvm/include/llvm/MC/MCWinCOFFStreamer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ class MCWinCOFFStreamer : public MCObjectStreamer {
5858
void emitCOFFSectionIndex(MCSymbol const *Symbol) override;
5959
void emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
6060
void emitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override;
61+
void emitCOFFSecNumber(MCSymbol const *Symbol) override;
62+
void emitCOFFSecOffset(MCSymbol const *Symbol) override;
6163
void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
6264
Align ByteAlignment) override;
6365
void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,

llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,9 @@ EmitSchedule(MachineBasicBlock::iterator &InsertPos) {
908908
It->setMMRAMetadata(MF, MMRA);
909909
}
910910

911+
if (auto CalledGlobal = DAG->getCalledGlobal(Node))
912+
MF.addCalledGlobal(MI, *CalledGlobal);
913+
911914
return MI;
912915
};
913916

llvm/lib/MC/MCAsmStreamer.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ class MCAsmStreamer final : public MCStreamer {
209209
void emitCOFFSectionIndex(MCSymbol const *Symbol) override;
210210
void emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
211211
void emitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override;
212+
void emitCOFFSecNumber(MCSymbol const *Symbol) override;
213+
void emitCOFFSecOffset(MCSymbol const *Symbol) override;
212214
void emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
213215
MCSymbol *CsectSym, Align Alignment) override;
214216
void emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
@@ -893,6 +895,18 @@ void MCAsmStreamer::emitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {
893895
EmitEOL();
894896
}
895897

898+
void MCAsmStreamer::emitCOFFSecNumber(MCSymbol const *Symbol) {
899+
OS << "\t.secnum\t";
900+
Symbol->print(OS, MAI);
901+
EmitEOL();
902+
}
903+
904+
void MCAsmStreamer::emitCOFFSecOffset(MCSymbol const *Symbol) {
905+
OS << "\t.secoffset\t";
906+
Symbol->print(OS, MAI);
907+
EmitEOL();
908+
}
909+
896910
// We need an XCOFF-specific version of this directive as the AIX syntax
897911
// requires a QualName argument identifying the csect name and storage mapping
898912
// class to appear before the alignment if we are specifying it.

llvm/lib/MC/MCObjectFileInfo.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,11 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
596596
COFF::IMAGE_SCN_MEM_READ);
597597
}
598598

599+
if (T.getArch() == Triple::aarch64) {
600+
ImportCallSection =
601+
Ctx->getCOFFSection(".impcall", COFF::IMAGE_SCN_LNK_INFO);
602+
}
603+
599604
// Debug info.
600605
COFFDebugSymbolsSection =
601606
Ctx->getCOFFSection(".debug$S", (COFF::IMAGE_SCN_MEM_DISCARDABLE |

llvm/lib/MC/MCParser/COFFAsmParser.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ class COFFAsmParser : public MCAsmParserExtension {
7070
addDirectiveHandler<&COFFAsmParser::parseDirectiveSymbolAttribute>(
7171
".weak_anti_dep");
7272
addDirectiveHandler<&COFFAsmParser::parseDirectiveCGProfile>(".cg_profile");
73+
addDirectiveHandler<&COFFAsmParser::parseDirectiveSecNum>(".secnum");
74+
addDirectiveHandler<&COFFAsmParser::parseDirectiveSecOffset>(".secoffset");
7375

7476
// Win64 EH directives.
7577
addDirectiveHandler<&COFFAsmParser::parseSEHDirectiveStartProc>(
@@ -126,6 +128,8 @@ class COFFAsmParser : public MCAsmParserExtension {
126128
bool parseDirectiveLinkOnce(StringRef, SMLoc);
127129
bool parseDirectiveRVA(StringRef, SMLoc);
128130
bool parseDirectiveCGProfile(StringRef, SMLoc);
131+
bool parseDirectiveSecNum(StringRef, SMLoc);
132+
bool parseDirectiveSecOffset(StringRef, SMLoc);
129133

130134
// Win64 EH directives.
131135
bool parseSEHDirectiveStartProc(StringRef, SMLoc);
@@ -577,6 +581,36 @@ bool COFFAsmParser::parseDirectiveSymIdx(StringRef, SMLoc) {
577581
return false;
578582
}
579583

584+
bool COFFAsmParser::parseDirectiveSecNum(StringRef, SMLoc) {
585+
StringRef SymbolID;
586+
if (getParser().parseIdentifier(SymbolID))
587+
return TokError("expected identifier in directive");
588+
589+
if (getLexer().isNot(AsmToken::EndOfStatement))
590+
return TokError("unexpected token in directive");
591+
592+
MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
593+
594+
Lex();
595+
getStreamer().emitCOFFSecNumber(Symbol);
596+
return false;
597+
}
598+
599+
bool COFFAsmParser::parseDirectiveSecOffset(StringRef, SMLoc) {
600+
StringRef SymbolID;
601+
if (getParser().parseIdentifier(SymbolID))
602+
return TokError("expected identifier in directive");
603+
604+
if (getLexer().isNot(AsmToken::EndOfStatement))
605+
return TokError("unexpected token in directive");
606+
607+
MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
608+
609+
Lex();
610+
getStreamer().emitCOFFSecOffset(Symbol);
611+
return false;
612+
}
613+
580614
/// ::= [ identifier ]
581615
bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
582616
StringRef TypeId = getTok().getIdentifier();

llvm/lib/MC/MCStreamer.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,6 +1023,10 @@ void MCStreamer::emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {}
10231023

10241024
void MCStreamer::emitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {}
10251025

1026+
void MCStreamer::emitCOFFSecNumber(MCSymbol const *Symbol) {}
1027+
1028+
void MCStreamer::emitCOFFSecOffset(MCSymbol const *Symbol) {}
1029+
10261030
/// EmitRawText - If this file is backed by an assembly streamer, this dumps
10271031
/// the specified string in the output .s file. This capability is
10281032
/// indicated by the hasRawTextSupport() predicate.

llvm/lib/MC/MCWinCOFFStreamer.cpp

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "llvm/MC/MCSectionCOFF.h"
3030
#include "llvm/MC/MCSymbolCOFF.h"
3131
#include "llvm/MC/MCTargetOptions.h"
32+
#include "llvm/MC/MCValue.h"
3233
#include "llvm/MC/MCWinCOFFObjectWriter.h"
3334
#include "llvm/Support/Casting.h"
3435
#include "llvm/Support/ErrorHandling.h"
@@ -43,6 +44,91 @@ using namespace llvm;
4344

4445
#define DEBUG_TYPE "WinCOFFStreamer"
4546

47+
/// MCExpr that represents the physical number for the sections that contains
48+
/// a symbol.
49+
class MCCOFFSectionNumberTargetExpr final : public MCTargetExpr {
50+
const MCSymbol &SectionSymbol;
51+
const WinCOFFObjectWriter &Writer;
52+
53+
MCCOFFSectionNumberTargetExpr(const MCSymbol &SectionSymbol_,
54+
const WinCOFFObjectWriter &Writer_)
55+
: SectionSymbol(SectionSymbol_), Writer(Writer_) {}
56+
57+
public:
58+
static MCCOFFSectionNumberTargetExpr *
59+
create(const MCSymbol &SectionSymbol, const WinCOFFObjectWriter &Writer,
60+
MCContext &Ctx) {
61+
return new (Ctx) MCCOFFSectionNumberTargetExpr(SectionSymbol, Writer);
62+
}
63+
64+
void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override {
65+
OS << ":secnum:";
66+
SectionSymbol.print(OS, MAI);
67+
}
68+
69+
bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
70+
const MCFixup *Fixup) const override {
71+
auto sectionNumber = Writer.getSectionNumber(SectionSymbol.getSection());
72+
assert(sectionNumber != 0 &&
73+
"Containing section was not assigned a number");
74+
Res = MCValue::get(sectionNumber);
75+
return true;
76+
}
77+
78+
void visitUsedExpr(MCStreamer &Streamer) const override {
79+
// Contains no sub-expressions.
80+
}
81+
82+
MCFragment *findAssociatedFragment() const override {
83+
return SectionSymbol.getFragment();
84+
}
85+
86+
void fixELFSymbolsInTLSFixups(MCAssembler &) const override {
87+
llvm_unreachable("Not supported for ELF");
88+
}
89+
};
90+
91+
/// MCExpr that represents the offset to a symbol from the beginning of its
92+
/// section.
93+
class MCCOFFSectionOffsetTargetExpr final : public MCTargetExpr {
94+
const MCSymbol &Symbol;
95+
96+
MCCOFFSectionOffsetTargetExpr(const MCSymbol &Symbol_) : Symbol(Symbol_) {}
97+
98+
public:
99+
static MCCOFFSectionOffsetTargetExpr *create(const MCSymbol &Symbol,
100+
MCContext &Ctx) {
101+
return new (Ctx) MCCOFFSectionOffsetTargetExpr(Symbol);
102+
}
103+
104+
void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override {
105+
OS << ":secoffset:";
106+
Symbol.print(OS, MAI);
107+
}
108+
109+
bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
110+
const MCFixup *Fixup) const override {
111+
uint64_t CallsiteOffset = 0;
112+
if (!Asm->getSymbolOffset(Symbol, CallsiteOffset)) {
113+
return true;
114+
}
115+
Res = MCValue::get(CallsiteOffset);
116+
return true;
117+
}
118+
119+
void visitUsedExpr(MCStreamer &Streamer) const override {
120+
// Contains no sub-expressions.
121+
}
122+
123+
MCFragment *findAssociatedFragment() const override {
124+
return Symbol.getFragment();
125+
}
126+
127+
void fixELFSymbolsInTLSFixups(MCAssembler &) const override {
128+
llvm_unreachable("Not supported for ELF");
129+
}
130+
};
131+
46132
MCWinCOFFStreamer::MCWinCOFFStreamer(MCContext &Context,
47133
std::unique_ptr<MCAsmBackend> MAB,
48134
std::unique_ptr<MCCodeEmitter> CE,
@@ -280,6 +366,34 @@ void MCWinCOFFStreamer::emitCOFFImgRel32(const MCSymbol *Symbol,
280366
DF->appendContents(4, 0);
281367
}
282368

369+
void MCWinCOFFStreamer::emitCOFFSecNumber(MCSymbol const *Symbol) {
370+
visitUsedSymbol(*Symbol);
371+
MCDataFragment *DF = getOrCreateDataFragment();
372+
// Create Symbol for section number.
373+
const MCExpr *MCE = MCCOFFSectionNumberTargetExpr::create(
374+
*Symbol, this->getWriter(), getContext());
375+
// Build the relocation.
376+
MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_Data_4);
377+
// Record the relocation.
378+
DF->getFixups().push_back(Fixup);
379+
// Emit 4 bytes (zeros) to the object file.
380+
DF->appendContents(4, 0);
381+
}
382+
383+
void MCWinCOFFStreamer::emitCOFFSecOffset(MCSymbol const *Symbol) {
384+
visitUsedSymbol(*Symbol);
385+
MCDataFragment *DF = getOrCreateDataFragment();
386+
// Create Symbol for section offset.
387+
const MCExpr *MCE =
388+
MCCOFFSectionOffsetTargetExpr::create(*Symbol, getContext());
389+
// Build the relocation.
390+
MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_Data_4);
391+
// Record the relocation.
392+
DF->getFixups().push_back(Fixup);
393+
// Emit 4 bytes (zeros) to the object file.
394+
DF->appendContents(4, 0);
395+
}
396+
283397
void MCWinCOFFStreamer::emitCommonSymbol(MCSymbol *S, uint64_t Size,
284398
Align ByteAlignment) {
285399
auto *Symbol = cast<MCSymbolCOFF>(S);

0 commit comments

Comments
 (0)