Skip to content

Commit a499cd6

Browse files
committed
[PowerPC][AIX] Emit PowerPC version for XCOFF
This PR emits implements the ability to emit the PPC version for both assembly and object files on AIX. Furthermore, this PR is intended to be a commandeered version of Esme's previous PR: #95510
1 parent ac9ee61 commit a499cd6

31 files changed

+248
-54
lines changed

llvm/include/llvm/BinaryFormat/XCOFF.h

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -333,10 +333,33 @@ enum CFileLangId : uint8_t {
333333
TB_CPLUSPLUS = 9 ///< C++ language.
334334
};
335335

336+
// XCOFF specific CPU IDs, defined in AIX OS header: `/usr/include/aouthdr.h`.
336337
enum CFileCpuId : uint8_t {
337-
TCPU_PPC64 = 2, ///< PowerPC common architecture 64-bit mode.
338-
TCPU_COM = 3, ///< POWER and PowerPC architecture common.
339-
TCPU_970 = 19 ///< PPC970 - PowerPC 64-bit architecture.
338+
TCPU_INVALID = 0, ///< Invalid id - assumes POWER for old objects.
339+
TCPU_PPC = 1, ///< PowerPC common architecture 32 bit mode.
340+
TCPU_PPC64 = 2, ///< PowerPC common architecture 64-bit mode.
341+
TCPU_COM = 3, ///< POWER and PowerPC architecture common.
342+
TCPU_PWR = 4, ///< POWER common architecture objects.
343+
TCPU_ANY = 5, ///< Mixture of any incompatable POWER
344+
///< and PowerPC architecture implementations.
345+
TCPU_601 = 6, ///< 601 implementation of PowerPC architecture.
346+
TCPU_603 = 7, ///< 603 implementation of PowerPC architecture.
347+
TCPU_604 = 8, ///< 604 implementation of PowerPC architecture.
348+
349+
// The following are PowerPC 64-bit architectures.
350+
TCPU_620 = 16,
351+
TCPU_A35 = 17,
352+
TCPU_PWR5 = 18,
353+
TCPU_970 = 19,
354+
TCPU_PWR6 = 20,
355+
TCPU_PWR5X = 22,
356+
TCPU_PWR6E = 23,
357+
TCPU_PWR7 = 24,
358+
TCPU_PWR8 = 25,
359+
TCPU_PWR9 = 26,
360+
TCPU_PWR10 = 27,
361+
362+
TCPU_PWRX = 224 ///< RS2 implementation of POWER architecture.
340363
};
341364

342365
enum SymbolAuxType : uint8_t {
@@ -350,6 +373,7 @@ enum SymbolAuxType : uint8_t {
350373

351374
StringRef getMappingClassString(XCOFF::StorageMappingClass SMC);
352375
StringRef getRelocationTypeString(XCOFF::RelocationType Type);
376+
StringRef getTCPUString(XCOFF::CFileCpuId TCPU);
353377
Expected<SmallString<32>> parseParmsType(uint32_t Value, unsigned FixedParmsNum,
354378
unsigned FloatingParmsNum);
355379
Expected<SmallString<32>> parseParmsTypeWithVecInfo(uint32_t Value,
@@ -468,6 +492,7 @@ enum ExtendedTBTableFlag : uint8_t {
468492

469493
StringRef getNameForTracebackTableLanguageId(TracebackTable::LanguageID LangId);
470494
SmallString<32> getExtendedTBTableFlagString(uint8_t Flag);
495+
XCOFF::CFileCpuId getCpuID(StringRef CPU);
471496

472497
struct CsectProperties {
473498
CsectProperties(StorageMappingClass SMC, SymbolType ST)

llvm/include/llvm/MC/MCAssembler.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ class MCAssembler {
7070

7171
SmallVector<const MCSymbol *, 0> Symbols;
7272

73+
// PPC CPU type.
74+
std::string CPU;
75+
7376
MCDwarfLineTableParams LTParams;
7477

7578
/// The set of function symbols for which a .thumb_func directive has
@@ -225,6 +228,9 @@ class MCAssembler {
225228
return make_pointee_range(Symbols);
226229
}
227230

231+
void setCPU(std::string TargetCPU) { CPU = std::move(TargetCPU); }
232+
StringRef getCPU() const { return CPU; }
233+
228234
bool registerSection(MCSection &Section);
229235
bool registerSymbol(const MCSymbol &Symbol);
230236

llvm/include/llvm/MC/MCObjectStreamer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ class MCObjectStreamer : public MCStreamer {
185185
void emitFileDirective(StringRef Filename) override;
186186
void emitFileDirective(StringRef Filename, StringRef CompilerVersion,
187187
StringRef TimeStamp, StringRef Description) override;
188+
void emitMachineDirective(StringRef CPU) override;
188189

189190
void emitAddrsig() override;
190191
void emitAddrsigSym(const MCSymbol *Sym) override;

llvm/include/llvm/MC/MCObjectWriter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ class MCObjectWriter {
3636
SmallVector<std::pair<std::string, size_t>, 0> FileNames;
3737
// XCOFF specific: Optional compiler version.
3838
std::string CompilerVersion;
39+
// AIX specific: CPU type.
40+
std::string CPUType;
3941
std::vector<const MCSymbol *> AddrsigSyms;
4042
bool EmitAddrsigSection = false;
4143
bool SubsectionsViaSymbols = false;
@@ -100,6 +102,7 @@ class MCObjectWriter {
100102
void setCompilerVersion(StringRef CompilerVers) {
101103
CompilerVersion = CompilerVers;
102104
}
105+
void setCPU(StringRef TargetCPU) { CPUType = TargetCPU; }
103106

104107
/// Tell the object writer to emit an address-significance table during
105108
/// writeObject(). If this function is not called, all symbols are treated as

llvm/include/llvm/MC/MCStreamer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,9 @@ class MCStreamer {
871871
virtual void emitFileDirective(StringRef Filename, StringRef CompilerVersion,
872872
StringRef TimeStamp, StringRef Description);
873873

874+
// Emit '.machine "CPU"' assembler directive.
875+
virtual void emitMachineDirective(StringRef CPU);
876+
874877
/// Emit the "identifiers" directive. This implements the
875878
/// '.ident "version foo"' assembler directive.
876879
virtual void emitIdent(StringRef IdentString) {}

llvm/lib/BinaryFormat/XCOFF.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
#include "llvm/BinaryFormat/XCOFF.h"
1010
#include "llvm/ADT/SmallString.h"
1111
#include "llvm/ADT/StringRef.h"
12+
#include "llvm/ADT/StringSwitch.h"
1213
#include "llvm/Support/Errc.h"
1314
#include "llvm/Support/Error.h"
15+
#include "llvm/TargetParser/PPCTargetParser.h"
1416

1517
using namespace llvm;
1618

@@ -107,6 +109,63 @@ StringRef XCOFF::getNameForTracebackTableLanguageId(
107109
}
108110
#undef LANG_CASE
109111

112+
XCOFF::CFileCpuId XCOFF::getCpuID(StringRef CPUName) {
113+
StringRef CPU = PPC::normalizeCPUName(CPUName);
114+
return StringSwitch<XCOFF::CFileCpuId>(CPU)
115+
.Cases("generic", "COM", XCOFF::TCPU_COM)
116+
.Case("601", XCOFF::TCPU_601)
117+
.Cases("602", "603", "603e", "603ev", XCOFF::TCPU_603)
118+
.Cases("604", "604e", XCOFF::TCPU_604)
119+
.Case("620", XCOFF::TCPU_620)
120+
.Case("970", XCOFF::TCPU_970)
121+
.Cases("a2", "g3", "g4", "g5", "e500", XCOFF::TCPU_COM)
122+
.Cases("pwr3", "pwr4", XCOFF::TCPU_COM)
123+
.Cases("pwr5", "PWR5", XCOFF::TCPU_PWR5)
124+
.Cases("pwr5x", "PWR5X", XCOFF::TCPU_PWR5X)
125+
.Cases("pwr6", "PWR6", XCOFF::TCPU_PWR6)
126+
.Cases("pwr6x", "PWR6E", XCOFF::TCPU_PWR6E)
127+
.Cases("pwr7", "PWR7", XCOFF::TCPU_PWR7)
128+
.Cases("pwr8", "PWR8", XCOFF::TCPU_PWR8)
129+
.Cases("pwr9", "PWR9", XCOFF::TCPU_PWR9)
130+
.Cases("pwr10", "PWR10", XCOFF::TCPU_PWR10)
131+
.Cases("ppc", "PPC", "ppc32", "ppc64", XCOFF::TCPU_COM)
132+
.Case("ppc64le", XCOFF::TCPU_PWR8)
133+
.Case("future", XCOFF::TCPU_PWR10)
134+
.Cases("any", "ANY", XCOFF::TCPU_ANY)
135+
.Default(XCOFF::TCPU_INVALID);
136+
}
137+
138+
#define TCPU_CASE(A) \
139+
case XCOFF::TCPU_##A: \
140+
return #A;
141+
StringRef XCOFF::getTCPUString(XCOFF::CFileCpuId TCPU) {
142+
switch (TCPU) {
143+
TCPU_CASE(INVALID)
144+
TCPU_CASE(PPC)
145+
TCPU_CASE(PPC64)
146+
TCPU_CASE(COM)
147+
TCPU_CASE(PWR)
148+
TCPU_CASE(ANY)
149+
TCPU_CASE(601)
150+
TCPU_CASE(603)
151+
TCPU_CASE(604)
152+
TCPU_CASE(620)
153+
TCPU_CASE(A35)
154+
TCPU_CASE(PWR5)
155+
TCPU_CASE(970)
156+
TCPU_CASE(PWR6)
157+
TCPU_CASE(PWR5X)
158+
TCPU_CASE(PWR6E)
159+
TCPU_CASE(PWR7)
160+
TCPU_CASE(PWR8)
161+
TCPU_CASE(PWR9)
162+
TCPU_CASE(PWR10)
163+
TCPU_CASE(PWRX)
164+
}
165+
return "INVALID";
166+
}
167+
#undef TCPU_CASE
168+
110169
Expected<SmallString<32>> XCOFF::parseParmsType(uint32_t Value,
111170
unsigned FixedParmsNum,
112171
unsigned FloatingParmsNum) {

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
#include "llvm/Target/TargetLoweringObjectFile.h"
121121
#include "llvm/Target/TargetMachine.h"
122122
#include "llvm/Target/TargetOptions.h"
123+
#include "llvm/TargetParser/PPCTargetParser.h"
123124
#include "llvm/TargetParser/Triple.h"
124125
#include <algorithm>
125126
#include <cassert>
@@ -508,9 +509,28 @@ bool AsmPrinter::doInitialization(Module &M) {
508509
}
509510
}
510511

511-
// On AIX, emit bytes for llvm.commandline metadata after .file so that the
512-
// C_INFO symbol is preserved if any csect is kept by the linker.
513-
if (TM.getTargetTriple().isOSBinFormatXCOFF()) {
512+
if (Target.isOSBinFormatXCOFF()) {
513+
// Emit .machine directive on AIX.
514+
XCOFF::CFileCpuId TargetCpuId = XCOFF::TCPU_INVALID;
515+
// Walk through the "target-cpu" attribute of functions and use the newest
516+
// level as the CPU of the module.
517+
for (auto &F : M) {
518+
XCOFF::CFileCpuId FunCpuId =
519+
XCOFF::getCpuID(TM.getSubtargetImpl(F)->getCPU());
520+
if (FunCpuId > TargetCpuId)
521+
TargetCpuId = FunCpuId;
522+
}
523+
// If there is no "target-cpu" attribute in functions, take the "-mcpu"
524+
// value. If both are omitted, use getNormalizedPPCTargetCPU() to determine
525+
// the default CPU.
526+
if (!TargetCpuId)
527+
TargetCpuId = XCOFF::getCpuID(TM.getTargetCPU().empty()
528+
? PPC::getNormalizedPPCTargetCPU(Target)
529+
: TM.getTargetCPU());
530+
OutStreamer->emitMachineDirective(XCOFF::getTCPUString(TargetCpuId));
531+
532+
// On AIX, emit bytes for llvm.commandline metadata after .file so that the
533+
// C_INFO symbol is preserved if any csect is kept by the linker.
514534
emitModuleCommandLines(M);
515535
// Now we can generate section information.
516536
OutStreamer->initSections(false, *TM.getMCSubtargetInfo());

llvm/lib/MC/MCAsmStreamer.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,9 @@ class MCAsmStreamer final : public MCStreamer {
288288
void emitFileDirective(StringRef Filename) override;
289289
void emitFileDirective(StringRef Filename, StringRef CompilerVersion,
290290
StringRef TimeStamp, StringRef Description) override;
291+
292+
void emitMachineDirective(StringRef CPU) override;
293+
291294
Expected<unsigned> tryEmitDwarfFileDirective(
292295
unsigned FileNo, StringRef Directory, StringRef Filename,
293296
std::optional<MD5::MD5Result> Checksum = std::nullopt,
@@ -1628,6 +1631,12 @@ void MCAsmStreamer::emitFileDirective(StringRef Filename,
16281631
EmitEOL();
16291632
}
16301633

1634+
void MCAsmStreamer::emitMachineDirective(StringRef CPU) {
1635+
OS << "\t.machine\t";
1636+
PrintQuotedString(CPU, OS);
1637+
EmitEOL();
1638+
}
1639+
16311640
void MCAsmStreamer::printDwarfFileDirective(
16321641
unsigned FileNo, StringRef Directory, StringRef Filename,
16331642
std::optional<MD5::MD5Result> Checksum, std::optional<StringRef> Source,

llvm/lib/MC/MCObjectStreamer.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,10 @@ void MCObjectStreamer::emitFileDirective(StringRef Filename,
804804
// with the integrated assembler.
805805
}
806806

807+
void MCObjectStreamer::emitMachineDirective(StringRef CPU) {
808+
getAssembler().getWriter().setCPU(CPU);
809+
}
810+
807811
void MCObjectStreamer::emitAddrsig() {
808812
getAssembler().getWriter().emitAddrsigSection();
809813
}

llvm/lib/MC/MCStreamer.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,6 +1174,9 @@ void MCStreamer::emitFileDirective(StringRef Filename,
11741174
StringRef CompilerVersion,
11751175
StringRef TimeStamp, StringRef Description) {
11761176
}
1177+
void MCStreamer::emitMachineDirective(StringRef CPU) {
1178+
llvm_unreachable("this directive only supported on XCOFF targets");
1179+
}
11771180
void MCStreamer::emitCOFFSymbolStorageClass(int StorageClass) {
11781181
llvm_unreachable("this directive only supported on COFF targets");
11791182
}

llvm/lib/MC/XCOFFObjectWriter.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,11 +1184,8 @@ void XCOFFObjectWriter::writeSymbolTable(MCAssembler &Asm) {
11841184
LangID = XCOFF::TB_Fortran;
11851185
else
11861186
LangID = XCOFF::TB_CPLUSPLUS;
1187-
uint8_t CpuID;
1188-
if (is64Bit())
1189-
CpuID = XCOFF::TCPU_PPC64;
1190-
else
1191-
CpuID = XCOFF::TCPU_COM;
1187+
1188+
uint8_t CpuID = XCOFF::getCpuID(CPUType);
11921189

11931190
int NumberOfFileAuxEntries = 1;
11941191
if (!Vers.empty())
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
; RUN: llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff < %s | FileCheck %s
2+
3+
; CHECK: .file "1.c"
4+
; CHECK-NEXT: .machine "PWR8"
5+
; CHECK-NEXT: .csect ..text..[PR],5
6+
; CHECK-NEXT: .rename ..text..[PR],""
7+
8+
source_filename = "1.c"
9+
10+
define dso_local signext i32 @main() #0 {
11+
entry:
12+
%retval = alloca i32, align 4
13+
store i32 0, ptr %retval, align 4
14+
ret i32 0
15+
}
16+
17+
attributes #0 = {"target-cpu"="pwr8"}

llvm/test/CodeGen/PowerPC/aix-extern-weak.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,7 @@ declare extern_weak void @foo_ext_weak(ptr)
6868
; CHECKSYM-NEXT: Value (SymbolTableIndex): 0x0
6969
; CHECKSYM-NEXT: Section: N_DEBUG
7070
; CHECKSYM-NEXT: Source Language ID: TB_CPLUSPLUS (0x9)
71-
; CHECKSYM32-NEXT: CPU Version ID: TCPU_COM (0x3)
72-
; CHECKSYM64-NEXT: CPU Version ID: TCPU_PPC64 (0x2)
71+
; CHECKSYM-NEXT: CPU Version ID: TCPU_COM (0x3)
7372
; CHECKSYM-NEXT: StorageClass: C_FILE (0x67)
7473
; CHECKSYM-NEXT: NumberOfAuxEntries: 2
7574
; CHECKSYM: Symbol {

llvm/test/CodeGen/PowerPC/aix-extern.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,7 @@ declare i32 @bar_extern(ptr)
9191
; CHECKSYM-NEXT: Value (SymbolTableIndex): 0x0
9292
; CHECKSYM-NEXT: Section: N_DEBUG
9393
; CHECKSYM-NEXT: Source Language ID: TB_CPLUSPLUS (0x9)
94-
; CHECKSYM32-NEXT: CPU Version ID: TCPU_COM (0x3)
95-
; CHECKSYM64-NEXT: CPU Version ID: TCPU_PPC64 (0x2)
94+
; CHECKSYM-NEXT: CPU Version ID: TCPU_COM (0x3)
9695
; CHECKSYM-NEXT: StorageClass: C_FILE (0x67)
9796
; CHECKSYM-NEXT: NumberOfAuxEntries: 2
9897
; CHECKSYM: Symbol {
Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,57 @@
1-
; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -filetype=obj -o %t.o < %s
2-
; RUN: llvm-readobj --symbols %t.o | FileCheck --check-prefixes=OBJ,OBJ32 %s
3-
; RUN: llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff -filetype=obj -o %t64.o < %s
4-
; RUN: llvm-readobj --symbols %t64.o | FileCheck --check-prefixes=OBJ,OBJ64 %s
1+
; RUN: llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff -mcpu=pwr9 < %s | FileCheck --check-prefixes=ASM %s
2+
3+
; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr9 -filetype=obj -o %t.o < %s
4+
; RUN: llvm-readobj --symbols %t.o | FileCheck --check-prefixes=OBJ32 %s
5+
; RUN: llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff -mcpu=pwr9 -filetype=obj -o %t64.o < %s
6+
; RUN: llvm-readobj --symbols %t64.o | FileCheck --check-prefixes=OBJ64 %s
57

68
source_filename = "1.c"
79

8-
; OBJ: Name: .file
9-
; OBJ: Source Language ID: TB_C (0x0)
10-
; OBJ32: CPU Version ID: TCPU_COM (0x3)
11-
; OBJ64: CPU Version ID: TCPU_PPC64 (0x2)
12-
; OBJ: Name: 1.c
10+
; ASM: .file "1.c",,"LLVM{{.*}}"
11+
; ASM-NEXT: .machine "PWR9"
12+
; ASM-NEXT: .csect ..text..[PR],5
13+
; ASM-NEXT: .rename ..text..[PR],""
14+
15+
; OBJ32: Symbol {
16+
; OBJ32-NEXT: Index: 0
17+
; OBJ32-NEXT: Name: .file
18+
; OBJ32-NEXT: Value (SymbolTableIndex): 0x0
19+
; OBJ32-NEXT: Section: N_DEBUG
20+
; OBJ32-NEXT: Source Language ID: TB_C (0x0)
21+
; OBJ32-NEXT: CPU Version ID: TCPU_PWR9 (0x1A)
22+
; OBJ32-NEXT: StorageClass: C_FILE (0x67)
23+
; OBJ32-NEXT: NumberOfAuxEntries: 2
24+
; OBJ32-NEXT: File Auxiliary Entry {
25+
; OBJ32-NEXT: Index: 1
26+
; OBJ32-NEXT: Name: 1.c
27+
; OBJ32-NEXT: Type: XFT_FN (0x0)
28+
; OBJ32-NEXT: }
29+
; OBJ32-NEXT: File Auxiliary Entry {
30+
; OBJ32-NEXT: Index: 2
31+
; OBJ32-NEXT: Name: LLVM
32+
; OBJ32-NEXT: Type: XFT_CV (0x2)
33+
; OBJ32-NEXT: }
34+
; OBJ32-NEXT: }
35+
36+
; OBJ64: Symbol {
37+
; OBJ64-NEXT: Index: 0
38+
; OBJ64-NEXT: Name: .file
39+
; OBJ64-NEXT: Value (SymbolTableIndex): 0x0
40+
; OBJ64-NEXT: Section: N_DEBUG
41+
; OBJ64-NEXT: Source Language ID: TB_C (0x0)
42+
; OBJ64-NEXT: CPU Version ID: TCPU_PWR9 (0x1A)
43+
; OBJ64-NEXT: StorageClass: C_FILE (0x67)
44+
; OBJ64-NEXT: NumberOfAuxEntries: 2
45+
; OBJ64-NEXT: File Auxiliary Entry {
46+
; OBJ64-NEXT: Index: 1
47+
; OBJ64-NEXT: Name: 1.c
48+
; OBJ64-NEXT: Type: XFT_FN (0x0)
49+
; OBJ64-NEXT: Auxiliary Type: AUX_FILE (0xFC)
50+
; OBJ64-NEXT: }
51+
; OBJ64-NEXT: File Auxiliary Entry {
52+
; OBJ64-NEXT: Index: 2
53+
; OBJ64-NEXT: Name: LLVM
54+
; OBJ64-NEXT: Type: XFT_CV (0x2)
55+
; OBJ64-NEXT: Auxiliary Type: AUX_FILE (0xFC)
56+
; OBJ64-NEXT: }
57+
; OBJ64-NEXT: }

0 commit comments

Comments
 (0)