diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -900,6 +900,26 @@ #include "ELFRelocs/CSKY.def" }; +// LoongArch Specific e_flags +enum : unsigned { + // Reference: https://github.com/loongson/LoongArch-Documentation. + // The last commit hash (main branch) is + // 99016636af64d02dee05e39974d4c1e55875c45b. + // Note that there is an open PR + // https://github.com/loongson/LoongArch-Documentation/pull/47 + // talking about using 0x1, 0x2, 0x3 for ILP32S/F/D and use EI_CLASS to + // distinguish LP64 and ILP32. If this PR get merged, we will update + // the definition here. + // Base ABI Types. + EF_LOONGARCH_BASE_ABI_LP64S = 0x1, // LP64 soft-float ABI + EF_LOONGARCH_BASE_ABI_LP64F = 0x2, // LP64 single-float ABI + EF_LOONGARCH_BASE_ABI_LP64D = 0x3, // LP64 double-float ABI + EF_LOONGARCH_BASE_ABI_ILP32S = 0x5, // ILP32 soft-float ABI + EF_LOONGARCH_BASE_ABI_ILP32F = 0x6, // ILP32 single-float ABI + EF_LOONGARCH_BASE_ABI_ILP32D = 0x7, // ILP32 double-float ABI + EF_LOONGARCH_BASE_ABI_MASK = 0x7, // Mask for selecting base ABI +}; + // ELF Relocation types for LoongArch enum { #include "ELFRelocs/LoongArch.def" diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -518,6 +518,14 @@ BCaseMask(EF_AVR_ARCH_XMEGA7, EF_AVR_ARCH_MASK); BCase(EF_AVR_LINKRELAX_PREPARED); break; + case ELF::EM_LOONGARCH: + BCaseMask(EF_LOONGARCH_BASE_ABI_ILP32S, EF_LOONGARCH_BASE_ABI_MASK); + BCaseMask(EF_LOONGARCH_BASE_ABI_ILP32F, EF_LOONGARCH_BASE_ABI_MASK); + BCaseMask(EF_LOONGARCH_BASE_ABI_ILP32D, EF_LOONGARCH_BASE_ABI_MASK); + BCaseMask(EF_LOONGARCH_BASE_ABI_LP64S, EF_LOONGARCH_BASE_ABI_MASK); + BCaseMask(EF_LOONGARCH_BASE_ABI_LP64F, EF_LOONGARCH_BASE_ABI_MASK); + BCaseMask(EF_LOONGARCH_BASE_ABI_LP64D, EF_LOONGARCH_BASE_ABI_MASK); + break; case ELF::EM_RISCV: BCase(EF_RISCV_RVC); BCaseMask(EF_RISCV_FLOAT_ABI_SOFT, EF_RISCV_FLOAT_ABI); diff --git a/llvm/test/tools/llvm-readobj/ELF/loongarch-eflags.test b/llvm/test/tools/llvm-readobj/ELF/loongarch-eflags.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/loongarch-eflags.test @@ -0,0 +1,64 @@ +## Check llvm-readobj is able to decode all possible LoongArch e_flags field values. + +# RUN: yaml2obj %s -o %t-lp64s -DCLASS=64 -DFLAG=LP64S +# RUN: llvm-readobj -h %t-lp64s | FileCheck --check-prefix=READOBJ-LP64S %s +# RUN: llvm-readelf -h %t-lp64s | FileCheck --check-prefix=READELF-LP64S --match-full-lines %s + +# RUN: yaml2obj %s -o %t-lp64f -DCLASS=64 -DFLAG=LP64F +# RUN: llvm-readobj -h %t-lp64f | FileCheck --check-prefix=READOBJ-LP64F %s +# RUN: llvm-readelf -h %t-lp64f | FileCheck --check-prefix=READELF-LP64F --match-full-lines %s + +# RUN: yaml2obj %s -o %t-lp64d -DCLASS=64 -DFLAG=LP64D +# RUN: llvm-readobj -h %t-lp64d | FileCheck --check-prefix=READOBJ-LP64D %s +# RUN: llvm-readelf -h %t-lp64d | FileCheck --check-prefix=READELF-LP64D --match-full-lines %s + +# RUN: yaml2obj %s -o %t-ilp32s -DCLASS=32 -DFLAG=ILP32S +# RUN: llvm-readobj -h %t-ilp32s | FileCheck --check-prefix=READOBJ-ILP32S %s +# RUN: llvm-readelf -h %t-ilp32s | FileCheck --check-prefix=READELF-ILP32S --match-full-lines %s + +# RUN: yaml2obj %s -o %t-ilp32f -DCLASS=32 -DFLAG=ILP32F +# RUN: llvm-readobj -h %t-ilp32f | FileCheck --check-prefix=READOBJ-ILP32F %s +# RUN: llvm-readelf -h %t-ilp32f | FileCheck --check-prefix=READELF-ILP32F --match-full-lines %s + +# RUN: yaml2obj %s -o %t-ilp32d -DCLASS=32 -DFLAG=ILP32D +# RUN: llvm-readobj -h %t-ilp32d | FileCheck --check-prefix=READOBJ-ILP32D %s +# RUN: llvm-readelf -h %t-ilp32d | FileCheck --check-prefix=READELF-ILP32D --match-full-lines %s + +# READOBJ-LP64S: Flags [ (0x1) +# READOBJ-LP64S-NEXT: EF_LOONGARCH_BASE_ABI_LP64S (0x1) +# READOBJ-LP64S-NEXT: ] + +# READOBJ-LP64F: Flags [ (0x2) +# READOBJ-LP64F-NEXT: EF_LOONGARCH_BASE_ABI_LP64F (0x2) +# READOBJ-LP64F-NEXT: ] + +# READOBJ-LP64D: Flags [ (0x3) +# READOBJ-LP64D-NEXT: EF_LOONGARCH_BASE_ABI_LP64D (0x3) +# READOBJ-LP64D-NEXT: ] + +# READOBJ-ILP32S: Flags [ (0x5) +# READOBJ-ILP32S-NEXT: EF_LOONGARCH_BASE_ABI_ILP32S (0x5) +# READOBJ-ILP32S-NEXT: ] + +# READOBJ-ILP32F: Flags [ (0x6) +# READOBJ-ILP32F-NEXT: EF_LOONGARCH_BASE_ABI_ILP32F (0x6) +# READOBJ-ILP32F-NEXT: ] + +# READOBJ-ILP32D: Flags [ (0x7) +# READOBJ-ILP32D-NEXT: EF_LOONGARCH_BASE_ABI_ILP32D (0x7) +# READOBJ-ILP32D-NEXT: ] + +# READELF-LP64S: Flags: 0x1, LP64, SOFT-FLOAT +# READELF-LP64F: Flags: 0x2, LP64, SINGLE-FLOAT +# READELF-LP64D: Flags: 0x3, LP64, DOUBLE-FLOAT +# READELF-ILP32S: Flags: 0x5, ILP32, SOFT-FLOAT +# READELF-ILP32F: Flags: 0x6, ILP32, SINGLE-FLOAT +# READELF-ILP32D: Flags: 0x7, ILP32, DOUBLE-FLOAT + +--- !ELF +FileHeader: + Class: ELFCLASS[[CLASS]] + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_LOONGARCH + Flags: [ EF_LOONGARCH_BASE_ABI_[[FLAG]] ] diff --git a/llvm/test/tools/obj2yaml/ELF/loongarch-eflags.yaml b/llvm/test/tools/obj2yaml/ELF/loongarch-eflags.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/obj2yaml/ELF/loongarch-eflags.yaml @@ -0,0 +1,29 @@ +## Check obj2yaml is able to decode all possible LoongArch e_flags field values. + +# RUN: yaml2obj %s -o %t-lp64s -DCLASS=64 -DFLAG=LP64S +# RUN: obj2yaml %t-lp64s | FileCheck -DFLAG=LP64S %s + +# RUN: yaml2obj %s -o %t-lp64f -DCLASS=64 -DFLAG=LP64F +# RUN: obj2yaml %t-lp64f | FileCheck -DFLAG=LP64F %s + +# RUN: yaml2obj %s -o %t-lp64d -DCLASS=64 -DFLAG=LP64D +# RUN: obj2yaml %t-lp64d | FileCheck -DFLAG=LP64D %s + +# RUN: yaml2obj %s -o %t-ilp32s -DCLASS=32 -DFLAG=ILP32S +# RUN: obj2yaml %t-ilp32s | FileCheck -DFLAG=ILP32S %s + +# RUN: yaml2obj %s -o %t-ilp32f -DCLASS=32 -DFLAG=ILP32F +# RUN: obj2yaml %t-ilp32f | FileCheck -DFLAG=ILP32F %s + +# RUN: yaml2obj %s -o %t-ilp32d -DCLASS=32 -DFLAG=ILP32D +# RUN: obj2yaml %t-ilp32d | FileCheck -DFLAG=ILP32D %s + +# CHECK: Flags: [ EF_LOONGARCH_BASE_ABI_[[FLAG]] ] + +--- !ELF +FileHeader: + Class: ELFCLASS[[CLASS]] + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_LOONGARCH + Flags: [ EF_LOONGARCH_BASE_ABI_[[FLAG]] ] diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -1648,6 +1648,15 @@ ENUM_ENT(EF_AVR_LINKRELAX_PREPARED, "relaxable"), }; +const EnumEntry ElfHeaderLoongArchFlags[] = { + ENUM_ENT(EF_LOONGARCH_BASE_ABI_ILP32S, "ILP32, SOFT-FLOAT"), + ENUM_ENT(EF_LOONGARCH_BASE_ABI_ILP32F, "ILP32, SINGLE-FLOAT"), + ENUM_ENT(EF_LOONGARCH_BASE_ABI_ILP32D, "ILP32, DOUBLE-FLOAT"), + ENUM_ENT(EF_LOONGARCH_BASE_ABI_LP64S, "LP64, SOFT-FLOAT"), + ENUM_ENT(EF_LOONGARCH_BASE_ABI_LP64F, "LP64, SINGLE-FLOAT"), + ENUM_ENT(EF_LOONGARCH_BASE_ABI_LP64D, "LP64, DOUBLE-FLOAT"), +}; + const EnumEntry ElfSymOtherFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, STV_INTERNAL), @@ -3357,6 +3366,9 @@ else if (e.e_machine == EM_AVR) ElfFlags = printFlags(e.e_flags, makeArrayRef(ElfHeaderAVRFlags), unsigned(ELF::EF_AVR_ARCH_MASK)); + else if (e.e_machine == EM_LOONGARCH) + ElfFlags = printFlags(e.e_flags, makeArrayRef(ElfHeaderLoongArchFlags), + unsigned(ELF::EF_LOONGARCH_BASE_ABI_MASK)); Str = "0x" + utohexstr(e.e_flags); if (!ElfFlags.empty()) Str = Str + ", " + ElfFlags; @@ -6507,6 +6519,9 @@ else if (E.e_machine == EM_AVR) W.printFlags("Flags", E.e_flags, makeArrayRef(ElfHeaderAVRFlags), unsigned(ELF::EF_AVR_ARCH_MASK)); + else if (E.e_machine == EM_LOONGARCH) + W.printFlags("Flags", E.e_flags, makeArrayRef(ElfHeaderLoongArchFlags), + unsigned(ELF::EF_LOONGARCH_BASE_ABI_MASK)); else W.printFlags("Flags", E.e_flags); W.printNumber("HeaderSize", E.e_ehsize);