Skip to content

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

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 8 commits into from
Dec 10, 2024
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
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.
};

// XCOFF specific CPU IDs, defined in AIX OS header: `/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.
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,

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
5 changes: 5 additions & 0 deletions llvm/include/llvm/MC/MCXCOFFObjectWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,16 @@ class MCXCOFFObjectTargetWriter : public MCObjectTargetWriter {
};

class XCOFFObjectWriter : public MCObjectWriter {
// AIX specific CPU type.
std::string CPUType;

public:
virtual void addExceptionEntry(const MCSymbol *Symbol, const MCSymbol *Trap,
unsigned LanguageCode, unsigned ReasonCode,
unsigned FunctionSize, bool hasDebug) = 0;
virtual void addCInfoSymEntry(StringRef Name, StringRef Metadata) = 0;
StringRef getCPUType() const { return CPUType; }
void setCPU(StringRef TargetCPU) { CPUType = TargetCPU; }
};

std::unique_ptr<MCObjectWriter>
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)
.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)
.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
7 changes: 2 additions & 5 deletions llvm/lib/MC/XCOFFObjectWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1180,11 +1180,8 @@ void XCOFFWriter::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(getCPUType());

int NumberOfFileAuxEntries = 1;
if (!Vers.empty())
Expand Down
10 changes: 8 additions & 2 deletions llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCSymbolELF.h"
#include "llvm/MC/MCSymbolXCOFF.h"
#include "llvm/MC/MCXCOFFObjectWriter.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
Expand Down Expand Up @@ -258,7 +259,11 @@ class PPCTargetAsmStreamer : public PPCTargetStreamer {
}

void emitMachine(StringRef CPU) override {
OS << "\t.machine " << CPU << '\n';
const Triple &TT = Streamer.getContext().getTargetTriple();
if (TT.isOSBinFormatXCOFF())
OS << "\t.machine\t" << '\"' << CPU << '\"' << '\n';
else
OS << "\t.machine " << CPU << '\n';
}

void emitAbiVersion(int AbiVersion) override {
Expand Down Expand Up @@ -422,7 +427,8 @@ class PPCTargetXCOFFStreamer : public PPCTargetStreamer {
}

void emitMachine(StringRef CPU) override {
llvm_unreachable("Machine pseudo-ops are invalid for XCOFF.");
static_cast<XCOFFObjectWriter &>(Streamer.getAssemblerPtr()->getWriter())
.setCPU(CPU);
}

void emitAbiVersion(int AbiVersion) override {
Expand Down
25 changes: 25 additions & 0 deletions llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
#include "llvm/Support/Threading.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/TargetParser/PPCTargetParser.h"
#include "llvm/TargetParser/Triple.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
#include <cassert>
Expand Down Expand Up @@ -3046,6 +3047,30 @@ void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {
bool PPCAIXAsmPrinter::doInitialization(Module &M) {
const bool Result = PPCAsmPrinter::doInitialization(M);

// Emit the .machine directive on AIX.
const Triple &Target = TM.getTargetTriple();
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;
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we need a test case for the code.

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 think llvm/test/CodeGen/PowerPC/aix-cpu-version.ll is supposed to cover this. Or am I misunderstanding your comment?

Copy link
Contributor

@diggerlin diggerlin Dec 6, 2024

Choose a reason for hiding this comment

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

my suggestion is that two functions with different "target-cpu" value since there is for loop.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

}
// If there is no "target-cpu" attribute within the functions, take the
// "-mcpu" value. If both are omitted, use getNormalizedPPCTargetCPU() to
// determine the default CPU.
if (!TargetCpuId) {
StringRef TargetCPU = TM.getTargetCPU();
TargetCpuId = XCOFF::getCpuID(
TargetCPU.empty() ? PPC::getNormalizedPPCTargetCPU(Target) : TargetCPU);
}

PPCTargetStreamer *TS =
static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
TS->emitMachine(XCOFF::getTCPUString(TargetCpuId));

auto setCsectAlignment = [this](const GlobalObject *GO) {
// Declarations have 0 alignment which is set by default.
if (GO->isDeclarationForLinker())
Expand Down
30 changes: 30 additions & 0 deletions llvm/test/CodeGen/PowerPC/aix-cpu-version-multifunction.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
; RUN: llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff < %s | FileCheck %s

; For the .machine directive emitted on AIX, the "target-cpu" attribute that is
; the newest will be used as the CPU for the module (in this case, PWR10).

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

source_filename = "file.c"

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

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

attributes #0 = { "target-cpu" = "pwr8" }
attributes #1 = { "target-cpu" = "pwr10" }

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: .csect ..text..[PR],5
; CHECK-NEXT: .rename ..text..[PR],""
; CHECK-NEXT: .machine "PWR8"

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: .csect ..text..[PR],5
; ASM-NEXT: .rename ..text..[PR],""
; ASM-NEXT: .machine "PWR9"

; 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: }
7 changes: 3 additions & 4 deletions llvm/test/CodeGen/PowerPC/aix-filename-cpp.ll
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
; 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: llvm-readobj --symbols %t.o | FileCheck --check-prefixes=OBJ %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: llvm-readobj --symbols %t64.o | FileCheck --check-prefixes=OBJ %s

source_filename = "1.cpp"

; OBJ: Name: .file
; OBJ: Source Language ID: TB_CPLUSPLUS (0x9)
; OBJ32: CPU Version ID: TCPU_COM (0x3)
; OBJ64: CPU Version ID: TCPU_PPC64 (0x2)
; OBJ: CPU Version ID: TCPU_PWR7 (0x18)
; OBJ: Name: 1.cpp
7 changes: 3 additions & 4 deletions llvm/test/CodeGen/PowerPC/aix-filename-f.ll
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
; 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: llvm-readobj --symbols %t.o | FileCheck --check-prefixes=OBJ %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: llvm-readobj --symbols %t64.o | FileCheck --check-prefixes=OBJ %s

source_filename = "1.f95"

; OBJ: Name: .file
; OBJ: Source Language ID: TB_Fortran (0x1)
; OBJ32: CPU Version ID: TCPU_COM (0x3)
; OBJ64: CPU Version ID: TCPU_PPC64 (0x2)
; OBJ: CPU Version ID: TCPU_PWR7 (0x18)
; OBJ: Name: 1.f95
Loading
Loading