Skip to content

[MC][AArch64][ARM][X86] Push target-dependent assembler flags into targets #139844

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions llvm/include/llvm/MC/MCAsmBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,6 @@ class MCAsmBackend {
/// Give backend an opportunity to finish layout after relaxation
virtual void finishLayout(MCAssembler const &Asm) const {}

/// Handle any target-specific assembler flags. By default, do nothing.
virtual void handleAssemblerFlag(MCAssemblerFlag Flag) {}

/// Generate the compact unwind encoding for the CFI instructions.
virtual uint64_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI,
const MCContext *Ctxt) const {
Expand Down
10 changes: 0 additions & 10 deletions llvm/include/llvm/MC/MCAsmInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,13 +166,6 @@ class MCAsmInfo {
const char *InlineAsmStart;
const char *InlineAsmEnd;

/// These are assembly directives that tells the assembler to interpret the
/// following instructions differently. Defaults to ".code16", ".code32",
/// ".code64".
const char *Code16Directive;
const char *Code32Directive;
const char *Code64Directive;

/// Which dialect of an assembler variant to use. Defaults to 0
unsigned AssemblerDialect = 0;

Expand Down Expand Up @@ -544,9 +537,6 @@ class MCAsmInfo {

const char *getInlineAsmStart() const { return InlineAsmStart; }
const char *getInlineAsmEnd() const { return InlineAsmEnd; }
const char *getCode16Directive() const { return Code16Directive; }
const char *getCode32Directive() const { return Code32Directive; }
const char *getCode64Directive() const { return Code64Directive; }
unsigned getAssemblerDialect() const { return AssemblerDialect; }
bool doesAllowAtInName() const { return AllowAtInName; }
void setAllowAtInName(bool V) { AllowAtInName = V; }
Expand Down
8 changes: 0 additions & 8 deletions llvm/include/llvm/MC/MCDirectives.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,6 @@ enum MCSymbolAttr {
MCSA_Memtag, ///< .memtag (ELF)
};

enum MCAssemblerFlag {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! I agree that it's better to handle these very target-specific flags into XXXTargetStreamer

MCAF_SyntaxUnified, ///< .syntax (ARM/ELF)
MCAF_SubsectionsViaSymbols, ///< .subsections_via_symbols (MachO)
MCAF_Code16, ///< .code16 (X86) / .code 16 (ARM)
MCAF_Code32, ///< .code32 (X86) / .code 32 (ARM)
MCAF_Code64 ///< .code64 (X86)
};

enum MCDataRegionType {
MCDR_DataRegion, ///< .data_region
MCDR_DataRegionJT8, ///< .data_region jt8
Expand Down
1 change: 0 additions & 1 deletion llvm/include/llvm/MC/MCELFStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ class MCELFStreamer : public MCObjectStreamer {
void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
void emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc, MCDataFragment &F,
uint64_t Offset) override;
void emitAssemblerFlag(MCAssemblerFlag Flag) override;
void emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
Expand Down
9 changes: 7 additions & 2 deletions llvm/include/llvm/MC/MCStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,11 @@ class ARMTargetStreamer : public MCTargetStreamer {

virtual void annotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE);

virtual void emitSyntaxUnified();

virtual void emitCode16();
virtual void emitCode32();

// Note in the output that the specified \p Symbol is a Thumb mode function.
virtual void emitThumbFunc(MCSymbol *Symbol);
virtual void emitThumbSet(MCSymbol *Symbol, const MCExpr *Value);
Expand Down Expand Up @@ -471,8 +476,8 @@ class MCStreamer {

virtual void emitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol);

/// Note in the output the specified \p Flag.
virtual void emitAssemblerFlag(MCAssemblerFlag Flag);
/// Emit a .subsection_via_symbols directive.
virtual void emitSubsectionsViaSymbols();

/// Emit the given list \p Options of strings as linker
/// options into the output.
Expand Down
1 change: 0 additions & 1 deletion llvm/include/llvm/MC/MCWasmStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ class MCWasmStreamer : public MCObjectStreamer {
void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
void emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc, MCDataFragment &F,
uint64_t Offset) override;
void emitAssemblerFlag(MCAssemblerFlag Flag) override;
void emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
Expand Down
1 change: 0 additions & 1 deletion llvm/include/llvm/MC/MCWinCOFFStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ class MCWinCOFFStreamer : public MCObjectStreamer {
void initSections(bool NoExecStack, const MCSubtargetInfo &STI) override;
void changeSection(MCSection *Section, uint32_t Subsection = 0) override;
void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
void emitAssemblerFlag(MCAssemblerFlag Flag) override;
bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
void emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
void beginCOFFSymbolDef(MCSymbol const *Symbol) override;
Expand Down
3 changes: 0 additions & 3 deletions llvm/lib/MC/MCAsmInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ MCAsmInfo::MCAsmInfo() {
LinkerPrivateGlobalPrefix = "";
InlineAsmStart = "APP";
InlineAsmEnd = "NO_APP";
Code16Directive = ".code16";
Code32Directive = ".code32";
Code64Directive = ".code64";
ZeroDirective = "\t.zero\t";
AsciiDirective = "\t.ascii\t";
AscizDirective = "\t.asciz\t";
Expand Down
13 changes: 3 additions & 10 deletions llvm/lib/MC/MCAsmStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ class MCAsmStreamer final : public MCStreamer {

void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;

void emitAssemblerFlag(MCAssemblerFlag Flag) override;
void emitSubsectionsViaSymbols() override;
void emitLinkerOptions(ArrayRef<std::string> Options) override;
void emitDataRegion(MCDataRegionType Kind) override;
void emitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
Expand Down Expand Up @@ -597,15 +597,8 @@ void MCAsmStreamer::emitGNUAttribute(unsigned Tag, unsigned Value) {
OS << "\t.gnu_attribute " << Tag << ", " << Value << "\n";
}

void MCAsmStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {
switch (Flag) {
case MCAF_SyntaxUnified: OS << "\t.syntax unified"; break;
case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break;
case MCAF_Code16: OS << '\t'<< MAI->getCode16Directive();break;
case MCAF_Code32: OS << '\t'<< MAI->getCode32Directive();break;
case MCAF_Code64: OS << '\t'<< MAI->getCode64Directive();break;
}
EmitEOL();
void MCAsmStreamer::emitSubsectionsViaSymbols() {
OS << ".subsections_via_symbols\n";
}

void MCAsmStreamer::emitLinkerOptions(ArrayRef<std::string> Options) {
Expand Down
5 changes: 0 additions & 5 deletions llvm/lib/MC/MCELFStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,6 @@ void MCELFStreamer::emitLabelAtPos(MCSymbol *S, SMLoc Loc, MCDataFragment &F,
Symbol->setType(ELF::STT_TLS);
}

void MCELFStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {
// Let the target do whatever target specific stuff it needs to do.
getAssembler().getBackend().handleAssemblerFlag(Flag);
}

// If bundle alignment is used and there are any instructions in the section, it
// needs to be aligned to at least the bundle size.
static void setSectionAlignmentForBundling(const MCAssembler &Assembler,
Expand Down
17 changes: 3 additions & 14 deletions llvm/lib/MC/MCMachOStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class MCMachOStreamer : public MCObjectStreamer {
void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
void emitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol) override;
void emitAssemblerFlag(MCAssemblerFlag Flag) override;
void emitSubsectionsViaSymbols() override;
void emitLinkerOptions(ArrayRef<std::string> Options) override;
void emitDataRegion(MCDataRegionType Kind) override;
void emitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
Expand Down Expand Up @@ -209,19 +209,8 @@ void MCMachOStreamer::emitDataRegionEnd() {
emitLabel(Data.End);
}

void MCMachOStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {
// Let the target do whatever target specific stuff it needs to do.
getAssembler().getBackend().handleAssemblerFlag(Flag);
// Do any generic stuff we need to do.
switch (Flag) {
case MCAF_SyntaxUnified: return; // no-op here.
case MCAF_Code16: return; // Change parsing mode; no-op here.
case MCAF_Code32: return; // Change parsing mode; no-op here.
case MCAF_Code64: return; // Change parsing mode; no-op here.
case MCAF_SubsectionsViaSymbols:
getWriter().setSubsectionsViaSymbols(true);
return;
}
void MCMachOStreamer::emitSubsectionsViaSymbols() {
getWriter().setSubsectionsViaSymbols(true);
}

void MCMachOStreamer::emitLinkerOptions(ArrayRef<std::string> Options) {
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/MC/MCNullStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ namespace {

void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
Align ByteAlignment) override {}
void emitSubsectionsViaSymbols() override {};
void beginCOFFSymbolDef(const MCSymbol *Symbol) override {}
void emitCOFFSymbolStorageClass(int StorageClass) override {}
void emitCOFFSymbolType(int Type) override {}
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/MC/MCParser/DarwinAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -817,7 +817,7 @@ bool DarwinAsmParser::parseDirectiveSubsectionsViaSymbols(StringRef, SMLoc) {

Lex();

getStreamer().emitAssemblerFlag(MCAF_SubsectionsViaSymbols);
getStreamer().emitSubsectionsViaSymbols();

return false;
}
Expand Down
5 changes: 4 additions & 1 deletion llvm/lib/MC/MCStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1245,7 +1245,10 @@ void MCStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
emitULEB128Value(Diff);
}

void MCStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {}
void MCStreamer::emitSubsectionsViaSymbols() {
llvm_unreachable(
"emitSubsectionsViaSymbols only supported on Mach-O targets");
}
void MCStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {}
void MCStreamer::beginCOFFSymbolDef(const MCSymbol *Symbol) {
llvm_unreachable("this directive only supported on COFF targets");
Expand Down
8 changes: 0 additions & 8 deletions llvm/lib/MC/MCWasmStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,6 @@ void MCWasmStreamer::emitLabelAtPos(MCSymbol *S, SMLoc Loc, MCDataFragment &F,
Symbol->setTLS();
}

void MCWasmStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {
// Let the target do whatever target specific stuff it needs to do.
getAssembler().getBackend().handleAssemblerFlag(Flag);

// Do any generic stuff we need to do.
llvm_unreachable("invalid assembler flag!");
}

void MCWasmStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
MCAssembler &Asm = getAssembler();
auto *SectionWasm = cast<MCSectionWasm>(Section);
Expand Down
16 changes: 0 additions & 16 deletions llvm/lib/MC/MCWinCOFFStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,22 +184,6 @@ void MCWinCOFFStreamer::emitLabel(MCSymbol *S, SMLoc Loc) {
MCObjectStreamer::emitLabel(Symbol, Loc);
}

void MCWinCOFFStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {
// Let the target do whatever target specific stuff it needs to do.
getAssembler().getBackend().handleAssemblerFlag(Flag);

switch (Flag) {
// None of these require COFF specific handling.
case MCAF_SyntaxUnified:
case MCAF_Code16:
case MCAF_Code32:
case MCAF_Code64:
break;
case MCAF_SubsectionsViaSymbols:
llvm_unreachable("COFF doesn't support .subsections_via_symbols");
}
}

bool MCWinCOFFStreamer::emitSymbolAttribute(MCSymbol *S,
MCSymbolAttr Attribute) {
auto *Symbol = cast<MCSymbolCOFF>(S);
Expand Down
7 changes: 4 additions & 3 deletions llvm/lib/Object/RecordStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ class RecordStreamer : public MCStreamer {
void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
Align ByteAlignment) override;

// Ignore COFF-specific directives; we do not need any information from them,
// but the default implementation of these methods crashes, so we override
// them with versions that do nothing.
// Ignore format-specific directives; we do not need any information from
// them, but the default implementation of these methods crashes, so we
// override them with versions that do nothing.
void emitSubsectionsViaSymbols() override {};
void beginCOFFSymbolDef(const MCSymbol *Symbol) override {}
void emitCOFFSymbolStorageClass(int StorageClass) override {}
void emitCOFFSymbolType(int Type) override {}
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -961,7 +961,7 @@ void AArch64AsmPrinter::emitEndOfAsmFile(Module &M) {
// implementation of multiple entry points). If this doesn't occur, the
// linker can safely perform dead code stripping. Since LLVM never
// generates code that does this, it is always safe to set.
OutStreamer->emitAssemblerFlag(MCAF_SubsectionsViaSymbols);
OutStreamer->emitSubsectionsViaSymbols();
}

if (TT.isOSBinFormatELF()) {
Expand Down
1 change: 0 additions & 1 deletion llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ AArch64MCAsmInfoELF::AArch64MCAsmInfoELF(const Triple &T) {
CommentString = "//";
PrivateGlobalPrefix = ".L";
PrivateLabelPrefix = ".L";
Code32Directive = ".code\t32";

Data16bitsDirective = "\t.hword\t";
Data32bitsDirective = "\t.word\t";
Expand Down
26 changes: 17 additions & 9 deletions llvm/lib/Target/ARM/ARMAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ void ARMAsmPrinter::emitFunctionEntryLabel() {
auto &TS =
static_cast<ARMTargetStreamer &>(*OutStreamer->getTargetStreamer());
if (AFI->isThumbFunction()) {
OutStreamer->emitAssemblerFlag(MCAF_Code16);
TS.emitCode16();
TS.emitThumbFunc(CurrentFnSym);
} else {
OutStreamer->emitAssemblerFlag(MCAF_Code32);
TS.emitCode32();
}

// Emit symbol for CMSE non-secure entry point
Expand Down Expand Up @@ -171,7 +171,9 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
// These are created per function, rather than per TU, since it's
// relatively easy to exceed the thumb branch range within a TU.
if (! ThumbIndirectPads.empty()) {
OutStreamer->emitAssemblerFlag(MCAF_Code16);
auto &TS =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ARMAsmPrinter should probably define a convenience method that returns ARMTargetStreamer. The cast appears to occur in quite a few functions.

static_cast<ARMTargetStreamer &>(*OutStreamer->getTargetStreamer());
TS.emitCode16();
emitAlignment(Align(2));
for (std::pair<unsigned, MCSymbol *> &TIP : ThumbIndirectPads) {
OutStreamer->emitLabel(TIP.second);
Expand Down Expand Up @@ -489,24 +491,30 @@ void ARMAsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,
// the start mode, then restore the start mode.
const bool WasThumb = isThumb(StartInfo);
if (!EndInfo || WasThumb != isThumb(*EndInfo)) {
OutStreamer->emitAssemblerFlag(WasThumb ? MCAF_Code16 : MCAF_Code32);
auto &TS =
static_cast<ARMTargetStreamer &>(*OutStreamer->getTargetStreamer());
if (WasThumb)
TS.emitCode16();
else
TS.emitCode32();
}
}

void ARMAsmPrinter::emitStartOfAsmFile(Module &M) {
const Triple &TT = TM.getTargetTriple();
auto &TS =
static_cast<ARMTargetStreamer &>(*OutStreamer->getTargetStreamer());
// Use unified assembler syntax.
OutStreamer->emitAssemblerFlag(MCAF_SyntaxUnified);
TS.emitSyntaxUnified();

// Emit ARM Build Attributes
if (TT.isOSBinFormatELF())
emitAttributes();

// Use the triple's architecture and subarchitecture to determine
// if we're thumb for the purposes of the top level code16 assembler
// flag.
// if we're thumb for the purposes of the top level code16 state.
if (!M.getModuleInlineAsm().empty() && TT.isThumb())
OutStreamer->emitAssemblerFlag(MCAF_Code16);
TS.emitCode16();
}

static void
Expand Down Expand Up @@ -575,7 +583,7 @@ void ARMAsmPrinter::emitEndOfAsmFile(Module &M) {
// implementation of multiple entry points). If this doesn't occur, the
// linker can safely perform dead code stripping. Since LLVM never
// generates code that does this, it is always safe to set.
OutStreamer->emitAssemblerFlag(MCAF_SubsectionsViaSymbols);
OutStreamer->emitSubsectionsViaSymbols();
}

// The last attribute to be emitted is ABI_optimization_goals
Expand Down
16 changes: 9 additions & 7 deletions llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11654,7 +11654,7 @@ bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
if (!isThumb())
SwitchMode();

getParser().getStreamer().emitAssemblerFlag(MCAF_Code16);
getTargetStreamer().emitCode16();
getParser().getStreamer().emitCodeAlignment(Align(2), &getSTI(), 0);
return false;
}
Expand All @@ -11667,7 +11667,7 @@ bool ARMAsmParser::parseDirectiveARM(SMLoc L) {

if (isThumb())
SwitchMode();
getParser().getStreamer().emitAssemblerFlag(MCAF_Code32);
getTargetStreamer().emitCode32();
getParser().getStreamer().emitCodeAlignment(Align(4), &getSTI(), 0);
return false;
}
Expand Down Expand Up @@ -11715,7 +11715,7 @@ bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
if (!isThumb())
SwitchMode();

getParser().getStreamer().emitAssemblerFlag(MCAF_Code16);
getTargetStreamer().emitCode16();

NextSymbolIsThumb = true;
return false;
Expand Down Expand Up @@ -11768,14 +11768,14 @@ bool ARMAsmParser::parseDirectiveCode(SMLoc L) {

if (!isThumb())
SwitchMode();
getParser().getStreamer().emitAssemblerFlag(MCAF_Code16);
getTargetStreamer().emitCode16();
} else {
if (!hasARM())
return Error(L, "target does not support ARM mode");

if (isThumb())
SwitchMode();
getParser().getStreamer().emitAssemblerFlag(MCAF_Code32);
getTargetStreamer().emitCode32();
}

return false;
Expand Down Expand Up @@ -11824,8 +11824,10 @@ void ARMAsmParser::FixModeAfterArchChange(bool WasThumb, SMLoc Loc) {
SwitchMode();
} else {
// Mode switch forced, because the new arch doesn't support the old mode.
getParser().getStreamer().emitAssemblerFlag(isThumb() ? MCAF_Code16
: MCAF_Code32);
if (isThumb())
getTargetStreamer().emitCode16();
else
getTargetStreamer().emitCode32();
// Warn about the implcit mode switch. GAS does not switch modes here,
// but instead stays in the old mode, reporting an error on any following
// instructions as the mode does not exist on the target.
Expand Down
Loading