Skip to content

[PowerPC][AIX] Emit PowerPC version for XCOFF #95510

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
31 changes: 28 additions & 3 deletions llvm/include/llvm/BinaryFormat/XCOFF.h
Original file line number Diff line number Diff line change
Expand Up @@ -333,10 +333,33 @@ enum CFileLangId : uint8_t {
TB_CPLUSPLUS = 9 ///< C++ language.
};

// CPU ID in XCOFF, defined in `/usr/include/aouthdr.h`.
enum CFileCpuId : uint8_t {
TCPU_PPC64 = 2, ///< PowerPC common architecture 64-bit mode.
TCPU_COM = 3, ///< POWER and PowerPC architecture common.
TCPU_970 = 19 ///< PPC970 - PowerPC 64-bit architecture.
TCPU_INVALID = 0, ///< Invalid id - assumes POWER for old objects.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is there any document where do these constants come from?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, these values are found in the file /usr/include/aouthdr.h on AIX.

Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: Maybe you can add a comments to say that these definitions are from AIX OS headers? So that we know that these are XCOFF specific.

TCPU_PPC = 1, ///< PowerPC common architecture 32 bit mode.
TCPU_PPC64 = 2, ///< PowerPC common architecture 64-bit mode.
TCPU_COM = 3, ///< POWER and PowerPC architecture common.
TCPU_PWR = 4, ///< POWER common architecture objects.
TCPU_ANY = 5, ///< Mixture of any incompatable POWER
///< and PowerPC architecture implementations.
TCPU_601 = 6, ///< 601 implementation of PowerPC architecture.
TCPU_603 = 7, ///< 603 implementation of PowerPC architecture.
TCPU_604 = 8, ///< 604 implementation of PowerPC architecture.

// The following are PowerPC 64-bit architectures.
TCPU_620 = 16,
TCPU_A35 = 17,
TCPU_PWR5 = 18,
TCPU_970 = 19,
TCPU_PWR6 = 20,
TCPU_PWR5X = 22,
TCPU_PWR6E = 23,
TCPU_PWR7 = 24,
TCPU_PWR8 = 25,
TCPU_PWR9 = 26,
TCPU_PWR10 = 27,

Copy link
Collaborator

Choose a reason for hiding this comment

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

PWR11 is recently added.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I checked /usr/include/aouthdr.h on an AIX7.2 machine and didn't find the PWR11. Did I miss something?

TCPU_PWRX = 224 ///< RS2 implementation of POWER architecture.
};

enum SymbolAuxType : uint8_t {
Expand All @@ -350,6 +373,7 @@ enum SymbolAuxType : uint8_t {

StringRef getMappingClassString(XCOFF::StorageMappingClass SMC);
StringRef getRelocationTypeString(XCOFF::RelocationType Type);
StringRef getTCPUString(XCOFF::CFileCpuId TCPU);
Expected<SmallString<32>> parseParmsType(uint32_t Value, unsigned FixedParmsNum,
unsigned FloatingParmsNum);
Expected<SmallString<32>> parseParmsTypeWithVecInfo(uint32_t Value,
Expand Down Expand Up @@ -468,6 +492,7 @@ enum ExtendedTBTableFlag : uint8_t {

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

struct CsectProperties {
CsectProperties(StorageMappingClass SMC, SymbolType ST)
Expand Down
6 changes: 6 additions & 0 deletions llvm/include/llvm/MC/MCAssembler.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ class MCAssembler {

SmallVector<const MCSymbol *, 0> Symbols;

// PPC CPU type.
std::string CPU;

MCDwarfLineTableParams LTParams;

/// The set of function symbols for which a .thumb_func directive has
Expand Down Expand Up @@ -224,6 +227,9 @@ class MCAssembler {
return make_pointee_range(Symbols);
}

void setCPU(std::string TargetCPU) { CPU = std::move(TargetCPU); }
StringRef getCPU() const { return CPU; }

bool registerSection(MCSection &Section);
bool registerSymbol(const MCSymbol &Symbol);

Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/MC/MCObjectStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ class MCObjectStreamer : public MCStreamer {
void emitFileDirective(StringRef Filename) override;
void emitFileDirective(StringRef Filename, StringRef CompilerVersion,
StringRef TimeStamp, StringRef Description) override;
void emitMachineDirective(StringRef CPU) override;

void emitAddrsig() override;
void emitAddrsigSym(const MCSymbol *Sym) override;
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/MC/MCObjectWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class MCObjectWriter {
SmallVector<std::pair<std::string, size_t>, 0> FileNames;
// XCOFF specific: Optional compiler version.
std::string CompilerVersion;
// AIX specific: CPU type.
std::string CPUType;
std::vector<const MCSymbol *> AddrsigSyms;
bool EmitAddrsigSection = false;
bool SubsectionsViaSymbols = false;
Expand Down Expand Up @@ -100,6 +102,7 @@ class MCObjectWriter {
void setCompilerVersion(StringRef CompilerVers) {
CompilerVersion = CompilerVers;
}
void setCPU(StringRef TargetCPU) { CPUType = TargetCPU; }

/// Tell the object writer to emit an address-significance table during
/// writeObject(). If this function is not called, all symbols are treated as
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/MC/MCStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,9 @@ class MCStreamer {
virtual void emitFileDirective(StringRef Filename, StringRef CompilerVersion,
StringRef TimeStamp, StringRef Description);

// Emit '.machine "CPU"' assembler diretive.
virtual void emitMachineDirective(StringRef CPU);

/// Emit the "identifiers" directive. This implements the
/// '.ident "version foo"' assembler directive.
virtual void emitIdent(StringRef IdentString) {}
Expand Down
59 changes: 59 additions & 0 deletions llvm/lib/BinaryFormat/XCOFF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
#include "llvm/BinaryFormat/XCOFF.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
#include "llvm/TargetParser/PPCTargetParser.h"

using namespace llvm;

Expand Down Expand Up @@ -107,6 +109,63 @@ StringRef XCOFF::getNameForTracebackTableLanguageId(
}
#undef LANG_CASE

XCOFF::CFileCpuId XCOFF::getCpuID(StringRef CPUName) {
StringRef CPU = PPC::normalizeCPUName(CPUName);
return StringSwitch<XCOFF::CFileCpuId>(CPU)
.Cases("generic", "COM", XCOFF::TCPU_COM)
.Case("601", XCOFF::TCPU_601)
.Cases("602", "603", "603e", "603ev", XCOFF::TCPU_603)
.Cases("604", "604e", XCOFF::TCPU_604)
.Case("620", XCOFF::TCPU_620)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think we need to handle names like power10 or ppc32 or powerpc which are all not supported by aix system assembler.

You can just add a statement here to say that the cpu names will be normalized by https://github.com/llvm/llvm-project/blob/main/clang/lib/Driver/ToolChains/Arch/PPC.cpp#L54-L77 in previous logic.

I continue to improve that normalization in #97541

The aix system supports:

        Valid values are:COM PWR PWR2 PPC 601 603 604 PPC64 620 A35 PWR4 PWR5 PWR5X 970 PPC970 PWR6 PWR6E PWR7 PWR8 PWR9 PWR10 ANY

We may need to map some other normalized CPU names like a2,g5 or others to some know value like COM.

Copy link
Collaborator

Choose a reason for hiding this comment

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

#97541 now is committed. We can adjust here accordingly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed. Thanks!

.Case("970", XCOFF::TCPU_970)
.Cases("a2", "g3", "g4", "g5", "e500", XCOFF::TCPU_COM)
.Cases("pwr3", "pwr4", XCOFF::TCPU_COM)
.Cases("pwr5", "PWR5", XCOFF::TCPU_PWR5)
.Cases("pwr5x", "PWR5X", XCOFF::TCPU_PWR5X)
.Cases("pwr6", "PWR6", XCOFF::TCPU_PWR6)
.Cases("pwr6x", "PWR6E", XCOFF::TCPU_PWR6E)
.Cases("pwr7", "PWR7", XCOFF::TCPU_PWR7)
.Cases("pwr8", "PWR8", XCOFF::TCPU_PWR8)
.Cases("pwr9", "PWR9", XCOFF::TCPU_PWR9)
.Cases("pwr10", "PWR10", XCOFF::TCPU_PWR10)
.Cases("ppc", "PPC", "ppc32", "ppc64", XCOFF::TCPU_COM)
.Case("ppc64le", XCOFF::TCPU_PWR8)
.Case("future", XCOFF::TCPU_PWR10)
Copy link
Collaborator

Choose a reason for hiding this comment

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

future is not pwr10 now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I didn't see the CPU ID for PWR11 defined in the header file on AIX.

.Cases("any", "ANY", XCOFF::TCPU_ANY)
.Default(XCOFF::TCPU_INVALID);
}

#define TCPU_CASE(A) \
case XCOFF::TCPU_##A: \
return #A;
StringRef XCOFF::getTCPUString(XCOFF::CFileCpuId TCPU) {
switch (TCPU) {
TCPU_CASE(INVALID)
TCPU_CASE(PPC)
TCPU_CASE(PPC64)
TCPU_CASE(COM)
TCPU_CASE(PWR)
TCPU_CASE(ANY)
TCPU_CASE(601)
TCPU_CASE(603)
TCPU_CASE(604)
TCPU_CASE(620)
TCPU_CASE(A35)
TCPU_CASE(PWR5)
TCPU_CASE(970)
TCPU_CASE(PWR6)
TCPU_CASE(PWR5X)
TCPU_CASE(PWR6E)
TCPU_CASE(PWR7)
TCPU_CASE(PWR8)
TCPU_CASE(PWR9)
TCPU_CASE(PWR10)
TCPU_CASE(PWRX)
}
return "INVALID";
}
#undef TCPU_CASE

Expected<SmallString<32>> XCOFF::parseParmsType(uint32_t Value,
unsigned FixedParmsNum,
unsigned FloatingParmsNum) {
Expand Down
26 changes: 23 additions & 3 deletions llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/TargetParser/PPCTargetParser.h"
#include "llvm/TargetParser/Triple.h"
#include <algorithm>
#include <cassert>
Expand Down Expand Up @@ -501,9 +502,28 @@ bool AsmPrinter::doInitialization(Module &M) {
}
}

// On AIX, emit bytes for llvm.commandline metadata after .file so that the
// C_INFO symbol is preserved if any csect is kept by the linker.
if (TM.getTargetTriple().isOSBinFormatXCOFF()) {
if (Target.isOSBinFormatXCOFF()) {
// Emit .machine directive on AIX.
XCOFF::CFileCpuId TargetCpuId = XCOFF::TCPU_INVALID;
// Walk through the "target-cpu" attribute of functions and use the newest
// level as the CPU of the module.
for (auto &F : M) {
XCOFF::CFileCpuId FunCpuId =
XCOFF::getCpuID(TM.getSubtargetImpl(F)->getCPU());
if (FunCpuId > TargetCpuId)
TargetCpuId = FunCpuId;
}
// If there is no "target-cpu" attribute in functions, take the "-mcpu"
// value. If both are omitted, use getNormalizedPPCTargetCPU() to determine
// the default CPU.
if (!TargetCpuId)
TargetCpuId = XCOFF::getCpuID(TM.getTargetCPU().empty()
? PPC::getNormalizedPPCTargetCPU(Target)
: TM.getTargetCPU());
OutStreamer->emitMachineDirective(XCOFF::getTCPUString(TargetCpuId));

// On AIX, emit bytes for llvm.commandline metadata after .file so that the
// C_INFO symbol is preserved if any csect is kept by the linker.
emitModuleCommandLines(M);
// Now we can generate section information.
OutStreamer->initSections(false, *TM.getMCSubtargetInfo());
Expand Down
9 changes: 9 additions & 0 deletions llvm/lib/MC/MCAsmStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,9 @@ class MCAsmStreamer final : public MCStreamer {
void emitFileDirective(StringRef Filename) override;
void emitFileDirective(StringRef Filename, StringRef CompilerVersion,
StringRef TimeStamp, StringRef Description) override;

void emitMachineDirective(StringRef CPU) override;

Expected<unsigned> tryEmitDwarfFileDirective(
unsigned FileNo, StringRef Directory, StringRef Filename,
std::optional<MD5::MD5Result> Checksum = std::nullopt,
Expand Down Expand Up @@ -1625,6 +1628,12 @@ void MCAsmStreamer::emitFileDirective(StringRef Filename,
EmitEOL();
}

void MCAsmStreamer::emitMachineDirective(StringRef CPU) {
OS << "\t.machine\t";
PrintQuotedString(CPU, OS);
EmitEOL();
}

void MCAsmStreamer::printDwarfFileDirective(
unsigned FileNo, StringRef Directory, StringRef Filename,
std::optional<MD5::MD5Result> Checksum, std::optional<StringRef> Source,
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/MC/MCObjectStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,10 @@ void MCObjectStreamer::emitFileDirective(StringRef Filename,
// with the integrated assembler.
}

void MCObjectStreamer::emitMachineDirective(StringRef CPU) {
getAssembler().getWriter().setCPU(CPU);
}

void MCObjectStreamer::emitAddrsig() {
getAssembler().getWriter().emitAddrsigSection();
}
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/MC/MCStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1168,6 +1168,9 @@ void MCStreamer::emitFileDirective(StringRef Filename,
StringRef CompilerVersion,
StringRef TimeStamp, StringRef Description) {
}
void MCStreamer::emitMachineDirective(StringRef CPU) {
llvm_unreachable("this directive only supported on XCOFF targets");
}
void MCStreamer::emitCOFFSymbolStorageClass(int StorageClass) {
llvm_unreachable("this directive only supported on COFF targets");
}
Expand Down
7 changes: 2 additions & 5 deletions llvm/lib/MC/XCOFFObjectWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1183,11 +1183,8 @@ void XCOFFObjectWriter::writeSymbolTable(MCAssembler &Asm) {
LangID = XCOFF::TB_Fortran;
else
LangID = XCOFF::TB_CPLUSPLUS;
uint8_t CpuID;
if (is64Bit())
CpuID = XCOFF::TCPU_PPC64;
else
CpuID = XCOFF::TCPU_COM;

uint8_t CpuID = XCOFF::getCpuID(CPUType);

int NumberOfFileAuxEntries = 1;
if (!Vers.empty())
Expand Down
17 changes: 17 additions & 0 deletions llvm/test/CodeGen/PowerPC/aix-cpu-version.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
; RUN: llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff < %s | FileCheck %s

; CHECK: .file "1.c"
; CHECK-NEXT: .machine "PWR8"
; CHECK-NEXT: .csect ..text..[PR],5
; CHECK-NEXT: .rename ..text..[PR],""

source_filename = "1.c"

define dso_local signext i32 @main() #0 {
entry:
%retval = alloca i32, align 4
store i32 0, ptr %retval, align 4
ret i32 0
}

attributes #0 = {"target-cpu"="pwr8"}
3 changes: 1 addition & 2 deletions llvm/test/CodeGen/PowerPC/aix-extern-weak.ll
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,7 @@ declare extern_weak void @foo_ext_weak(ptr)
; CHECKSYM-NEXT: Value (SymbolTableIndex): 0x0
; CHECKSYM-NEXT: Section: N_DEBUG
; CHECKSYM-NEXT: Source Language ID: TB_CPLUSPLUS (0x9)
; CHECKSYM32-NEXT: CPU Version ID: TCPU_COM (0x3)
; CHECKSYM64-NEXT: CPU Version ID: TCPU_PPC64 (0x2)
; CHECKSYM-NEXT: CPU Version ID: TCPU_COM (0x3)
; CHECKSYM-NEXT: StorageClass: C_FILE (0x67)
; CHECKSYM-NEXT: NumberOfAuxEntries: 2
; CHECKSYM: Symbol {
Expand Down
3 changes: 1 addition & 2 deletions llvm/test/CodeGen/PowerPC/aix-extern.ll
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,7 @@ declare i32 @bar_extern(ptr)
; CHECKSYM-NEXT: Value (SymbolTableIndex): 0x0
; CHECKSYM-NEXT: Section: N_DEBUG
; CHECKSYM-NEXT: Source Language ID: TB_CPLUSPLUS (0x9)
; CHECKSYM32-NEXT: CPU Version ID: TCPU_COM (0x3)
; CHECKSYM64-NEXT: CPU Version ID: TCPU_PPC64 (0x2)
; CHECKSYM-NEXT: CPU Version ID: TCPU_COM (0x3)
; CHECKSYM-NEXT: StorageClass: C_FILE (0x67)
; CHECKSYM-NEXT: NumberOfAuxEntries: 2
; CHECKSYM: Symbol {
Expand Down
63 changes: 54 additions & 9 deletions llvm/test/CodeGen/PowerPC/aix-filename-c.ll
Original file line number Diff line number Diff line change
@@ -1,12 +1,57 @@
; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -filetype=obj -o %t.o < %s
; RUN: llvm-readobj --symbols %t.o | FileCheck --check-prefixes=OBJ,OBJ32 %s
; RUN: llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff -filetype=obj -o %t64.o < %s
; RUN: llvm-readobj --symbols %t64.o | FileCheck --check-prefixes=OBJ,OBJ64 %s
; RUN: llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff -mcpu=pwr9 < %s | FileCheck --check-prefixes=ASM %s

; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr9 -filetype=obj -o %t.o < %s
; RUN: llvm-readobj --symbols %t.o | FileCheck --check-prefixes=OBJ32 %s
; RUN: llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff -mcpu=pwr9 -filetype=obj -o %t64.o < %s
; RUN: llvm-readobj --symbols %t64.o | FileCheck --check-prefixes=OBJ64 %s

source_filename = "1.c"

; OBJ: Name: .file
; OBJ: Source Language ID: TB_C (0x0)
; OBJ32: CPU Version ID: TCPU_COM (0x3)
; OBJ64: CPU Version ID: TCPU_PPC64 (0x2)
; OBJ: Name: 1.c
; ASM: .file "1.c",,"LLVM{{.*}}"
; ASM-NEXT: .machine "PWR9"
; ASM-NEXT: .csect ..text..[PR],5
; ASM-NEXT: .rename ..text..[PR],""

; OBJ32: Symbol {
; OBJ32-NEXT: Index: 0
; OBJ32-NEXT: Name: .file
; OBJ32-NEXT: Value (SymbolTableIndex): 0x0
; OBJ32-NEXT: Section: N_DEBUG
; OBJ32-NEXT: Source Language ID: TB_C (0x0)
; OBJ32-NEXT: CPU Version ID: TCPU_PWR9 (0x1A)
; OBJ32-NEXT: StorageClass: C_FILE (0x67)
; OBJ32-NEXT: NumberOfAuxEntries: 2
; OBJ32-NEXT: File Auxiliary Entry {
; OBJ32-NEXT: Index: 1
; OBJ32-NEXT: Name: 1.c
; OBJ32-NEXT: Type: XFT_FN (0x0)
; OBJ32-NEXT: }
; OBJ32-NEXT: File Auxiliary Entry {
; OBJ32-NEXT: Index: 2
; OBJ32-NEXT: Name: LLVM
; OBJ32-NEXT: Type: XFT_CV (0x2)
; OBJ32-NEXT: }
; OBJ32-NEXT: }

; OBJ64: Symbol {
; OBJ64-NEXT: Index: 0
; OBJ64-NEXT: Name: .file
; OBJ64-NEXT: Value (SymbolTableIndex): 0x0
; OBJ64-NEXT: Section: N_DEBUG
; OBJ64-NEXT: Source Language ID: TB_C (0x0)
; OBJ64-NEXT: CPU Version ID: TCPU_PWR9 (0x1A)
; OBJ64-NEXT: StorageClass: C_FILE (0x67)
; OBJ64-NEXT: NumberOfAuxEntries: 2
; OBJ64-NEXT: File Auxiliary Entry {
; OBJ64-NEXT: Index: 1
; OBJ64-NEXT: Name: 1.c
; OBJ64-NEXT: Type: XFT_FN (0x0)
; OBJ64-NEXT: Auxiliary Type: AUX_FILE (0xFC)
; OBJ64-NEXT: }
; OBJ64-NEXT: File Auxiliary Entry {
; OBJ64-NEXT: Index: 2
; OBJ64-NEXT: Name: LLVM
; OBJ64-NEXT: Type: XFT_CV (0x2)
; OBJ64-NEXT: Auxiliary Type: AUX_FILE (0xFC)
; OBJ64-NEXT: }
; OBJ64-NEXT: }
Loading
Loading