Skip to content

Commit b3ab7fa

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: llvm#95510
1 parent 04996a2 commit b3ab7fa

31 files changed

+248
-54
lines changed

llvm/include/llvm/BinaryFormat/XCOFF.h

+28-3
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

+6
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

+1
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

+3
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

+3
Original file line numberDiff line numberDiff line change
@@ -873,6 +873,9 @@ class MCStreamer {
873873
virtual void emitFileDirective(StringRef Filename, StringRef CompilerVersion,
874874
StringRef TimeStamp, StringRef Description);
875875

876+
// Emit '.machine "CPU"' assembler directive.
877+
virtual void emitMachineDirective(StringRef CPU);
878+
876879
/// Emit the "identifiers" directive. This implements the
877880
/// '.ident "version foo"' assembler directive.
878881
virtual void emitIdent(StringRef IdentString) {}

llvm/lib/BinaryFormat/XCOFF.cpp

+59
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

+23-3
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>
@@ -526,9 +527,28 @@ bool AsmPrinter::doInitialization(Module &M) {
526527
}
527528
}
528529

529-
// On AIX, emit bytes for llvm.commandline metadata after .file so that the
530-
// C_INFO symbol is preserved if any csect is kept by the linker.
531-
if (TM.getTargetTriple().isOSBinFormatXCOFF()) {
530+
if (Target.isOSBinFormatXCOFF()) {
531+
// Emit .machine directive on AIX.
532+
XCOFF::CFileCpuId TargetCpuId = XCOFF::TCPU_INVALID;
533+
// Walk through the "target-cpu" attribute of functions and use the newest
534+
// level as the CPU of the module.
535+
for (auto &F : M) {
536+
XCOFF::CFileCpuId FunCpuId =
537+
XCOFF::getCpuID(TM.getSubtargetImpl(F)->getCPU());
538+
if (FunCpuId > TargetCpuId)
539+
TargetCpuId = FunCpuId;
540+
}
541+
// If there is no "target-cpu" attribute in functions, take the "-mcpu"
542+
// value. If both are omitted, use getNormalizedPPCTargetCPU() to determine
543+
// the default CPU.
544+
if (!TargetCpuId)
545+
TargetCpuId = XCOFF::getCpuID(TM.getTargetCPU().empty()
546+
? PPC::getNormalizedPPCTargetCPU(Target)
547+
: TM.getTargetCPU());
548+
OutStreamer->emitMachineDirective(XCOFF::getTCPUString(TargetCpuId));
549+
550+
// On AIX, emit bytes for llvm.commandline metadata after .file so that the
551+
// C_INFO symbol is preserved if any csect is kept by the linker.
532552
emitModuleCommandLines(M);
533553
// Now we can generate section information.
534554
OutStreamer->initSections(false, *TM.getMCSubtargetInfo());

llvm/lib/MC/MCAsmStreamer.cpp

+9
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,
@@ -1630,6 +1633,12 @@ void MCAsmStreamer::emitFileDirective(StringRef Filename,
16301633
EmitEOL();
16311634
}
16321635

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

llvm/lib/MC/MCObjectStreamer.cpp

+4
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

+3
Original file line numberDiff line numberDiff line change
@@ -1208,6 +1208,9 @@ void MCStreamer::emitFileDirective(StringRef Filename,
12081208
StringRef CompilerVersion,
12091209
StringRef TimeStamp, StringRef Description) {
12101210
}
1211+
void MCStreamer::emitMachineDirective(StringRef CPU) {
1212+
llvm_unreachable("this directive only supported on XCOFF targets");
1213+
}
12111214
void MCStreamer::emitCOFFSymbolStorageClass(int StorageClass) {
12121215
llvm_unreachable("this directive only supported on COFF targets");
12131216
}

llvm/lib/MC/XCOFFObjectWriter.cpp

+2-5
Original file line numberDiff line numberDiff line change
@@ -1180,11 +1180,8 @@ void XCOFFWriter::writeSymbolTable(MCAssembler &Asm) {
11801180
LangID = XCOFF::TB_Fortran;
11811181
else
11821182
LangID = XCOFF::TB_CPLUSPLUS;
1183-
uint8_t CpuID;
1184-
if (is64Bit())
1185-
CpuID = XCOFF::TCPU_PPC64;
1186-
else
1187-
CpuID = XCOFF::TCPU_COM;
1183+
1184+
uint8_t CpuID = XCOFF::getCpuID(CPUType);
11881185

11891186
int NumberOfFileAuxEntries = 1;
11901187
if (!Vers.empty())
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

+1-2
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

+1-2
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 {
+54-9
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)