summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlrich Weigand <ulrich.weigand@de.ibm.com>2014-07-20 22:56:57 +0000
committerUlrich Weigand <ulrich.weigand@de.ibm.com>2014-07-20 22:56:57 +0000
commit0daa5164bf30159a805765c76a07b7b3104ae9de (patch)
tree23a112a4ad89111316fd807911a423869655a63e
parent241959722e5433617a96818e2938a4b9926e3650 (diff)
downloadbcm5719-llvm-0daa5164bf30159a805765c76a07b7b3104ae9de.tar.gz
bcm5719-llvm-0daa5164bf30159a805765c76a07b7b3104ae9de.zip
[PowerPC] ELFv2 MC support for .abiversion directive
ELFv2 binaries are marked by a bit in the ELF header e_flags field. A new assembler directive .abiversion can be used to set that flag. This patch implements support in the PowerPC MC streamers to emit the .abiversion directive (both into assembler and ELF binary output), as well as support in the assembler parser to parse the .abiversion directive. Reviewed by Hal Finkel. llvm-svn: 213484
-rw-r--r--llvm/include/llvm/Support/ELF.h9
-rw-r--r--llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp24
-rw-r--r--llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp20
-rw-r--r--llvm/lib/Target/PowerPC/PPCTargetStreamer.h1
-rw-r--r--llvm/test/MC/PowerPC/ppc64-abiversion.s9
5 files changed, 62 insertions, 1 deletions
diff --git a/llvm/include/llvm/Support/ELF.h b/llvm/include/llvm/Support/ELF.h
index b8f80a3bcbc..b8ab048a4b3 100644
--- a/llvm/include/llvm/Support/ELF.h
+++ b/llvm/include/llvm/Support/ELF.h
@@ -496,6 +496,15 @@ enum {
R_PPC_REL16_HA = 252
};
+// Specific e_flags for PPC64
+enum {
+ // e_flags bits specifying ABI:
+ // 1 for original ABI using function descriptors,
+ // 2 for revised ABI without function descriptors,
+ // 0 for unspecified or not using any features affected by the differences.
+ EF_PPC64_ABI = 3
+};
+
// ELF Relocation types for PPC64
enum {
R_PPC64_NONE = 0,
diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index 2f562ca7891..7560a7a1831 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -244,6 +244,7 @@ class PPCAsmParser : public MCTargetAsmParser {
bool ParseDirectiveTC(unsigned Size, SMLoc L);
bool ParseDirectiveMachine(SMLoc L);
bool ParseDarwinDirectiveMachine(SMLoc L);
+ bool ParseDirectiveAbiVersion(SMLoc L);
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
OperandVector &Operands, MCStreamer &Out,
@@ -1412,6 +1413,8 @@ bool PPCAsmParser::ParseDirective(AsmToken DirectiveID) {
return ParseDirectiveTC(isPPC64()? 8 : 4, DirectiveID.getLoc());
if (IDVal == ".machine")
return ParseDirectiveMachine(DirectiveID.getLoc());
+ if (IDVal == ".abiversion")
+ return ParseDirectiveAbiVersion(DirectiveID.getLoc());
} else {
if (IDVal == ".machine")
return ParseDarwinDirectiveMachine(DirectiveID.getLoc());
@@ -1534,6 +1537,27 @@ bool PPCAsmParser::ParseDarwinDirectiveMachine(SMLoc L) {
return false;
}
+/// ParseDirectiveAbiVersion
+/// ::= .abiversion constant-expression
+bool PPCAsmParser::ParseDirectiveAbiVersion(SMLoc L) {
+ int64_t AbiVersion;
+ if (getParser().parseAbsoluteExpression(AbiVersion)){
+ Error(L, "expected constant expression");
+ return false;
+ }
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ Error(L, "unexpected token in directive");
+ return false;
+ }
+
+ PPCTargetStreamer &TStreamer =
+ *static_cast<PPCTargetStreamer *>(
+ getParser().getStreamer().getTargetStreamer());
+ TStreamer.emitAbiVersion(AbiVersion);
+
+ return false;
+}
+
/// Force static initialization.
extern "C" void LLVMInitializePowerPCAsmParser() {
RegisterMCAsmParser<PPCAsmParser> A(ThePPC32Target);
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
index 7057797cf8c..fa0e78ab3a7 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
@@ -16,12 +16,14 @@
#include "PPCMCAsmInfo.h"
#include "PPCTargetStreamer.h"
#include "llvm/MC/MCCodeGenInfo.h"
+#include "llvm/MC/MCELFStreamer.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MachineLocation.h"
+#include "llvm/Support/ELF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/TargetRegistry.h"
@@ -125,12 +127,18 @@ public:
void emitMachine(StringRef CPU) override {
OS << "\t.machine " << CPU << '\n';
}
+ virtual void emitAbiVersion(int AbiVersion) override {
+ OS << "\t.abiversion " << AbiVersion << '\n';
+ }
};
class PPCTargetELFStreamer : public PPCTargetStreamer {
public:
PPCTargetELFStreamer(MCStreamer &S) : PPCTargetStreamer(S) {}
- void emitTCEntry(const MCSymbol &S) override {
+ MCELFStreamer &getStreamer() {
+ return static_cast<MCELFStreamer &>(Streamer);
+ }
+ virtual void emitTCEntry(const MCSymbol &S) override {
// Creates a R_PPC64_TOC relocation
Streamer.EmitSymbolValue(&S, 8);
}
@@ -138,6 +146,13 @@ public:
// FIXME: Is there anything to do in here or does this directive only
// limit the parser?
}
+ virtual void emitAbiVersion(int AbiVersion) override {
+ MCAssembler &MCA = getStreamer().getAssembler();
+ unsigned Flags = MCA.getELFHeaderEFlags();
+ Flags &= ~ELF::EF_PPC64_ABI;
+ Flags |= (AbiVersion & ELF::EF_PPC64_ABI);
+ MCA.setELFHeaderEFlags(Flags);
+ }
};
class PPCTargetMachOStreamer : public PPCTargetStreamer {
@@ -150,6 +165,9 @@ public:
// FIXME: We should update the CPUType, CPUSubType in the Object file if
// the new values are different from the defaults.
}
+ virtual void emitAbiVersion(int AbiVersion) override {
+ llvm_unreachable("Unknown pseudo-op: .abiversion");
+ }
};
}
diff --git a/llvm/lib/Target/PowerPC/PPCTargetStreamer.h b/llvm/lib/Target/PowerPC/PPCTargetStreamer.h
index 74b5f458452..9baf57d4c72 100644
--- a/llvm/lib/Target/PowerPC/PPCTargetStreamer.h
+++ b/llvm/lib/Target/PowerPC/PPCTargetStreamer.h
@@ -19,6 +19,7 @@ public:
virtual ~PPCTargetStreamer();
virtual void emitTCEntry(const MCSymbol &S) = 0;
virtual void emitMachine(StringRef CPU) = 0;
+ virtual void emitAbiVersion(int AbiVersion) = 0;
};
}
diff --git a/llvm/test/MC/PowerPC/ppc64-abiversion.s b/llvm/test/MC/PowerPC/ppc64-abiversion.s
new file mode 100644
index 00000000000..d2970f8c905
--- /dev/null
+++ b/llvm/test/MC/PowerPC/ppc64-abiversion.s
@@ -0,0 +1,9 @@
+
+# RUN: llvm-mc -triple powerpc64-unknown-unknown -filetype=obj %s | \
+# RUN: llvm-readobj -h | FileCheck %s
+# RUN: llvm-mc -triple powerpc64le-unknown-unknown -filetype=obj %s | \
+# RUN: llvm-readobj -h | FileCheck %s
+
+ .abiversion 2
+# CHECK: Flags [ (0x2)
+
OpenPOWER on IntegriCloud