19 #define DEBUG_TYPE "asmprinter"
74 virtual const char *getPassName()
const {
75 return "PowerPC Assembly Printer";
84 bool PrintAsmOperand(
const MachineInstr *MI,
unsigned OpNo,
85 unsigned AsmVariant,
const char *ExtraCode,
87 bool PrintAsmMemoryOperand(
const MachineInstr *MI,
unsigned OpNo,
88 unsigned AsmVariant,
const char *ExtraCode,
93 class PPCLinuxAsmPrinter :
public PPCAsmPrinter {
96 : PPCAsmPrinter(TM, Streamer) {}
98 virtual const char *getPassName()
const {
99 return "Linux PPC Assembly Printer";
102 bool doFinalization(
Module &M);
104 virtual void EmitFunctionEntryLabel();
106 void EmitFunctionBodyEnd();
111 class PPCDarwinAsmPrinter :
public PPCAsmPrinter {
114 : PPCAsmPrinter(TM, Streamer) {}
116 virtual const char *getPassName()
const {
117 return "Darwin PPC Assembly Printer";
120 bool doFinalization(
Module &M);
121 void EmitStartOfAsmFile(
Module &M);
130 switch (RegName[0]) {
133 case 'v':
return RegName + 1;
134 case 'c':
if (RegName[1] ==
'r')
return RegName + 2;
140 void PPCAsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNo,
161 O << MAI->getPrivateGlobalPrefix() <<
"JTI" << getFunctionNumber()
166 O << MAI->getPrivateGlobalPrefix() <<
"CPI" << getFunctionNumber()
180 OutContext.GetOrCreateSymbol(
StringRef(MAI->getGlobalPrefix())+
186 StubValueTy(GetExternalSymbolSymbol(MO.
getSymbolName()),
true);
200 SymToPrint = GetSymbolWithGlobalValueBase(GV,
"$non_lazy_ptr");
203 .getGVStubEntry(SymToPrint);
209 SymToPrint = GetSymbolWithGlobalValueBase(GV,
"$non_lazy_ptr");
213 getHiddenGVStubEntry(SymToPrint);
218 SymToPrint = getSymbol(GV);
221 SymToPrint = getSymbol(GV);
231 O <<
"<unknown operand type: " << MO.
getType() <<
">";
238 bool PPCAsmPrinter::PrintAsmOperand(
const MachineInstr *MI,
unsigned OpNo,
242 if (ExtraCode && ExtraCode[0]) {
243 if (ExtraCode[1] != 0)
return true;
245 switch (ExtraCode[0]) {
268 printOperand(MI, OpNo, O);
276 bool PPCAsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *MI,
unsigned OpNo,
278 const char *ExtraCode,
280 if (ExtraCode && ExtraCode[0]) {
281 if (ExtraCode[1] != 0)
return true;
283 switch (ExtraCode[0]) {
284 default:
return true;
287 const char *RegName =
"r0";
289 O << RegName <<
", ";
290 printOperand(MI, OpNo, O);
298 printOperand(MI, OpNo, O);
312 while (TOCEntry == 0) {
313 if (OutContext.LookupSymbol(
Twine(MAI->getPrivateGlobalPrefix()) +
314 "C" +
Twine(TOCLabelID++)) == 0) {
315 TOCEntry = GetTempSymbol(
"C", TOCLabelID);
326 void PPCAsmPrinter::EmitInstruction(
const MachineInstr *MI) {
334 case PPC::MovePCtoLR:
335 case PPC::MovePCtoLR8: {
340 MCSymbol *PICBase = MF->getPICBaseSymbol();
349 OutStreamer.EmitLabel(PICBase);
369 MOSymbol = GetCPISymbol(MO.
getIndex());
371 MOSymbol = GetJTISymbol(MO.
getIndex());
373 MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol);
379 OutStreamer.EmitInstruction(TmpInst);
383 case PPC::ADDIStocHA: {
394 "Invalid operand for ADDIStocHA!");
396 bool IsExternal =
false;
397 bool IsFunction =
false;
398 bool IsCommon =
false;
399 bool IsAvailExt =
false;
406 MOSymbol = getSymbol(RealGValue);
412 }
else if (MO.
isCPI())
413 MOSymbol = GetCPISymbol(MO.
getIndex());
415 MOSymbol = GetJTISymbol(MO.
getIndex());
417 if (IsExternal || IsFunction || IsCommon || IsAvailExt || MO.
isJTI() ||
419 MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
425 OutStreamer.EmitInstruction(TmpInst);
438 "Invalid operand for LDtocL!");
442 MOSymbol = lookUpOrCreateTOCEntry(GetJTISymbol(MO.
getIndex()));
443 else if (MO.
isCPI()) {
444 MOSymbol = GetCPISymbol(MO.
getIndex());
446 MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
453 MOSymbol = getSymbol(RealGValue);
456 if (!GVar || !GVar->
hasInitializer() || RealGValue->hasCommonLinkage() ||
457 RealGValue->hasAvailableExternallyLinkage() ||
459 MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
466 OutStreamer.EmitInstruction(TmpInst);
469 case PPC::ADDItocL: {
478 assert((MO.
isGlobal() || MO.
isCPI()) &&
"Invalid operand for ADDItocL");
480 bool IsExternal =
false;
481 bool IsFunction =
false;
488 MOSymbol = getSymbol(RealGValue);
492 }
else if (MO.
isCPI())
493 MOSymbol = GetCPISymbol(MO.
getIndex());
496 MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
502 OutStreamer.EmitInstruction(TmpInst);
505 case PPC::ADDISgotTprelHA: {
508 assert(Subtarget.isPPC64() &&
"Not supported for 32-bit PowerPC");
511 MCSymbol *MOSymbol = getSymbol(GValue);
512 const MCExpr *SymGotTprel =
521 case PPC::LDgotTprelL: {
529 MCSymbol *MOSymbol = getSymbol(GValue);
534 OutStreamer.EmitInstruction(TmpInst);
537 case PPC::ADDIStlsgdHA: {
540 assert(Subtarget.isPPC64() &&
"Not supported for 32-bit PowerPC");
543 MCSymbol *MOSymbol = getSymbol(GValue);
544 const MCExpr *SymGotTlsGD =
553 case PPC::ADDItlsgdL: {
556 assert(Subtarget.isPPC64() &&
"Not supported for 32-bit PowerPC");
559 MCSymbol *MOSymbol = getSymbol(GValue);
560 const MCExpr *SymGotTlsGD =
566 .addExpr(SymGotTlsGD));
569 case PPC::GETtlsADDR: {
572 assert(Subtarget.isPPC64() &&
"Not supported for 32-bit PowerPC");
575 MCSymbol *TlsGetAddr = OutContext.GetOrCreateSymbol(Name);
580 MCSymbol *MOSymbol = getSymbol(GValue);
589 case PPC::ADDIStlsldHA: {
592 assert(Subtarget.isPPC64() &&
"Not supported for 32-bit PowerPC");
595 MCSymbol *MOSymbol = getSymbol(GValue);
596 const MCExpr *SymGotTlsLD =
605 case PPC::ADDItlsldL: {
608 assert(Subtarget.isPPC64() &&
"Not supported for 32-bit PowerPC");
611 MCSymbol *MOSymbol = getSymbol(GValue);
612 const MCExpr *SymGotTlsLD =
618 .addExpr(SymGotTlsLD));
621 case PPC::GETtlsldADDR: {
624 assert(Subtarget.isPPC64() &&
"Not supported for 32-bit PowerPC");
627 MCSymbol *TlsGetAddr = OutContext.GetOrCreateSymbol(Name);
632 MCSymbol *MOSymbol = getSymbol(GValue);
641 case PPC::ADDISdtprelHA: {
644 assert(Subtarget.isPPC64() &&
"Not supported for 32-bit PowerPC");
647 MCSymbol *MOSymbol = getSymbol(GValue);
657 case PPC::ADDIdtprelL: {
660 assert(Subtarget.isPPC64() &&
"Not supported for 32-bit PowerPC");
663 MCSymbol *MOSymbol = getSymbol(GValue);
670 .addExpr(SymDtprel));
675 if (!Subtarget.hasMFOCRF()) {
689 if (!Subtarget.hasMFOCRF()) {
693 MI->
getOpcode() == PPC::MTOCRF ? PPC::MTCRF : PPC::MTCRF8;
694 unsigned Mask = 0x80 >> OutContext.getRegisterInfo()
706 if (Subtarget.isBookE()) {
707 OutStreamer.EmitRawText(
StringRef(
"\tmsync"));
721 if (!Subtarget.isDarwin()) {
722 unsigned OpNum = (MI->
getOpcode() == PPC::STD) ? 2 : 1;
733 OutStreamer.EmitInstruction(TmpInst);
736 void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() {
737 if (!Subtarget.isPPC64())
743 ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC,
745 OutStreamer.SwitchSection(Section);
746 OutStreamer.EmitLabel(CurrentFnSym);
747 OutStreamer.EmitValueToAlignment(8);
749 OutContext.GetOrCreateSymbol(
".L." +
Twine(CurrentFnSym->getName()));
760 OutStreamer.EmitIntValue(0, 8 );
761 OutStreamer.SwitchSection(Current.first, Current.second);
763 MCSymbol *RealFnSym = OutContext.GetOrCreateSymbol(
764 ".L." +
Twine(CurrentFnSym->getName()));
765 OutStreamer.EmitLabel(RealFnSym);
766 CurrentFnSymForSize = RealFnSym;
770 bool PPCLinuxAsmPrinter::doFinalization(
Module &M) {
778 if (isPPC64 && !TOC.empty()) {
779 const MCSectionELF *Section = OutStreamer.getContext().getELFSection(
".toc",
780 ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC,
782 OutStreamer.SwitchSection(Section);
784 for (MapVector<MCSymbol*, MCSymbol*>::iterator
I = TOC.begin(),
785 E = TOC.end();
I != E; ++
I) {
786 OutStreamer.EmitLabel(
I->second);
787 MCSymbol *S = OutContext.GetOrCreateSymbol(
I->first->getName());
796 if (!Stubs.empty()) {
797 OutStreamer.SwitchSection(getObjFileLowering().getDataSection());
798 for (
unsigned i = 0, e = Stubs.size(); i != e; ++i) {
800 OutStreamer.EmitLabel(Stubs[i].first);
808 OutStreamer.AddBlankLine();
817 void PPCLinuxAsmPrinter::EmitFunctionBodyEnd() {
825 if (Subtarget.isPPC64()) {
826 OutStreamer.EmitIntValue(0, 4);
827 OutStreamer.EmitIntValue(0, 8);
831 void PPCDarwinAsmPrinter::EmitStartOfAsmFile(
Module &M) {
832 static const char *
const CPUDirectives[] = {
856 unsigned Directive = Subtarget.getDarwinDirective();
861 if (Subtarget.isPPC64() && Directive <
PPC::DIR_64)
863 assert(Directive <=
PPC::DIR_64 &&
"Directive out of range.");
866 if (OutStreamer.hasRawTextSupport()) {
868 "CPUDirectives[] might not be up-to-date!");
869 OutStreamer.EmitRawText(
"\t.machine " +
Twine(CPUDirectives[Directive]));
878 OutStreamer.SwitchSection(
879 OutContext.getMachOSection(
"__TEXT",
"__picsymbolstub1",
881 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
884 OutStreamer.SwitchSection(
885 OutContext.getMachOSection(
"__TEXT",
"__symbol_stub1",
887 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
890 OutStreamer.SwitchSection(getObjFileLowering().getTextSection());
904 void PPCDarwinAsmPrinter::
906 bool isPPC64 =
TM.getDataLayout()->getPointerSizeInBits() == 64;
907 bool isDarwin = Subtarget.isDarwin();
918 OutContext.getMachOSection(
"__TEXT",
"__picsymbolstub1",
920 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
922 for (
unsigned i = 0, e = Stubs.size(); i != e; ++i) {
923 OutStreamer.SwitchSection(StubSection);
927 MCSymbol *RawSym = Stubs[i].second.getPointer();
931 OutStreamer.EmitLabel(Stub);
940 OutStreamer.EmitInstruction(
MCInstBuilder(PPC::MFLR).addReg(PPC::R0));
942 OutStreamer.EmitInstruction(
MCInstBuilder(PPC::BCLalways).addExpr(Anon));
943 OutStreamer.EmitLabel(AnonSymbol);
945 OutStreamer.EmitInstruction(
MCInstBuilder(PPC::MFLR).addReg(PPC::R11));
953 OutStreamer.EmitInstruction(
MCInstBuilder(PPC::MTLR).addReg(PPC::R0));
958 OutStreamer.EmitInstruction(
MCInstBuilder(isPPC64 ? PPC::LDU : PPC::LWZU)
960 .addExpr(SubLo16).addExpr(SubLo16)
967 OutStreamer.SwitchSection(LSPSection);
968 OutStreamer.EmitLabel(LazyPtr);
972 OutContext.GetOrCreateSymbol(
StringRef(
"dyld_stub_binding_helper"));
975 OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 8);
978 OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 4);
981 OutStreamer.AddBlankLine();
986 OutContext.getMachOSection(
"__TEXT",
"__symbol_stub1",
988 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
990 for (
unsigned i = 0, e = Stubs.size(); i != e; ++i) {
992 MCSymbol *RawSym = Stubs[i].second.getPointer();
996 OutStreamer.SwitchSection(StubSection);
998 OutStreamer.EmitLabel(Stub);
1002 const MCExpr *LazyPtrHa16 =
1006 .addExpr(LazyPtrHa16));
1010 const MCExpr *LazyPtrLo16 =
1012 OutStreamer.EmitInstruction(
MCInstBuilder(isPPC64 ? PPC::LDU : PPC::LWZU)
1014 .addExpr(LazyPtrLo16).addExpr(LazyPtrLo16)
1022 OutStreamer.SwitchSection(LSPSection);
1023 OutStreamer.EmitLabel(LazyPtr);
1027 OutContext.GetOrCreateSymbol(
StringRef(
"dyld_stub_binding_helper"));
1030 OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 8);
1033 OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 4);
1037 OutStreamer.AddBlankLine();
1041 bool PPCDarwinAsmPrinter::doFinalization(
Module &M) {
1042 bool isPPC64 =
TM.getDataLayout()->getPointerSizeInBits() == 64;
1052 EmitFunctionStubs(Stubs);
1054 if (MAI->doesSupportExceptionHandling() && MMI) {
1057 const std::vector<const Function*> &Personalities = MMI->getPersonalities();
1058 for (std::vector<const Function*>::const_iterator
I = Personalities.begin(),
1059 E = Personalities.end();
I != E; ++
I) {
1061 MCSymbol *NLPSym = GetSymbolWithGlobalValueBase(*
I,
"$non_lazy_ptr");
1073 if (!Stubs.empty()) {
1076 EmitAlignment(isPPC64 ? 3 : 2);
1078 for (
unsigned i = 0, e = Stubs.size(); i != e; ++i) {
1080 OutStreamer.EmitLabel(Stubs[i].first);
1087 OutStreamer.EmitIntValue(0, isPPC64 ? 8 : 4);
1101 OutStreamer.AddBlankLine();
1105 if (!Stubs.empty()) {
1106 OutStreamer.SwitchSection(getObjFileLowering().getDataSection());
1107 EmitAlignment(isPPC64 ? 3 : 2);
1109 for (
unsigned i = 0, e = Stubs.size(); i != e; ++i) {
1111 OutStreamer.EmitLabel(Stubs[i].first);
1114 Create(Stubs[i].second.getPointer(),
1120 OutStreamer.AddBlankLine();
1142 return new PPCDarwinAsmPrinter(tm, Streamer);
1143 return new PPCLinuxAsmPrinter(tm, Streamer);
static const PPCMCExpr * CreateHa(const MCExpr *Expr, bool isDarwin, MCContext &Ctx)
PointerIntPair< MCSymbol *, 1, bool > StubValueTy
const GlobalValue * getGlobal() const
size_t size() const
size - Get the string size.
MachineBasicBlock * getMBB() const
The main container class for the LLVM Intermediate Representation.
unsigned getAlignment() const
enable_if_c<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
SymbolListTy GetFnStubList() const
Accessor methods to return the set of stubs in sorted order.
static MCOperand CreateExpr(const MCExpr *Val)
StringRef substr(size_t Start, size_t N=npos) const
static MCSymbol * GetAnonSym(MCSymbol *Sym, MCContext &Ctx)
const MCSection * getNonLazySymbolPointerSection() const
bool hasAvailableExternallyLinkage() const
bool isDarwin() const
isDarwin - True if this is any darwin platform.
const char * getSymbolName() const
std::vector< std::pair< MCSymbol *, StubValueTy > > SymbolListTy
SymbolListTy GetGVStubList() const
Address of indexed Jump Table for switch.
static const PPCMCExpr * CreateLo(const MCExpr *Expr, bool isDarwin, MCContext &Ctx)
bool isJTI() const
isJTI - Tests if this is a MO_JumpTableIndex operand.
MCSymbol * GetOrCreateSymbol(StringRef Name)
bool hasCommonLinkage() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
#define llvm_unreachable(msg)
static MCSymbol * GetLazyPtr(MCSymbol *Sym, MCContext &Ctx)
bool hasInternalLinkage() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
static const MCBinaryExpr * CreateSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
unsigned getNumOperands() const
bool isCPI() const
isCPI - Tests if this is a MO_ConstantPoolIndex operand.
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
size_t array_lengthof(T(&)[N])
Find the length of an array.
static AsmPrinter * createPPCAsmPrinterPass(TargetMachine &tm, MCStreamer &Streamer)
GlobalValue * resolveAliasedGlobal(bool stopOnWeak=true)
Address of indexed Constant in Constant Pool.
const MCSection * getTextCoalSection() const
MCInstBuilder & addExpr(const MCExpr *Val)
Add a new MCExpr operand.
SymbolListTy GetGVStubList() const
Accessor methods to return the set of stubs in sorted order.
static const MCSymbolRefExpr * Create(const MCSymbol *Symbol, MCContext &Ctx)
static bool isWeakForLinker(LinkageTypes Linkage)
void LLVMInitializePowerPCAsmPrinter()
bool hasHiddenVisibility() const
const MachineOperand & getOperand(unsigned i) const
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, const char *ExtraCode, raw_ostream &OS)
static const char * getRegisterName(unsigned RegNo)
.subsections_via_symbols (MachO)
int64_t getOffset() const
MCSymbol * getSymbol() const
StubValueTy & getGVStubEntry(MCSymbol *Sym)
PointerTy getPointer() const
void setOpcode(unsigned Op)
const STC & getSubtarget() const
std::pair< const MCSection *, const MCExpr * > MCSectionSubPair
bool hasInitializer() const
MachineOperandType getType() const
StringRef getName() const
getName - Get the symbol name.
bool isDeclaration() const
bool doFinalization(Module &M)
DBG_VALUE - a mapping of the llvm.dbg.value intrinsic.
unsigned getPointerSizeInBits(unsigned AS=0) const
virtual void EmitFunctionEntryLabel()
unsigned getReg() const
getReg - Returns the register number.
virtual void emitTCEntry(const MCSymbol &S)=0
Address of a basic block.
const MCSection * getLazySymbolPointerSection() const
void LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, AsmPrinter &AP, bool isDarwin)
static void RegisterAsmPrinter(Target &T, Target::AsmPrinterCtorTy Fn)
const BlockAddress * getBlockAddress() const
static SectionKind getReadOnly()
SymbolListTy GetHiddenGVStubList() const
INITIALIZE_PASS(GlobalMerge,"global-merge","Global Merge", false, false) bool GlobalMerge const DataLayout * TD
MachineBasicBlock reference.
const MCOperand & getOperand(unsigned i) const
static const char * stripRegisterPrefix(const char *RegName)
Address of a global value.
static SectionKind getText()
Name of external global symbol.