xref: /freebsd/contrib/llvm-project/lld/ELF/Arch/PPC.cpp (revision 2c2ec6bbc9cc7762a250ffe903bda6c2e44d25ff)
1 //===- PPC.cpp ------------------------------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "OutputSections.h"
10 #include "Symbols.h"
11 #include "SyntheticSections.h"
12 #include "Target.h"
13 #include "Thunks.h"
14 
15 using namespace llvm;
16 using namespace llvm::support::endian;
17 using namespace llvm::ELF;
18 using namespace lld;
19 using namespace lld::elf;
20 
21 // Undefine the macro predefined by GCC powerpc32.
22 #undef PPC
23 
24 namespace {
25 class PPC final : public TargetInfo {
26 public:
27   PPC(Ctx &);
28   RelExpr getRelExpr(RelType type, const Symbol &s,
29                      const uint8_t *loc) const override;
30   RelType getDynRel(RelType type) const override;
31   int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override;
32   void writeGotHeader(uint8_t *buf) const override;
33   void writePltHeader(uint8_t *buf) const override {
34     llvm_unreachable("should call writePPC32GlinkSection() instead");
35   }
36   void writePlt(uint8_t *buf, const Symbol &sym,
37                 uint64_t pltEntryAddr) const override {
38     llvm_unreachable("should call writePPC32GlinkSection() instead");
39   }
40   void writeIplt(uint8_t *buf, const Symbol &sym,
41                  uint64_t pltEntryAddr) const override;
42   void writeGotPlt(uint8_t *buf, const Symbol &s) const override;
43   bool needsThunk(RelExpr expr, RelType relocType, const InputFile *file,
44                   uint64_t branchAddr, const Symbol &s,
45                   int64_t a) const override;
46   uint32_t getThunkSectionSpacing() const override;
47   bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const override;
48   void relocate(uint8_t *loc, const Relocation &rel,
49                 uint64_t val) const override;
50   RelExpr adjustTlsExpr(RelType type, RelExpr expr) const override;
51   int getTlsGdRelaxSkip(RelType type) const override;
52   void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override;
53 
54 private:
55   void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
56   void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
57   void relaxTlsLdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
58   void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
59 };
60 } // namespace
61 
62 static uint16_t lo(uint32_t v) { return v; }
63 static uint16_t ha(uint32_t v) { return (v + 0x8000) >> 16; }
64 
65 static uint32_t readFromHalf16(Ctx &ctx, const uint8_t *loc) {
66   return read32(ctx, ctx.arg.isLE ? loc : loc - 2);
67 }
68 
69 static void writeFromHalf16(Ctx &ctx, uint8_t *loc, uint32_t insn) {
70   write32(ctx, ctx.arg.isLE ? loc : loc - 2, insn);
71 }
72 
73 void elf::writePPC32GlinkSection(Ctx &ctx, uint8_t *buf, size_t numEntries) {
74   // Create canonical PLT entries for non-PIE code. Compilers don't generate
75   // non-GOT-non-PLT relocations referencing external functions for -fpie/-fPIE.
76   uint32_t glink = ctx.in.plt->getVA(); // VA of .glink
77   if (!ctx.arg.isPic) {
78     for (const Symbol *sym :
79          cast<PPC32GlinkSection>(*ctx.in.plt).canonical_plts) {
80       writePPC32PltCallStub(ctx, buf, sym->getGotPltVA(ctx), nullptr, 0);
81       buf += 16;
82       glink += 16;
83     }
84   }
85 
86   // On PPC Secure PLT ABI, bl foo@plt jumps to a call stub, which loads an
87   // absolute address from a specific .plt slot (usually called .got.plt on
88   // other targets) and jumps there.
89   //
90   // a) With immediate binding (BIND_NOW), the .plt entry is resolved at load
91   // time. The .glink section is not used.
92   // b) With lazy binding, the .plt entry points to a `b PLTresolve`
93   // instruction in .glink, filled in by PPC::writeGotPlt().
94 
95   // Write N `b PLTresolve` first.
96   for (size_t i = 0; i != numEntries; ++i)
97     write32(ctx, buf + 4 * i, 0x48000000 | 4 * (numEntries - i));
98   buf += 4 * numEntries;
99 
100   // Then write PLTresolve(), which has two forms: PIC and non-PIC. PLTresolve()
101   // computes the PLT index (by computing the distance from the landing b to
102   // itself) and calls _dl_runtime_resolve() (in glibc).
103   uint32_t got = ctx.in.got->getVA();
104   const uint8_t *end = buf + 64;
105   if (ctx.arg.isPic) {
106     uint32_t afterBcl = 4 * ctx.in.plt->getNumEntries() + 12;
107     uint32_t gotBcl = got + 4 - (glink + afterBcl);
108     write32(ctx, buf + 0,
109             0x3d6b0000 | ha(afterBcl)); // addis r11,r11,1f-glink@ha
110     write32(ctx, buf + 4, 0x7c0802a6);  // mflr r0
111     write32(ctx, buf + 8, 0x429f0005);  // bcl 20,30,.+4
112     write32(ctx, buf + 12,
113             0x396b0000 | lo(afterBcl)); // 1: addi r11,r11,1b-glink@l
114     write32(ctx, buf + 16, 0x7d8802a6); // mflr r12
115     write32(ctx, buf + 20, 0x7c0803a6); // mtlr r0
116     write32(ctx, buf + 24, 0x7d6c5850); // sub r11,r11,r12
117     write32(ctx, buf + 28, 0x3d8c0000 | ha(gotBcl)); // addis 12,12,GOT+4-1b@ha
118     if (ha(gotBcl) == ha(gotBcl + 4)) {
119       write32(ctx, buf + 32,
120               0x800c0000 | lo(gotBcl)); // lwz r0,r12,GOT+4-1b@l(r12)
121       write32(ctx, buf + 36,
122               0x818c0000 | lo(gotBcl + 4)); // lwz r12,r12,GOT+8-1b@l(r12)
123     } else {
124       write32(ctx, buf + 32,
125               0x840c0000 | lo(gotBcl));       // lwzu r0,r12,GOT+4-1b@l(r12)
126       write32(ctx, buf + 36, 0x818c0000 | 4); // lwz r12,r12,4(r12)
127     }
128     write32(ctx, buf + 40, 0x7c0903a6); // mtctr 0
129     write32(ctx, buf + 44, 0x7c0b5a14); // add r0,11,11
130     write32(ctx, buf + 48, 0x7d605a14); // add r11,0,11
131     write32(ctx, buf + 52, 0x4e800420); // bctr
132     buf += 56;
133   } else {
134     write32(ctx, buf + 0, 0x3d800000 | ha(got + 4)); // lis     r12,GOT+4@ha
135     write32(ctx, buf + 4, 0x3d6b0000 | ha(-glink)); // addis   r11,r11,-glink@ha
136     if (ha(got + 4) == ha(got + 8))
137       write32(ctx, buf + 8, 0x800c0000 | lo(got + 4)); // lwz r0,GOT+4@l(r12)
138     else
139       write32(ctx, buf + 8, 0x840c0000 | lo(got + 4)); // lwzu r0,GOT+4@l(r12)
140     write32(ctx, buf + 12, 0x396b0000 | lo(-glink)); // addi    r11,r11,-glink@l
141     write32(ctx, buf + 16, 0x7c0903a6);              // mtctr   r0
142     write32(ctx, buf + 20, 0x7c0b5a14);              // add     r0,r11,r11
143     if (ha(got + 4) == ha(got + 8))
144       write32(ctx, buf + 24, 0x818c0000 | lo(got + 8)); // lwz r12,GOT+8@l(r12)
145     else
146       write32(ctx, buf + 24, 0x818c0000 | 4); // lwz r12,4(r12)
147     write32(ctx, buf + 28, 0x7d605a14);       // add     r11,r0,r11
148     write32(ctx, buf + 32, 0x4e800420);       // bctr
149     buf += 36;
150   }
151 
152   // Pad with nop. They should not be executed.
153   for (; buf < end; buf += 4)
154     write32(ctx, buf, 0x60000000);
155 }
156 
157 PPC::PPC(Ctx &ctx) : TargetInfo(ctx) {
158   copyRel = R_PPC_COPY;
159   gotRel = R_PPC_GLOB_DAT;
160   pltRel = R_PPC_JMP_SLOT;
161   relativeRel = R_PPC_RELATIVE;
162   iRelativeRel = R_PPC_IRELATIVE;
163   symbolicRel = R_PPC_ADDR32;
164   gotHeaderEntriesNum = 3;
165   gotPltHeaderEntriesNum = 0;
166   pltHeaderSize = 0;
167   pltEntrySize = 4;
168   ipltEntrySize = 16;
169 
170   needsThunks = true;
171 
172   tlsModuleIndexRel = R_PPC_DTPMOD32;
173   tlsOffsetRel = R_PPC_DTPREL32;
174   tlsGotRel = R_PPC_TPREL32;
175 
176   defaultMaxPageSize = 65536;
177   defaultImageBase = 0x10000000;
178 
179   write32(ctx, trapInstr.data(), 0x7fe00008);
180 }
181 
182 void PPC::writeIplt(uint8_t *buf, const Symbol &sym,
183                     uint64_t /*pltEntryAddr*/) const {
184   // In -pie or -shared mode, assume r30 points to .got2+0x8000, and use a
185   // .got2.plt_pic32. thunk.
186   writePPC32PltCallStub(ctx, buf, sym.getGotPltVA(ctx), sym.file, 0x8000);
187 }
188 
189 void PPC::writeGotHeader(uint8_t *buf) const {
190   // _GLOBAL_OFFSET_TABLE_[0] = _DYNAMIC
191   // glibc stores _dl_runtime_resolve in _GLOBAL_OFFSET_TABLE_[1],
192   // link_map in _GLOBAL_OFFSET_TABLE_[2].
193   write32(ctx, buf, ctx.mainPart->dynamic->getVA());
194 }
195 
196 void PPC::writeGotPlt(uint8_t *buf, const Symbol &s) const {
197   // Address of the symbol resolver stub in .glink .
198   write32(ctx, buf,
199           ctx.in.plt->getVA() + ctx.in.plt->headerSize + 4 * s.getPltIdx(ctx));
200 }
201 
202 bool PPC::needsThunk(RelExpr expr, RelType type, const InputFile *file,
203                      uint64_t branchAddr, const Symbol &s, int64_t a) const {
204   if (type != R_PPC_LOCAL24PC && type != R_PPC_REL24 && type != R_PPC_PLTREL24)
205     return false;
206   if (s.isInPlt(ctx))
207     return true;
208   if (s.isUndefWeak())
209     return false;
210   return !PPC::inBranchRange(type, branchAddr, s.getVA(ctx, a));
211 }
212 
213 uint32_t PPC::getThunkSectionSpacing() const { return 0x2000000; }
214 
215 bool PPC::inBranchRange(RelType type, uint64_t src, uint64_t dst) const {
216   uint64_t offset = dst - src;
217   if (type == R_PPC_LOCAL24PC || type == R_PPC_REL24 || type == R_PPC_PLTREL24)
218     return isInt<26>(offset);
219   llvm_unreachable("unsupported relocation type used in branch");
220 }
221 
222 RelExpr PPC::getRelExpr(RelType type, const Symbol &s,
223                         const uint8_t *loc) const {
224   switch (type) {
225   case R_PPC_NONE:
226     return R_NONE;
227   case R_PPC_ADDR16_HA:
228   case R_PPC_ADDR16_HI:
229   case R_PPC_ADDR16_LO:
230   case R_PPC_ADDR24:
231   case R_PPC_ADDR32:
232     return R_ABS;
233   case R_PPC_DTPREL16:
234   case R_PPC_DTPREL16_HA:
235   case R_PPC_DTPREL16_HI:
236   case R_PPC_DTPREL16_LO:
237   case R_PPC_DTPREL32:
238     return R_DTPREL;
239   case R_PPC_REL14:
240   case R_PPC_REL32:
241   case R_PPC_REL16_LO:
242   case R_PPC_REL16_HI:
243   case R_PPC_REL16_HA:
244     return R_PC;
245   case R_PPC_GOT16:
246     return R_GOT_OFF;
247   case R_PPC_LOCAL24PC:
248   case R_PPC_REL24:
249     return R_PLT_PC;
250   case R_PPC_PLTREL24:
251     return RE_PPC32_PLTREL;
252   case R_PPC_GOT_TLSGD16:
253     return R_TLSGD_GOT;
254   case R_PPC_GOT_TLSLD16:
255     return R_TLSLD_GOT;
256   case R_PPC_GOT_TPREL16:
257     return R_GOT_OFF;
258   case R_PPC_TLS:
259     return R_TLSIE_HINT;
260   case R_PPC_TLSGD:
261     return R_TLSDESC_CALL;
262   case R_PPC_TLSLD:
263     return R_TLSLD_HINT;
264   case R_PPC_TPREL16:
265   case R_PPC_TPREL16_HA:
266   case R_PPC_TPREL16_LO:
267   case R_PPC_TPREL16_HI:
268     return R_TPREL;
269   default:
270     Err(ctx) << getErrorLoc(ctx, loc) << "unknown relocation (" << type.v
271              << ") against symbol " << &s;
272     return R_NONE;
273   }
274 }
275 
276 RelType PPC::getDynRel(RelType type) const {
277   if (type == R_PPC_ADDR32)
278     return type;
279   return R_PPC_NONE;
280 }
281 
282 int64_t PPC::getImplicitAddend(const uint8_t *buf, RelType type) const {
283   switch (type) {
284   case R_PPC_NONE:
285   case R_PPC_GLOB_DAT:
286   case R_PPC_JMP_SLOT:
287     return 0;
288   case R_PPC_ADDR32:
289   case R_PPC_REL32:
290   case R_PPC_RELATIVE:
291   case R_PPC_IRELATIVE:
292   case R_PPC_DTPMOD32:
293   case R_PPC_DTPREL32:
294   case R_PPC_TPREL32:
295     return SignExtend64<32>(read32(ctx, buf));
296   default:
297     InternalErr(ctx, buf) << "cannot read addend for relocation " << type;
298     return 0;
299   }
300 }
301 
302 static std::pair<RelType, uint64_t> fromDTPREL(RelType type, uint64_t val) {
303   uint64_t dtpBiasedVal = val - 0x8000;
304   switch (type) {
305   case R_PPC_DTPREL16:
306     return {R_PPC64_ADDR16, dtpBiasedVal};
307   case R_PPC_DTPREL16_HA:
308     return {R_PPC_ADDR16_HA, dtpBiasedVal};
309   case R_PPC_DTPREL16_HI:
310     return {R_PPC_ADDR16_HI, dtpBiasedVal};
311   case R_PPC_DTPREL16_LO:
312     return {R_PPC_ADDR16_LO, dtpBiasedVal};
313   case R_PPC_DTPREL32:
314     return {R_PPC_ADDR32, dtpBiasedVal};
315   default:
316     return {type, val};
317   }
318 }
319 
320 void PPC::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
321   RelType newType;
322   std::tie(newType, val) = fromDTPREL(rel.type, val);
323   switch (newType) {
324   case R_PPC_ADDR16:
325     checkIntUInt(ctx, loc, val, 16, rel);
326     write16(ctx, loc, val);
327     break;
328   case R_PPC_GOT16:
329   case R_PPC_GOT_TLSGD16:
330   case R_PPC_GOT_TLSLD16:
331   case R_PPC_GOT_TPREL16:
332   case R_PPC_TPREL16:
333     checkInt(ctx, loc, val, 16, rel);
334     write16(ctx, loc, val);
335     break;
336   case R_PPC_ADDR16_HA:
337   case R_PPC_DTPREL16_HA:
338   case R_PPC_GOT_TLSGD16_HA:
339   case R_PPC_GOT_TLSLD16_HA:
340   case R_PPC_GOT_TPREL16_HA:
341   case R_PPC_REL16_HA:
342   case R_PPC_TPREL16_HA:
343     write16(ctx, loc, ha(val));
344     break;
345   case R_PPC_ADDR16_HI:
346   case R_PPC_DTPREL16_HI:
347   case R_PPC_GOT_TLSGD16_HI:
348   case R_PPC_GOT_TLSLD16_HI:
349   case R_PPC_GOT_TPREL16_HI:
350   case R_PPC_REL16_HI:
351   case R_PPC_TPREL16_HI:
352     write16(ctx, loc, val >> 16);
353     break;
354   case R_PPC_ADDR16_LO:
355   case R_PPC_DTPREL16_LO:
356   case R_PPC_GOT_TLSGD16_LO:
357   case R_PPC_GOT_TLSLD16_LO:
358   case R_PPC_GOT_TPREL16_LO:
359   case R_PPC_REL16_LO:
360   case R_PPC_TPREL16_LO:
361     write16(ctx, loc, val);
362     break;
363   case R_PPC_ADDR32:
364   case R_PPC_REL32:
365     write32(ctx, loc, val);
366     break;
367   case R_PPC_REL14: {
368     uint32_t mask = 0x0000FFFC;
369     checkInt(ctx, loc, val, 16, rel);
370     checkAlignment(ctx, loc, val, 4, rel);
371     write32(ctx, loc, (read32(ctx, loc) & ~mask) | (val & mask));
372     break;
373   }
374   case R_PPC_ADDR24:
375   case R_PPC_REL24:
376   case R_PPC_LOCAL24PC:
377   case R_PPC_PLTREL24: {
378     uint32_t mask = 0x03FFFFFC;
379     checkInt(ctx, loc, val, 26, rel);
380     checkAlignment(ctx, loc, val, 4, rel);
381     write32(ctx, loc, (read32(ctx, loc) & ~mask) | (val & mask));
382     break;
383   }
384   default:
385     llvm_unreachable("unknown relocation");
386   }
387 }
388 
389 RelExpr PPC::adjustTlsExpr(RelType type, RelExpr expr) const {
390   if (expr == R_RELAX_TLS_GD_TO_IE)
391     return R_RELAX_TLS_GD_TO_IE_GOT_OFF;
392   if (expr == R_RELAX_TLS_LD_TO_LE)
393     return R_RELAX_TLS_LD_TO_LE_ABS;
394   return expr;
395 }
396 
397 int PPC::getTlsGdRelaxSkip(RelType type) const {
398   // A __tls_get_addr call instruction is marked with 2 relocations:
399   //
400   //   R_PPC_TLSGD / R_PPC_TLSLD: marker relocation
401   //   R_PPC_REL24: __tls_get_addr
402   //
403   // After the relaxation we no longer call __tls_get_addr and should skip both
404   // relocations to not create a false dependence on __tls_get_addr being
405   // defined.
406   if (type == R_PPC_TLSGD || type == R_PPC_TLSLD)
407     return 2;
408   return 1;
409 }
410 
411 void PPC::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
412                          uint64_t val) const {
413   switch (rel.type) {
414   case R_PPC_GOT_TLSGD16: {
415     // addi rT, rA, x@got@tlsgd --> lwz rT, x@got@tprel(rA)
416     uint32_t insn = readFromHalf16(ctx, loc);
417     writeFromHalf16(ctx, loc, 0x80000000 | (insn & 0x03ff0000));
418     relocateNoSym(loc, R_PPC_GOT_TPREL16, val);
419     break;
420   }
421   case R_PPC_TLSGD:
422     // bl __tls_get_addr(x@tldgd) --> add r3, r3, r2
423     write32(ctx, loc, 0x7c631214);
424     break;
425   default:
426     llvm_unreachable("unsupported relocation for TLS GD to IE relaxation");
427   }
428 }
429 
430 void PPC::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
431                          uint64_t val) const {
432   switch (rel.type) {
433   case R_PPC_GOT_TLSGD16:
434     // addi r3, r31, x@got@tlsgd --> addis r3, r2, x@tprel@ha
435     writeFromHalf16(ctx, loc, 0x3c620000 | ha(val));
436     break;
437   case R_PPC_TLSGD:
438     // bl __tls_get_addr(x@tldgd) --> add r3, r3, x@tprel@l
439     write32(ctx, loc, 0x38630000 | lo(val));
440     break;
441   default:
442     llvm_unreachable("unsupported relocation for TLS GD to LE relaxation");
443   }
444 }
445 
446 void PPC::relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
447                          uint64_t val) const {
448   switch (rel.type) {
449   case R_PPC_GOT_TLSLD16:
450     // addi r3, rA, x@got@tlsgd --> addis r3, r2, 0
451     writeFromHalf16(ctx, loc, 0x3c620000);
452     break;
453   case R_PPC_TLSLD:
454     // r3+x@dtprel computes r3+x-0x8000, while we want it to compute r3+x@tprel
455     // = r3+x-0x7000, so add 4096 to r3.
456     // bl __tls_get_addr(x@tlsld) --> addi r3, r3, 4096
457     write32(ctx, loc, 0x38631000);
458     break;
459   case R_PPC_DTPREL16:
460   case R_PPC_DTPREL16_HA:
461   case R_PPC_DTPREL16_HI:
462   case R_PPC_DTPREL16_LO:
463     relocate(loc, rel, val);
464     break;
465   default:
466     llvm_unreachable("unsupported relocation for TLS LD to LE relaxation");
467   }
468 }
469 
470 void PPC::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
471                          uint64_t val) const {
472   switch (rel.type) {
473   case R_PPC_GOT_TPREL16: {
474     // lwz rT, x@got@tprel(rA) --> addis rT, r2, x@tprel@ha
475     uint32_t rt = readFromHalf16(ctx, loc) & 0x03e00000;
476     writeFromHalf16(ctx, loc, 0x3c020000 | rt | ha(val));
477     break;
478   }
479   case R_PPC_TLS: {
480     uint32_t insn = read32(ctx, loc);
481     if (insn >> 26 != 31)
482       ErrAlways(ctx) << "unrecognized instruction for IE to LE R_PPC_TLS";
483     // addi rT, rT, x@tls --> addi rT, rT, x@tprel@l
484     unsigned secondaryOp = (read32(ctx, loc) & 0x000007fe) >> 1;
485     uint32_t dFormOp = getPPCDFormOp(secondaryOp);
486     if (dFormOp == 0) { // Expecting a DS-Form instruction.
487       dFormOp = getPPCDSFormOp(secondaryOp);
488       if (dFormOp == 0)
489         ErrAlways(ctx) << "unrecognized instruction for IE to LE R_PPC_TLS";
490     }
491     write32(ctx, loc, (dFormOp | (insn & 0x03ff0000) | lo(val)));
492     break;
493   }
494   default:
495     llvm_unreachable("unsupported relocation for TLS IE to LE relaxation");
496   }
497 }
498 
499 void PPC::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
500   uint64_t secAddr = sec.getOutputSection()->addr;
501   if (auto *s = dyn_cast<InputSection>(&sec))
502     secAddr += s->outSecOff;
503   for (const Relocation &rel : sec.relocs()) {
504     uint8_t *loc = buf + rel.offset;
505     const uint64_t val =
506         SignExtend64(sec.getRelocTargetVA(ctx, rel, secAddr + rel.offset), 32);
507     switch (rel.expr) {
508     case R_RELAX_TLS_GD_TO_IE_GOT_OFF:
509       relaxTlsGdToIe(loc, rel, val);
510       break;
511     case R_RELAX_TLS_GD_TO_LE:
512       relaxTlsGdToLe(loc, rel, val);
513       break;
514     case R_RELAX_TLS_LD_TO_LE_ABS:
515       relaxTlsLdToLe(loc, rel, val);
516       break;
517     case R_RELAX_TLS_IE_TO_LE:
518       relaxTlsIeToLe(loc, rel, val);
519       break;
520     default:
521       relocate(loc, rel, val);
522       break;
523     }
524   }
525 }
526 
527 void elf::setPPCTargetInfo(Ctx &ctx) { ctx.target.reset(new PPC(ctx)); }
528