1 //===-- PPCAsmBackend.cpp - PPC Assembler Backend -------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "MCTargetDesc/PPCFixupKinds.h"
10 #include "MCTargetDesc/PPCMCTargetDesc.h"
11 #include "llvm/BinaryFormat/ELF.h"
12 #include "llvm/BinaryFormat/MachO.h"
13 #include "llvm/MC/MCAsmBackend.h"
14 #include "llvm/MC/MCAssembler.h"
15 #include "llvm/MC/MCELFObjectWriter.h"
16 #include "llvm/MC/MCFixupKindInfo.h"
17 #include "llvm/MC/MCMachObjectWriter.h"
18 #include "llvm/MC/MCObjectWriter.h"
19 #include "llvm/MC/MCSectionMachO.h"
20 #include "llvm/MC/MCSubtargetInfo.h"
21 #include "llvm/MC/MCSymbolELF.h"
22 #include "llvm/MC/MCValue.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include "llvm/Support/TargetRegistry.h"
27 static uint64_t adjustFixupValue(unsigned Kind
, uint64_t Value
) {
30 llvm_unreachable("Unknown fixup kind!");
36 case PPC::fixup_ppc_nofixup
:
38 case PPC::fixup_ppc_brcond14
:
39 case PPC::fixup_ppc_brcond14abs
:
40 return Value
& 0xfffc;
41 case PPC::fixup_ppc_br24
:
42 case PPC::fixup_ppc_br24abs
:
43 return Value
& 0x3fffffc;
44 case PPC::fixup_ppc_half16
:
45 return Value
& 0xffff;
46 case PPC::fixup_ppc_half16ds
:
47 return Value
& 0xfffc;
51 static unsigned getFixupKindNumBytes(unsigned Kind
) {
54 llvm_unreachable("Unknown fixup kind!");
60 case PPC::fixup_ppc_half16
:
61 case PPC::fixup_ppc_half16ds
:
64 case PPC::fixup_ppc_brcond14
:
65 case PPC::fixup_ppc_brcond14abs
:
66 case PPC::fixup_ppc_br24
:
67 case PPC::fixup_ppc_br24abs
:
71 case PPC::fixup_ppc_nofixup
:
78 class PPCAsmBackend
: public MCAsmBackend
{
82 PPCAsmBackend(const Target
&T
, const Triple
&TT
)
83 : MCAsmBackend(TT
.isLittleEndian() ? support::little
: support::big
),
86 unsigned getNumFixupKinds() const override
{
87 return PPC::NumTargetFixupKinds
;
90 const MCFixupKindInfo
&getFixupKindInfo(MCFixupKind Kind
) const override
{
91 const static MCFixupKindInfo InfosBE
[PPC::NumTargetFixupKinds
] = {
92 // name offset bits flags
93 { "fixup_ppc_br24", 6, 24, MCFixupKindInfo::FKF_IsPCRel
},
94 { "fixup_ppc_brcond14", 16, 14, MCFixupKindInfo::FKF_IsPCRel
},
95 { "fixup_ppc_br24abs", 6, 24, 0 },
96 { "fixup_ppc_brcond14abs", 16, 14, 0 },
97 { "fixup_ppc_half16", 0, 16, 0 },
98 { "fixup_ppc_half16ds", 0, 14, 0 },
99 { "fixup_ppc_nofixup", 0, 0, 0 }
101 const static MCFixupKindInfo InfosLE
[PPC::NumTargetFixupKinds
] = {
102 // name offset bits flags
103 { "fixup_ppc_br24", 2, 24, MCFixupKindInfo::FKF_IsPCRel
},
104 { "fixup_ppc_brcond14", 2, 14, MCFixupKindInfo::FKF_IsPCRel
},
105 { "fixup_ppc_br24abs", 2, 24, 0 },
106 { "fixup_ppc_brcond14abs", 2, 14, 0 },
107 { "fixup_ppc_half16", 0, 16, 0 },
108 { "fixup_ppc_half16ds", 2, 14, 0 },
109 { "fixup_ppc_nofixup", 0, 0, 0 }
112 if (Kind
< FirstTargetFixupKind
)
113 return MCAsmBackend::getFixupKindInfo(Kind
);
115 assert(unsigned(Kind
- FirstTargetFixupKind
) < getNumFixupKinds() &&
117 return (Endian
== support::little
119 : InfosBE
)[Kind
- FirstTargetFixupKind
];
122 void applyFixup(const MCAssembler
&Asm
, const MCFixup
&Fixup
,
123 const MCValue
&Target
, MutableArrayRef
<char> Data
,
124 uint64_t Value
, bool IsResolved
,
125 const MCSubtargetInfo
*STI
) const override
{
126 Value
= adjustFixupValue(Fixup
.getKind(), Value
);
127 if (!Value
) return; // Doesn't change encoding.
129 unsigned Offset
= Fixup
.getOffset();
130 unsigned NumBytes
= getFixupKindNumBytes(Fixup
.getKind());
132 // For each byte of the fragment that the fixup touches, mask in the bits
133 // from the fixup value. The Value has been "split up" into the appropriate
135 for (unsigned i
= 0; i
!= NumBytes
; ++i
) {
136 unsigned Idx
= Endian
== support::little
? i
: (NumBytes
- 1 - i
);
137 Data
[Offset
+ i
] |= uint8_t((Value
>> (Idx
* 8)) & 0xff);
141 bool shouldForceRelocation(const MCAssembler
&Asm
, const MCFixup
&Fixup
,
142 const MCValue
&Target
) override
{
143 switch ((unsigned)Fixup
.getKind()) {
148 case PPC::fixup_ppc_br24
:
149 case PPC::fixup_ppc_br24abs
:
150 // If the target symbol has a local entry point we must not attempt
151 // to resolve the fixup directly. Emit a relocation and leave
152 // resolution of the final target address to the linker.
153 if (const MCSymbolRefExpr
*A
= Target
.getSymA()) {
154 if (const auto *S
= dyn_cast
<MCSymbolELF
>(&A
->getSymbol())) {
155 // The "other" values are stored in the last 6 bits of the second
156 // byte. The traditional defines for STO values assume the full byte
157 // and thus the shift to pack it.
158 unsigned Other
= S
->getOther() << 2;
159 if ((Other
& ELF::STO_PPC64_LOCAL_MASK
) != 0)
167 bool mayNeedRelaxation(const MCInst
&Inst
,
168 const MCSubtargetInfo
&STI
) const override
{
173 bool fixupNeedsRelaxation(const MCFixup
&Fixup
,
175 const MCRelaxableFragment
*DF
,
176 const MCAsmLayout
&Layout
) const override
{
178 llvm_unreachable("relaxInstruction() unimplemented");
181 void relaxInstruction(const MCInst
&Inst
, const MCSubtargetInfo
&STI
,
182 MCInst
&Res
) const override
{
184 llvm_unreachable("relaxInstruction() unimplemented");
187 bool writeNopData(raw_ostream
&OS
, uint64_t Count
) const override
{
188 uint64_t NumNops
= Count
/ 4;
189 for (uint64_t i
= 0; i
!= NumNops
; ++i
)
190 support::endian::write
<uint32_t>(OS
, 0x60000000, Endian
);
192 OS
.write_zeros(Count
% 4);
197 } // end anonymous namespace
200 // FIXME: This should be in a separate file.
203 class DarwinPPCAsmBackend
: public PPCAsmBackend
{
205 DarwinPPCAsmBackend(const Target
&T
, const Triple
&TT
)
206 : PPCAsmBackend(T
, TT
) {}
208 std::unique_ptr
<MCObjectTargetWriter
>
209 createObjectTargetWriter() const override
{
210 bool Is64
= TT
.isPPC64();
211 return createPPCMachObjectWriter(
213 (Is64
? MachO::CPU_TYPE_POWERPC64
: MachO::CPU_TYPE_POWERPC
),
214 MachO::CPU_SUBTYPE_POWERPC_ALL
);
218 class ELFPPCAsmBackend
: public PPCAsmBackend
{
220 ELFPPCAsmBackend(const Target
&T
, const Triple
&TT
) : PPCAsmBackend(T
, TT
) {}
222 std::unique_ptr
<MCObjectTargetWriter
>
223 createObjectTargetWriter() const override
{
224 uint8_t OSABI
= MCELFObjectTargetWriter::getOSABI(TT
.getOS());
225 bool Is64
= TT
.isPPC64();
226 return createPPCELFObjectWriter(Is64
, OSABI
);
229 Optional
<MCFixupKind
> getFixupKind(StringRef Name
) const override
;
232 class XCOFFPPCAsmBackend
: public PPCAsmBackend
{
234 XCOFFPPCAsmBackend(const Target
&T
, const Triple
&TT
)
235 : PPCAsmBackend(T
, TT
) {}
237 std::unique_ptr
<MCObjectTargetWriter
>
238 createObjectTargetWriter() const override
{
239 return createPPCXCOFFObjectWriter(TT
.isArch64Bit());
243 } // end anonymous namespace
245 Optional
<MCFixupKind
> ELFPPCAsmBackend::getFixupKind(StringRef Name
) const {
247 if (Name
== "R_PPC64_NONE")
250 if (Name
== "R_PPC_NONE")
253 return MCAsmBackend::getFixupKind(Name
);
256 MCAsmBackend
*llvm::createPPCAsmBackend(const Target
&T
,
257 const MCSubtargetInfo
&STI
,
258 const MCRegisterInfo
&MRI
,
259 const MCTargetOptions
&Options
) {
260 const Triple
&TT
= STI
.getTargetTriple();
262 return new DarwinPPCAsmBackend(T
, TT
);
264 if (TT
.isOSBinFormatXCOFF())
265 return new XCOFFPPCAsmBackend(T
, TT
);
267 return new ELFPPCAsmBackend(T
, TT
);