2012-02-18 20:03:15 +08:00
|
|
|
//===-- PPCMCTargetDesc.cpp - PowerPC Target Descriptions -----------------===//
|
2011-07-15 04:59:42 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file provides PowerPC specific target descriptions.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "PPCMCTargetDesc.h"
|
2011-07-26 05:20:24 +08:00
|
|
|
#include "InstPrinter/PPCInstPrinter.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "PPCMCAsmInfo.h"
|
2013-10-08 21:08:17 +08:00
|
|
|
#include "PPCTargetStreamer.h"
|
2011-08-24 04:15:21 +08:00
|
|
|
#include "llvm/MC/MCCodeGenInfo.h"
|
[PowerPC] ELFv2 MC support for .localentry directive
A second binutils feature needed to support ELFv2 is the .localentry
directive. In the ELFv2 ABI, functions may have two entry points:
one for calling the routine locally via "bl", and one for calling the
function via function pointer (either at the source level, or implicitly
via a PLT stub for global calls). The two entry points share a single
ELF symbol, where the ELF symbol address identifies the global entry
point address, while the local entry point is found by adding a delta
offset to the symbol address. That offset is encoded into three
platform-specific bits of the ELF symbol st_other field.
The .localentry directive instructs the assembler to set those fields
to encode a particular offset. This is typically used by a function
prologue sequence like this:
func:
addis r2, r12, (.TOC.-func)@ha
addi r2, r2, (.TOC.-func)@l
.localentry func, .-func
Note that according to the ABI, when calling the global entry point,
r12 must be set to point the global entry point address itself; while
when calling the local entry point, r2 must be set to point to the TOC
base. The two instructions between the global and local entry point in
the above example translate the first requirement into the second.
This patch implements support in the PowerPC MC streamers to emit the
.localentry directive (both into assembler and ELF object output), as
well as support in the assembler parser to parse that directive.
In addition, there is another change required in MC fixup/relocation
handling to properly deal with relocations targeting function symbols
with two entry points: When the target function is known local, the MC
layer would immediately handle the fixup by inserting the target
address -- this is wrong, since the call may need to go to the local
entry point instead. The GNU assembler handles this case by *not*
directly resolving fixups targeting functions with two entry points,
but always emits the relocation and relies on the linker to handle
this case correctly. This patch changes LLVM MC to do the same (this
is done via the processFixupValue routine).
Similarly, there are cases where the assembler would normally emit a
relocation, but "simplify" it to a relocation targeting a *section*
instead of the actual symbol. For the same reason as above, this
may be wrong when the target symbol has two entry points. The GNU
assembler again handles this case by not performing this simplification
in that case, but leaving the relocation targeting the full symbol,
which is then resolved by the linker. This patch changes LLVM MC
to do the same (via the needsRelocateWithSymbol routine).
NOTE: The method used in this patch is overly pessimistic, since the
needsRelocateWithSymbol routine currently does not have access to the
actual target symbol, and thus must always assume that it might have
two entry points. This will be improved upon by a follow-on patch
that modifies common code to pass the target symbol when calling
needsRelocateWithSymbol.
Reviewed by Hal Finkel.
llvm-svn: 213485
2014-07-21 07:06:03 +08:00
|
|
|
#include "llvm/MC/MCELF.h"
|
2014-07-21 06:56:57 +08:00
|
|
|
#include "llvm/MC/MCELFStreamer.h"
|
[PowerPC] ELFv2 MC support for .localentry directive
A second binutils feature needed to support ELFv2 is the .localentry
directive. In the ELFv2 ABI, functions may have two entry points:
one for calling the routine locally via "bl", and one for calling the
function via function pointer (either at the source level, or implicitly
via a PLT stub for global calls). The two entry points share a single
ELF symbol, where the ELF symbol address identifies the global entry
point address, while the local entry point is found by adding a delta
offset to the symbol address. That offset is encoded into three
platform-specific bits of the ELF symbol st_other field.
The .localentry directive instructs the assembler to set those fields
to encode a particular offset. This is typically used by a function
prologue sequence like this:
func:
addis r2, r12, (.TOC.-func)@ha
addi r2, r2, (.TOC.-func)@l
.localentry func, .-func
Note that according to the ABI, when calling the global entry point,
r12 must be set to point the global entry point address itself; while
when calling the local entry point, r2 must be set to point to the TOC
base. The two instructions between the global and local entry point in
the above example translate the first requirement into the second.
This patch implements support in the PowerPC MC streamers to emit the
.localentry directive (both into assembler and ELF object output), as
well as support in the assembler parser to parse that directive.
In addition, there is another change required in MC fixup/relocation
handling to properly deal with relocations targeting function symbols
with two entry points: When the target function is known local, the MC
layer would immediately handle the fixup by inserting the target
address -- this is wrong, since the call may need to go to the local
entry point instead. The GNU assembler handles this case by *not*
directly resolving fixups targeting functions with two entry points,
but always emits the relocation and relies on the linker to handle
this case correctly. This patch changes LLVM MC to do the same (this
is done via the processFixupValue routine).
Similarly, there are cases where the assembler would normally emit a
relocation, but "simplify" it to a relocation targeting a *section*
instead of the actual symbol. For the same reason as above, this
may be wrong when the target symbol has two entry points. The GNU
assembler again handles this case by not performing this simplification
in that case, but leaving the relocation targeting the full symbol,
which is then resolved by the linker. This patch changes LLVM MC
to do the same (via the needsRelocateWithSymbol routine).
NOTE: The method used in this patch is overly pessimistic, since the
needsRelocateWithSymbol routine currently does not have access to the
actual target symbol, and thus must always assume that it might have
two entry points. This will be improved upon by a follow-on patch
that modifies common code to pass the target symbol when calling
needsRelocateWithSymbol.
Reviewed by Hal Finkel.
llvm-svn: 213485
2014-07-21 07:06:03 +08:00
|
|
|
#include "llvm/MC/MCExpr.h"
|
2011-07-15 04:59:42 +08:00
|
|
|
#include "llvm/MC/MCInstrInfo.h"
|
|
|
|
#include "llvm/MC/MCRegisterInfo.h"
|
2011-07-26 03:53:23 +08:00
|
|
|
#include "llvm/MC/MCStreamer.h"
|
2011-07-15 04:59:42 +08:00
|
|
|
#include "llvm/MC/MCSubtargetInfo.h"
|
2013-10-08 21:08:17 +08:00
|
|
|
#include "llvm/MC/MCSymbol.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/MC/MachineLocation.h"
|
2014-07-21 06:56:57 +08:00
|
|
|
#include "llvm/Support/ELF.h"
|
2012-02-05 15:21:30 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2013-10-08 21:08:17 +08:00
|
|
|
#include "llvm/Support/FormattedStream.h"
|
2011-08-25 02:08:43 +08:00
|
|
|
#include "llvm/Support/TargetRegistry.h"
|
2011-07-15 04:59:42 +08:00
|
|
|
|
2014-04-22 10:03:14 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
2011-07-15 04:59:42 +08:00
|
|
|
#define GET_INSTRINFO_MC_DESC
|
|
|
|
#include "PPCGenInstrInfo.inc"
|
|
|
|
|
|
|
|
#define GET_SUBTARGETINFO_MC_DESC
|
|
|
|
#include "PPCGenSubtargetInfo.inc"
|
|
|
|
|
|
|
|
#define GET_REGINFO_MC_DESC
|
|
|
|
#include "PPCGenRegisterInfo.inc"
|
|
|
|
|
2013-11-19 08:57:56 +08:00
|
|
|
// Pin the vtable to this file.
|
|
|
|
PPCTargetStreamer::~PPCTargetStreamer() {}
|
2014-01-26 14:06:37 +08:00
|
|
|
PPCTargetStreamer::PPCTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}
|
2013-11-19 08:57:56 +08:00
|
|
|
|
2011-07-15 07:50:31 +08:00
|
|
|
static MCInstrInfo *createPPCMCInstrInfo() {
|
2011-07-15 04:59:42 +08:00
|
|
|
MCInstrInfo *X = new MCInstrInfo();
|
|
|
|
InitPPCMCInstrInfo(X);
|
|
|
|
return X;
|
|
|
|
}
|
|
|
|
|
2011-07-19 04:57:22 +08:00
|
|
|
static MCRegisterInfo *createPPCMCRegisterInfo(StringRef TT) {
|
|
|
|
Triple TheTriple(TT);
|
2013-07-26 09:35:43 +08:00
|
|
|
bool isPPC64 = (TheTriple.getArch() == Triple::ppc64 ||
|
|
|
|
TheTriple.getArch() == Triple::ppc64le);
|
2011-07-19 04:57:22 +08:00
|
|
|
unsigned Flavour = isPPC64 ? 0 : 1;
|
|
|
|
unsigned RA = isPPC64 ? PPC::LR8 : PPC::LR;
|
|
|
|
|
|
|
|
MCRegisterInfo *X = new MCRegisterInfo();
|
|
|
|
InitPPCMCRegisterInfo(X, RA, Flavour, Flavour);
|
|
|
|
return X;
|
|
|
|
}
|
|
|
|
|
2011-07-15 07:50:31 +08:00
|
|
|
static MCSubtargetInfo *createPPCMCSubtargetInfo(StringRef TT, StringRef CPU,
|
|
|
|
StringRef FS) {
|
2011-07-15 04:59:42 +08:00
|
|
|
MCSubtargetInfo *X = new MCSubtargetInfo();
|
|
|
|
InitPPCMCSubtargetInfo(X, TT, CPU, FS);
|
|
|
|
return X;
|
|
|
|
}
|
|
|
|
|
2013-05-13 09:16:13 +08:00
|
|
|
static MCAsmInfo *createPPCMCAsmInfo(const MCRegisterInfo &MRI, StringRef TT) {
|
2011-07-15 07:50:31 +08:00
|
|
|
Triple TheTriple(TT);
|
2013-07-26 09:35:43 +08:00
|
|
|
bool isPPC64 = (TheTriple.getArch() == Triple::ppc64 ||
|
|
|
|
TheTriple.getArch() == Triple::ppc64le);
|
2011-07-19 06:29:13 +08:00
|
|
|
|
|
|
|
MCAsmInfo *MAI;
|
2011-07-15 07:50:31 +08:00
|
|
|
if (TheTriple.isOSDarwin())
|
2013-12-11 05:37:41 +08:00
|
|
|
MAI = new PPCMCAsmInfoDarwin(isPPC64, TheTriple);
|
2011-07-19 06:29:13 +08:00
|
|
|
else
|
2014-08-05 02:46:13 +08:00
|
|
|
MAI = new PPCELFMCAsmInfo(isPPC64, TheTriple);
|
2011-07-19 06:29:13 +08:00
|
|
|
|
|
|
|
// Initial state of the frame pointer is R1.
|
2013-05-13 09:16:13 +08:00
|
|
|
unsigned Reg = isPPC64 ? PPC::X1 : PPC::R1;
|
|
|
|
MCCFIInstruction Inst =
|
2014-04-25 13:30:21 +08:00
|
|
|
MCCFIInstruction::createDefCfa(nullptr, MRI.getDwarfRegNum(Reg, true), 0);
|
2013-05-13 09:16:13 +08:00
|
|
|
MAI->addInitialFrameState(Inst);
|
2011-07-19 06:29:13 +08:00
|
|
|
|
|
|
|
return MAI;
|
2011-07-15 07:50:31 +08:00
|
|
|
}
|
|
|
|
|
2011-07-23 08:01:04 +08:00
|
|
|
static MCCodeGenInfo *createPPCMCCodeGenInfo(StringRef TT, Reloc::Model RM,
|
2011-11-16 16:38:26 +08:00
|
|
|
CodeModel::Model CM,
|
|
|
|
CodeGenOpt::Level OL) {
|
2011-07-19 14:37:02 +08:00
|
|
|
MCCodeGenInfo *X = new MCCodeGenInfo();
|
|
|
|
|
|
|
|
if (RM == Reloc::Default) {
|
|
|
|
Triple T(TT);
|
|
|
|
if (T.isOSDarwin())
|
|
|
|
RM = Reloc::DynamicNoPIC;
|
|
|
|
else
|
|
|
|
RM = Reloc::Static;
|
|
|
|
}
|
2012-11-28 07:36:26 +08:00
|
|
|
if (CM == CodeModel::Default) {
|
|
|
|
Triple T(TT);
|
2013-07-26 09:35:43 +08:00
|
|
|
if (!T.isOSDarwin() &&
|
|
|
|
(T.getArch() == Triple::ppc64 || T.getArch() == Triple::ppc64le))
|
2012-11-28 07:36:26 +08:00
|
|
|
CM = CodeModel::Medium;
|
|
|
|
}
|
2011-11-16 16:38:26 +08:00
|
|
|
X->InitMCCodeGenInfo(RM, CM, OL);
|
2011-07-19 14:37:02 +08:00
|
|
|
return X;
|
|
|
|
}
|
|
|
|
|
2013-10-08 21:08:17 +08:00
|
|
|
namespace {
|
|
|
|
class PPCTargetAsmStreamer : public PPCTargetStreamer {
|
|
|
|
formatted_raw_ostream &OS;
|
|
|
|
|
|
|
|
public:
|
2014-01-26 14:06:37 +08:00
|
|
|
PPCTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS)
|
|
|
|
: PPCTargetStreamer(S), OS(OS) {}
|
2014-04-29 15:57:37 +08:00
|
|
|
void emitTCEntry(const MCSymbol &S) override {
|
2013-10-08 21:08:17 +08:00
|
|
|
OS << "\t.tc ";
|
|
|
|
OS << S.getName();
|
|
|
|
OS << "[TC],";
|
|
|
|
OS << S.getName();
|
|
|
|
OS << '\n';
|
|
|
|
}
|
2014-04-29 15:57:37 +08:00
|
|
|
void emitMachine(StringRef CPU) override {
|
2014-01-25 10:35:56 +08:00
|
|
|
OS << "\t.machine " << CPU << '\n';
|
|
|
|
}
|
2014-08-31 00:48:34 +08:00
|
|
|
void emitAbiVersion(int AbiVersion) override {
|
2014-07-21 06:56:57 +08:00
|
|
|
OS << "\t.abiversion " << AbiVersion << '\n';
|
|
|
|
}
|
2014-08-31 00:48:34 +08:00
|
|
|
void emitLocalEntry(MCSymbol *S, const MCExpr *LocalOffset) override {
|
[PowerPC] ELFv2 MC support for .localentry directive
A second binutils feature needed to support ELFv2 is the .localentry
directive. In the ELFv2 ABI, functions may have two entry points:
one for calling the routine locally via "bl", and one for calling the
function via function pointer (either at the source level, or implicitly
via a PLT stub for global calls). The two entry points share a single
ELF symbol, where the ELF symbol address identifies the global entry
point address, while the local entry point is found by adding a delta
offset to the symbol address. That offset is encoded into three
platform-specific bits of the ELF symbol st_other field.
The .localentry directive instructs the assembler to set those fields
to encode a particular offset. This is typically used by a function
prologue sequence like this:
func:
addis r2, r12, (.TOC.-func)@ha
addi r2, r2, (.TOC.-func)@l
.localentry func, .-func
Note that according to the ABI, when calling the global entry point,
r12 must be set to point the global entry point address itself; while
when calling the local entry point, r2 must be set to point to the TOC
base. The two instructions between the global and local entry point in
the above example translate the first requirement into the second.
This patch implements support in the PowerPC MC streamers to emit the
.localentry directive (both into assembler and ELF object output), as
well as support in the assembler parser to parse that directive.
In addition, there is another change required in MC fixup/relocation
handling to properly deal with relocations targeting function symbols
with two entry points: When the target function is known local, the MC
layer would immediately handle the fixup by inserting the target
address -- this is wrong, since the call may need to go to the local
entry point instead. The GNU assembler handles this case by *not*
directly resolving fixups targeting functions with two entry points,
but always emits the relocation and relies on the linker to handle
this case correctly. This patch changes LLVM MC to do the same (this
is done via the processFixupValue routine).
Similarly, there are cases where the assembler would normally emit a
relocation, but "simplify" it to a relocation targeting a *section*
instead of the actual symbol. For the same reason as above, this
may be wrong when the target symbol has two entry points. The GNU
assembler again handles this case by not performing this simplification
in that case, but leaving the relocation targeting the full symbol,
which is then resolved by the linker. This patch changes LLVM MC
to do the same (via the needsRelocateWithSymbol routine).
NOTE: The method used in this patch is overly pessimistic, since the
needsRelocateWithSymbol routine currently does not have access to the
actual target symbol, and thus must always assume that it might have
two entry points. This will be improved upon by a follow-on patch
that modifies common code to pass the target symbol when calling
needsRelocateWithSymbol.
Reviewed by Hal Finkel.
llvm-svn: 213485
2014-07-21 07:06:03 +08:00
|
|
|
OS << "\t.localentry\t" << *S << ", " << *LocalOffset << '\n';
|
|
|
|
}
|
2013-10-08 21:08:17 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
class PPCTargetELFStreamer : public PPCTargetStreamer {
|
2014-01-26 14:06:37 +08:00
|
|
|
public:
|
|
|
|
PPCTargetELFStreamer(MCStreamer &S) : PPCTargetStreamer(S) {}
|
2014-07-21 06:56:57 +08:00
|
|
|
MCELFStreamer &getStreamer() {
|
|
|
|
return static_cast<MCELFStreamer &>(Streamer);
|
|
|
|
}
|
2014-08-31 00:48:34 +08:00
|
|
|
void emitTCEntry(const MCSymbol &S) override {
|
2013-10-08 21:08:17 +08:00
|
|
|
// Creates a R_PPC64_TOC relocation
|
2014-01-26 14:06:37 +08:00
|
|
|
Streamer.EmitSymbolValue(&S, 8);
|
2013-10-08 21:08:17 +08:00
|
|
|
}
|
2014-04-29 15:57:37 +08:00
|
|
|
void emitMachine(StringRef CPU) override {
|
2014-01-25 10:35:56 +08:00
|
|
|
// FIXME: Is there anything to do in here or does this directive only
|
|
|
|
// limit the parser?
|
|
|
|
}
|
2014-08-31 00:48:34 +08:00
|
|
|
void emitAbiVersion(int AbiVersion) override {
|
2014-07-21 06:56:57 +08:00
|
|
|
MCAssembler &MCA = getStreamer().getAssembler();
|
|
|
|
unsigned Flags = MCA.getELFHeaderEFlags();
|
|
|
|
Flags &= ~ELF::EF_PPC64_ABI;
|
|
|
|
Flags |= (AbiVersion & ELF::EF_PPC64_ABI);
|
|
|
|
MCA.setELFHeaderEFlags(Flags);
|
|
|
|
}
|
2014-08-31 00:48:34 +08:00
|
|
|
void emitLocalEntry(MCSymbol *S, const MCExpr *LocalOffset) override {
|
[PowerPC] ELFv2 MC support for .localentry directive
A second binutils feature needed to support ELFv2 is the .localentry
directive. In the ELFv2 ABI, functions may have two entry points:
one for calling the routine locally via "bl", and one for calling the
function via function pointer (either at the source level, or implicitly
via a PLT stub for global calls). The two entry points share a single
ELF symbol, where the ELF symbol address identifies the global entry
point address, while the local entry point is found by adding a delta
offset to the symbol address. That offset is encoded into three
platform-specific bits of the ELF symbol st_other field.
The .localentry directive instructs the assembler to set those fields
to encode a particular offset. This is typically used by a function
prologue sequence like this:
func:
addis r2, r12, (.TOC.-func)@ha
addi r2, r2, (.TOC.-func)@l
.localentry func, .-func
Note that according to the ABI, when calling the global entry point,
r12 must be set to point the global entry point address itself; while
when calling the local entry point, r2 must be set to point to the TOC
base. The two instructions between the global and local entry point in
the above example translate the first requirement into the second.
This patch implements support in the PowerPC MC streamers to emit the
.localentry directive (both into assembler and ELF object output), as
well as support in the assembler parser to parse that directive.
In addition, there is another change required in MC fixup/relocation
handling to properly deal with relocations targeting function symbols
with two entry points: When the target function is known local, the MC
layer would immediately handle the fixup by inserting the target
address -- this is wrong, since the call may need to go to the local
entry point instead. The GNU assembler handles this case by *not*
directly resolving fixups targeting functions with two entry points,
but always emits the relocation and relies on the linker to handle
this case correctly. This patch changes LLVM MC to do the same (this
is done via the processFixupValue routine).
Similarly, there are cases where the assembler would normally emit a
relocation, but "simplify" it to a relocation targeting a *section*
instead of the actual symbol. For the same reason as above, this
may be wrong when the target symbol has two entry points. The GNU
assembler again handles this case by not performing this simplification
in that case, but leaving the relocation targeting the full symbol,
which is then resolved by the linker. This patch changes LLVM MC
to do the same (via the needsRelocateWithSymbol routine).
NOTE: The method used in this patch is overly pessimistic, since the
needsRelocateWithSymbol routine currently does not have access to the
actual target symbol, and thus must always assume that it might have
two entry points. This will be improved upon by a follow-on patch
that modifies common code to pass the target symbol when calling
needsRelocateWithSymbol.
Reviewed by Hal Finkel.
llvm-svn: 213485
2014-07-21 07:06:03 +08:00
|
|
|
MCAssembler &MCA = getStreamer().getAssembler();
|
|
|
|
MCSymbolData &Data = getStreamer().getOrCreateSymbolData(S);
|
|
|
|
|
|
|
|
int64_t Res;
|
|
|
|
if (!LocalOffset->EvaluateAsAbsolute(Res, MCA))
|
|
|
|
report_fatal_error(".localentry expression must be absolute.");
|
|
|
|
|
|
|
|
unsigned Encoded = ELF::encodePPC64LocalEntryOffset(Res);
|
|
|
|
if (Res != ELF::decodePPC64LocalEntryOffset(Encoded))
|
|
|
|
report_fatal_error(".localentry expression cannot be encoded.");
|
|
|
|
|
|
|
|
// The "other" values are stored in the last 6 bits of the second byte.
|
|
|
|
// The traditional defines for STO values assume the full byte and thus
|
|
|
|
// the shift to pack it.
|
|
|
|
unsigned Other = MCELF::getOther(Data) << 2;
|
|
|
|
Other &= ~ELF::STO_PPC64_LOCAL_MASK;
|
|
|
|
Other |= Encoded;
|
|
|
|
MCELF::setOther(Data, Other >> 2);
|
|
|
|
|
|
|
|
// For GAS compatibility, unless we already saw a .abiversion directive,
|
|
|
|
// set e_flags to indicate ELFv2 ABI.
|
|
|
|
unsigned Flags = MCA.getELFHeaderEFlags();
|
|
|
|
if ((Flags & ELF::EF_PPC64_ABI) == 0)
|
|
|
|
MCA.setELFHeaderEFlags(Flags | 2);
|
|
|
|
}
|
2014-11-25 02:09:47 +08:00
|
|
|
void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override {
|
|
|
|
// When encoding an assignment to set symbol A to symbol B, also copy
|
|
|
|
// the st_other bits encoding the local entry point offset.
|
|
|
|
if (Value->getKind() != MCExpr::SymbolRef)
|
|
|
|
return;
|
|
|
|
const MCSymbol &RhsSym =
|
|
|
|
static_cast<const MCSymbolRefExpr *>(Value)->getSymbol();
|
|
|
|
MCSymbolData &Data = getStreamer().getOrCreateSymbolData(&RhsSym);
|
|
|
|
MCSymbolData &SymbolData = getStreamer().getOrCreateSymbolData(Symbol);
|
|
|
|
// The "other" values are stored in the last 6 bits of the second byte.
|
|
|
|
// The traditional defines for STO values assume the full byte and thus
|
|
|
|
// the shift to pack it.
|
|
|
|
unsigned Other = MCELF::getOther(SymbolData) << 2;
|
|
|
|
Other &= ~ELF::STO_PPC64_LOCAL_MASK;
|
|
|
|
Other |= (MCELF::getOther(Data) << 2) & ELF::STO_PPC64_LOCAL_MASK;
|
|
|
|
MCELF::setOther(SymbolData, Other >> 2);
|
|
|
|
}
|
2013-10-08 21:08:17 +08:00
|
|
|
};
|
2014-01-28 19:03:17 +08:00
|
|
|
|
|
|
|
class PPCTargetMachOStreamer : public PPCTargetStreamer {
|
|
|
|
public:
|
|
|
|
PPCTargetMachOStreamer(MCStreamer &S) : PPCTargetStreamer(S) {}
|
2014-04-29 15:57:37 +08:00
|
|
|
void emitTCEntry(const MCSymbol &S) override {
|
2014-01-28 19:03:17 +08:00
|
|
|
llvm_unreachable("Unknown pseudo-op: .tc");
|
|
|
|
}
|
2014-04-29 15:57:37 +08:00
|
|
|
void emitMachine(StringRef CPU) override {
|
2014-01-28 19:03:17 +08:00
|
|
|
// FIXME: We should update the CPUType, CPUSubType in the Object file if
|
|
|
|
// the new values are different from the defaults.
|
|
|
|
}
|
2014-08-31 00:48:34 +08:00
|
|
|
void emitAbiVersion(int AbiVersion) override {
|
2014-07-21 06:56:57 +08:00
|
|
|
llvm_unreachable("Unknown pseudo-op: .abiversion");
|
|
|
|
}
|
2014-08-31 00:48:34 +08:00
|
|
|
void emitLocalEntry(MCSymbol *S, const MCExpr *LocalOffset) override {
|
[PowerPC] ELFv2 MC support for .localentry directive
A second binutils feature needed to support ELFv2 is the .localentry
directive. In the ELFv2 ABI, functions may have two entry points:
one for calling the routine locally via "bl", and one for calling the
function via function pointer (either at the source level, or implicitly
via a PLT stub for global calls). The two entry points share a single
ELF symbol, where the ELF symbol address identifies the global entry
point address, while the local entry point is found by adding a delta
offset to the symbol address. That offset is encoded into three
platform-specific bits of the ELF symbol st_other field.
The .localentry directive instructs the assembler to set those fields
to encode a particular offset. This is typically used by a function
prologue sequence like this:
func:
addis r2, r12, (.TOC.-func)@ha
addi r2, r2, (.TOC.-func)@l
.localentry func, .-func
Note that according to the ABI, when calling the global entry point,
r12 must be set to point the global entry point address itself; while
when calling the local entry point, r2 must be set to point to the TOC
base. The two instructions between the global and local entry point in
the above example translate the first requirement into the second.
This patch implements support in the PowerPC MC streamers to emit the
.localentry directive (both into assembler and ELF object output), as
well as support in the assembler parser to parse that directive.
In addition, there is another change required in MC fixup/relocation
handling to properly deal with relocations targeting function symbols
with two entry points: When the target function is known local, the MC
layer would immediately handle the fixup by inserting the target
address -- this is wrong, since the call may need to go to the local
entry point instead. The GNU assembler handles this case by *not*
directly resolving fixups targeting functions with two entry points,
but always emits the relocation and relies on the linker to handle
this case correctly. This patch changes LLVM MC to do the same (this
is done via the processFixupValue routine).
Similarly, there are cases where the assembler would normally emit a
relocation, but "simplify" it to a relocation targeting a *section*
instead of the actual symbol. For the same reason as above, this
may be wrong when the target symbol has two entry points. The GNU
assembler again handles this case by not performing this simplification
in that case, but leaving the relocation targeting the full symbol,
which is then resolved by the linker. This patch changes LLVM MC
to do the same (via the needsRelocateWithSymbol routine).
NOTE: The method used in this patch is overly pessimistic, since the
needsRelocateWithSymbol routine currently does not have access to the
actual target symbol, and thus must always assume that it might have
two entry points. This will be improved upon by a follow-on patch
that modifies common code to pass the target symbol when calling
needsRelocateWithSymbol.
Reviewed by Hal Finkel.
llvm-svn: 213485
2014-07-21 07:06:03 +08:00
|
|
|
llvm_unreachable("Unknown pseudo-op: .localentry");
|
|
|
|
}
|
2014-01-28 19:03:17 +08:00
|
|
|
};
|
2013-10-08 21:08:17 +08:00
|
|
|
}
|
|
|
|
|
2011-07-26 03:53:23 +08:00
|
|
|
// This is duplicated code. Refactor this.
|
2011-07-26 08:42:34 +08:00
|
|
|
static MCStreamer *createMCStreamer(const Target &T, StringRef TT,
|
2011-07-26 07:24:55 +08:00
|
|
|
MCContext &Ctx, MCAsmBackend &MAB,
|
2014-10-16 00:12:52 +08:00
|
|
|
raw_ostream &OS, MCCodeEmitter *Emitter,
|
|
|
|
const MCSubtargetInfo &STI, bool RelaxAll) {
|
2014-01-28 19:03:17 +08:00
|
|
|
if (Triple(TT).isOSDarwin()) {
|
|
|
|
MCStreamer *S = createMachOStreamer(Ctx, MAB, OS, Emitter, RelaxAll);
|
|
|
|
new PPCTargetMachOStreamer(*S);
|
|
|
|
return S;
|
|
|
|
}
|
2011-07-26 03:53:23 +08:00
|
|
|
|
2014-10-16 00:12:52 +08:00
|
|
|
MCStreamer *S = createELFStreamer(Ctx, MAB, OS, Emitter, RelaxAll);
|
2014-01-26 14:06:37 +08:00
|
|
|
new PPCTargetELFStreamer(*S);
|
|
|
|
return S;
|
2013-10-08 21:08:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static MCStreamer *
|
|
|
|
createMCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS,
|
2014-05-07 21:00:43 +08:00
|
|
|
bool isVerboseAsm, bool useDwarfDirectory,
|
2014-02-06 02:00:21 +08:00
|
|
|
MCInstPrinter *InstPrint, MCCodeEmitter *CE,
|
|
|
|
MCAsmBackend *TAB, bool ShowInst) {
|
2013-10-08 21:08:17 +08:00
|
|
|
|
2014-05-07 21:00:43 +08:00
|
|
|
MCStreamer *S = llvm::createAsmStreamer(
|
|
|
|
Ctx, OS, isVerboseAsm, useDwarfDirectory, InstPrint, CE, TAB, ShowInst);
|
2014-01-26 14:06:37 +08:00
|
|
|
new PPCTargetAsmStreamer(*S, OS);
|
|
|
|
return S;
|
2011-07-26 03:53:23 +08:00
|
|
|
}
|
|
|
|
|
2011-07-26 05:20:24 +08:00
|
|
|
static MCInstPrinter *createPPCMCInstPrinter(const Target &T,
|
|
|
|
unsigned SyntaxVariant,
|
2011-09-08 01:24:38 +08:00
|
|
|
const MCAsmInfo &MAI,
|
2012-04-02 14:09:36 +08:00
|
|
|
const MCInstrInfo &MII,
|
2012-03-06 03:33:20 +08:00
|
|
|
const MCRegisterInfo &MRI,
|
2011-09-08 01:24:38 +08:00
|
|
|
const MCSubtargetInfo &STI) {
|
[PowerPC] Always use "assembler dialect" 1
A setting in MCAsmInfo defines the "assembler dialect" to use. This is used
by common code to choose between alternatives in a multi-alternative GNU
inline asm statement like the following:
__asm__ ("{sfe|subfe} %0,%1,%2" : "=r" (out) : "r" (in1), "r" (in2));
The meaning of these dialects is platform specific, and GCC defines those
for PowerPC to use dialect 0 for old-style (POWER) mnemonics and 1 for
new-style (PowerPC) mnemonics, like in the example above.
To be compatible with inline asm used with GCC, LLVM ought to do the same.
Specifically, this means we should always use assembler dialect 1 since
old-style mnemonics really aren't supported on any current platform.
However, the current LLVM back-end uses:
AssemblerDialect = 1; // New-Style mnemonics.
in PPCMCAsmInfoDarwin, and
AssemblerDialect = 0; // Old-Style mnemonics.
in PPCLinuxMCAsmInfo.
The Linux setting really isn't correct, we should be using new-style
mnemonics everywhere. This is changed by this commit.
Unfortunately, the setting of this variable is overloaded in the back-end
to decide whether or not we are on a Darwin target. This is done in
PPCInstPrinter (the "SyntaxVariant" is initialized from the MCAsmInfo
AssemblerDialect setting), and also in PPCMCExpr. Setting AssemblerDialect
to 1 for both Darwin and Linux no longer allows us to make this distinction.
Instead, this patch uses the MCSubtargetInfo passed to createPPCMCInstPrinter
to distinguish Darwin targets, and ignores the SyntaxVariant parameter.
As to PPCMCExpr, this patch adds an explicit isDarwin argument that needs
to be passed in by the caller when creating a target MCExpr. (To do so
this patch implicitly also reverts commit 184441.)
llvm-svn: 185858
2013-07-09 04:20:51 +08:00
|
|
|
bool isDarwin = Triple(STI.getTargetTriple()).isOSDarwin();
|
|
|
|
return new PPCInstPrinter(MAI, MII, MRI, isDarwin);
|
2011-07-26 05:20:24 +08:00
|
|
|
}
|
|
|
|
|
2011-07-23 05:58:54 +08:00
|
|
|
extern "C" void LLVMInitializePowerPCTargetMC() {
|
|
|
|
// Register the MC asm info.
|
|
|
|
RegisterMCAsmInfoFn C(ThePPC32Target, createPPCMCAsmInfo);
|
|
|
|
RegisterMCAsmInfoFn D(ThePPC64Target, createPPCMCAsmInfo);
|
2013-07-26 09:35:43 +08:00
|
|
|
RegisterMCAsmInfoFn E(ThePPC64LETarget, createPPCMCAsmInfo);
|
2011-07-23 05:58:54 +08:00
|
|
|
|
|
|
|
// Register the MC codegen info.
|
2011-07-19 14:37:02 +08:00
|
|
|
TargetRegistry::RegisterMCCodeGenInfo(ThePPC32Target, createPPCMCCodeGenInfo);
|
|
|
|
TargetRegistry::RegisterMCCodeGenInfo(ThePPC64Target, createPPCMCCodeGenInfo);
|
2013-07-26 09:35:43 +08:00
|
|
|
TargetRegistry::RegisterMCCodeGenInfo(ThePPC64LETarget,
|
|
|
|
createPPCMCCodeGenInfo);
|
2011-07-23 05:58:54 +08:00
|
|
|
|
|
|
|
// Register the MC instruction info.
|
|
|
|
TargetRegistry::RegisterMCInstrInfo(ThePPC32Target, createPPCMCInstrInfo);
|
|
|
|
TargetRegistry::RegisterMCInstrInfo(ThePPC64Target, createPPCMCInstrInfo);
|
2013-07-26 09:35:43 +08:00
|
|
|
TargetRegistry::RegisterMCInstrInfo(ThePPC64LETarget,
|
|
|
|
createPPCMCInstrInfo);
|
2011-07-23 05:58:54 +08:00
|
|
|
|
|
|
|
// Register the MC register info.
|
|
|
|
TargetRegistry::RegisterMCRegInfo(ThePPC32Target, createPPCMCRegisterInfo);
|
|
|
|
TargetRegistry::RegisterMCRegInfo(ThePPC64Target, createPPCMCRegisterInfo);
|
2013-07-26 09:35:43 +08:00
|
|
|
TargetRegistry::RegisterMCRegInfo(ThePPC64LETarget, createPPCMCRegisterInfo);
|
2011-07-23 05:58:54 +08:00
|
|
|
|
|
|
|
// Register the MC subtarget info.
|
|
|
|
TargetRegistry::RegisterMCSubtargetInfo(ThePPC32Target,
|
|
|
|
createPPCMCSubtargetInfo);
|
|
|
|
TargetRegistry::RegisterMCSubtargetInfo(ThePPC64Target,
|
|
|
|
createPPCMCSubtargetInfo);
|
2013-07-26 09:35:43 +08:00
|
|
|
TargetRegistry::RegisterMCSubtargetInfo(ThePPC64LETarget,
|
|
|
|
createPPCMCSubtargetInfo);
|
2011-07-26 03:53:23 +08:00
|
|
|
|
|
|
|
// Register the MC Code Emitter
|
2011-07-26 08:42:34 +08:00
|
|
|
TargetRegistry::RegisterMCCodeEmitter(ThePPC32Target, createPPCMCCodeEmitter);
|
|
|
|
TargetRegistry::RegisterMCCodeEmitter(ThePPC64Target, createPPCMCCodeEmitter);
|
2013-07-26 09:35:43 +08:00
|
|
|
TargetRegistry::RegisterMCCodeEmitter(ThePPC64LETarget,
|
|
|
|
createPPCMCCodeEmitter);
|
2011-07-26 03:53:23 +08:00
|
|
|
|
|
|
|
// Register the asm backend.
|
2011-07-26 07:24:55 +08:00
|
|
|
TargetRegistry::RegisterMCAsmBackend(ThePPC32Target, createPPCAsmBackend);
|
|
|
|
TargetRegistry::RegisterMCAsmBackend(ThePPC64Target, createPPCAsmBackend);
|
2013-07-26 09:35:43 +08:00
|
|
|
TargetRegistry::RegisterMCAsmBackend(ThePPC64LETarget, createPPCAsmBackend);
|
2011-07-26 03:53:23 +08:00
|
|
|
|
|
|
|
// Register the object streamer.
|
2011-07-26 08:42:34 +08:00
|
|
|
TargetRegistry::RegisterMCObjectStreamer(ThePPC32Target, createMCStreamer);
|
|
|
|
TargetRegistry::RegisterMCObjectStreamer(ThePPC64Target, createMCStreamer);
|
2013-07-26 09:35:43 +08:00
|
|
|
TargetRegistry::RegisterMCObjectStreamer(ThePPC64LETarget, createMCStreamer);
|
2011-07-26 05:20:24 +08:00
|
|
|
|
2013-10-08 21:08:17 +08:00
|
|
|
// Register the asm streamer.
|
|
|
|
TargetRegistry::RegisterAsmStreamer(ThePPC32Target, createMCAsmStreamer);
|
|
|
|
TargetRegistry::RegisterAsmStreamer(ThePPC64Target, createMCAsmStreamer);
|
|
|
|
TargetRegistry::RegisterAsmStreamer(ThePPC64LETarget, createMCAsmStreamer);
|
|
|
|
|
2011-07-26 05:20:24 +08:00
|
|
|
// Register the MCInstPrinter.
|
|
|
|
TargetRegistry::RegisterMCInstPrinter(ThePPC32Target, createPPCMCInstPrinter);
|
|
|
|
TargetRegistry::RegisterMCInstPrinter(ThePPC64Target, createPPCMCInstPrinter);
|
2013-07-26 09:35:43 +08:00
|
|
|
TargetRegistry::RegisterMCInstPrinter(ThePPC64LETarget,
|
|
|
|
createPPCMCInstPrinter);
|
2011-07-19 14:37:02 +08:00
|
|
|
}
|