//
// The LLVM Compiler Infrastructure
//
-// This file was developed by the "Instituto Nokia de Tecnologia" and
-// is distributed under the University of Illinois Open Source
+// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/Module.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DwarfWriter.h"
-#include "llvm/CodeGen/MachineDebugInfo.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/MathExtras.h"
#include <cctype>
-#include <iostream>
-#include <set>
using namespace llvm;
STATISTIC(EmittedInsts, "Number of machine instrs printed");
void printOperand(const MachineInstr *MI, int opNum,
const char *Modifier = 0);
void printSOImmOperand(const MachineInstr *MI, int opNum);
+ void printSOImm2PartOperand(const MachineInstr *MI, int opNum);
void printSORegOperand(const MachineInstr *MI, int opNum);
void printAddrMode2Operand(const MachineInstr *MI, int OpNo);
void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNo);
void printThumbAddrModeRROperand(const MachineInstr *MI, int OpNo);
void printThumbAddrModeRI5Operand(const MachineInstr *MI, int OpNo,
unsigned Scale);
- void printThumbAddrModeRI5_1Operand(const MachineInstr *MI, int OpNo);
- void printThumbAddrModeRI5_2Operand(const MachineInstr *MI, int OpNo);
- void printThumbAddrModeRI5_4Operand(const MachineInstr *MI, int OpNo);
+ void printThumbAddrModeS1Operand(const MachineInstr *MI, int OpNo);
+ void printThumbAddrModeS2Operand(const MachineInstr *MI, int OpNo);
+ void printThumbAddrModeS4Operand(const MachineInstr *MI, int OpNo);
void printThumbAddrModeSPOperand(const MachineInstr *MI, int OpNo);
- void printCCOperand(const MachineInstr *MI, int opNum);
+ void printPredicateOperand(const MachineInstr *MI, int opNum);
+ void printSBitModifierOperand(const MachineInstr *MI, int opNum);
void printPCLabel(const MachineInstr *MI, int opNum);
void printRegisterList(const MachineInstr *MI, int opNum);
void printCPInstOperand(const MachineInstr *MI, int opNum,
printDataDirective(MCPV->getType());
ARMConstantPoolValue *ACPV = (ARMConstantPoolValue*)MCPV;
- std::string Name = Mang->getValueName(ACPV->getGV());
+ GlobalValue *GV = ACPV->getGV();
+ std::string Name = GV ? Mang->getValueName(GV) : TAI->getGlobalPrefix();
+ if (!GV)
+ Name += ACPV->getSymbol();
if (ACPV->isNonLazyPointer()) {
GVNonLazyPtrs.insert(Name);
- O << TAI->getPrivateGlobalPrefix() << Name << "$non_lazy_ptr";
+ printSuffixedName(Name, "$non_lazy_ptr");
+ } else if (ACPV->isStub()) {
+ FnStubs.insert(Name);
+ printSuffixedName(Name, "$stub");
} else
O << Name;
- if (ACPV->getPCAdjustment() != 0)
+ if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";
+ if (ACPV->getPCAdjustment() != 0) {
O << "-(" << TAI->getPrivateGlobalPrefix() << "PC"
<< utostr(ACPV->getLabelId())
- << "+" << (unsigned)ACPV->getPCAdjustment() << ")";
+ << "+" << (unsigned)ACPV->getPCAdjustment();
+ if (ACPV->mustAddCurrentAddress())
+ O << "-.";
+ O << ")";
+ }
O << "\n";
+
+ // If the constant pool value is a extern weak symbol, remember to emit
+ // the weak reference.
+ if (GV && GV->hasExternalWeakLinkage())
+ ExtWeakSymbols.insert(GV);
}
void getAnalysisUsage(AnalysisUsage &AU) const {
+ AsmPrinter::getAnalysisUsage(AU);
AU.setPreservesAll();
- AU.addRequired<MachineDebugInfo>();
+ AU.addRequired<MachineModuleInfo>();
}
};
} // end of anonymous namespace
bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
AFI = MF.getInfo<ARMFunctionInfo>();
- if (Subtarget->isDarwin()) {
- DW.SetDebugInfo(&getAnalysis<MachineDebugInfo>());
- }
+ DW.SetModuleInfo(&getAnalysis<MachineModuleInfo>());
SetupMachineFunction(MF);
O << "\n";
break;
case Function::WeakLinkage:
case Function::LinkOnceLinkage:
- if (Subtarget->isDarwin()) {
+ if (Subtarget->isTargetDarwin()) {
SwitchToTextSection(
".section __TEXT,__textcoal_nt,coalesced,pure_instructions", F);
O << "\t.globl\t" << CurrentFnName << "\n";
break;
}
+ const char *VisibilityDirective = NULL;
+ if (F->hasHiddenVisibility())
+ VisibilityDirective = TAI->getHiddenDirective();
+ else if (F->hasProtectedVisibility())
+ VisibilityDirective = TAI->getProtectedDirective();
+
+ if (VisibilityDirective)
+ O << VisibilityDirective << CurrentFnName << "\n";
+
if (AFI->isThumbFunction()) {
- EmitAlignment(1, F);
+ EmitAlignment(1, F, AFI->getAlign());
O << "\t.code\t16\n";
- O << "\t.thumb_func\t" << CurrentFnName << "\n";
+ O << "\t.thumb_func";
+ if (Subtarget->isTargetDarwin())
+ O << "\t" << CurrentFnName;
+ O << "\n";
InCPMode = false;
} else
EmitAlignment(2, F);
O << CurrentFnName << ":\n";
- if (Subtarget->isDarwin()) {
- // Emit pre-function debug information.
- DW.BeginFunction(&MF);
+ // Emit pre-function debug information.
+ DW.BeginFunction(&MF);
+
+ if (Subtarget->isTargetDarwin()) {
+ // If the function is empty, then we need to emit *something*. Otherwise,
+ // the function's label might be associated with something that it wasn't
+ // meant to be associated with. We emit a noop in this situation.
+ MachineFunction::iterator I = MF.begin();
+
+ if (++I == MF.end() && MF.front().empty())
+ O << "\tnop\n";
}
// Print out code for the function.
I != E; ++I) {
// Print a label for the basic block.
if (I != MF.begin()) {
- printBasicBlockLabel(I, true);
+ printBasicBlockLabel(I, true, true);
O << '\n';
}
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
if (TAI->hasDotTypeDotSizeDirective())
O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n";
- if (Subtarget->isDarwin()) {
- // Emit post-function debug information.
- DW.EndFunction();
- }
+ // Emit post-function debug information.
+ DW.EndFunction();
return false;
}
const MachineOperand &MO = MI->getOperand(opNum);
switch (MO.getType()) {
case MachineOperand::MO_Register:
- if (MRegisterInfo::isPhysicalRegister(MO.getReg()))
- O << TM.getRegisterInfo()->get(MO.getReg()).Name;
+ if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
+ O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
else
assert(0 && "not implemented");
break;
if (!Modifier || strcmp(Modifier, "no_hash") != 0)
O << "#";
- O << (int)MO.getImmedValue();
+ O << (int)MO.getImm();
break;
}
case MachineOperand::MO_MachineBasicBlock:
- printBasicBlockLabel(MO.getMachineBasicBlock());
+ printBasicBlockLabel(MO.getMBB());
return;
case MachineOperand::MO_GlobalAddress: {
bool isCallOp = Modifier && !strcmp(Modifier, "call");
GlobalValue *GV = MO.getGlobal();
std::string Name = Mang->getValueName(GV);
- bool isExt = (GV->isExternal() || GV->hasWeakLinkage() ||
+ bool isExt = (GV->isDeclaration() || GV->hasWeakLinkage() ||
GV->hasLinkOnceLinkage());
- if (isExt && isCallOp && Subtarget->isDarwin() &&
+ if (isExt && isCallOp && Subtarget->isTargetDarwin() &&
TM.getRelocationModel() != Reloc::Static) {
- O << TAI->getPrivateGlobalPrefix() << Name << "$stub";
+ printSuffixedName(Name, "$stub");
FnStubs.insert(Name);
} else
O << Name;
-
+
+ if (MO.getOffset() > 0)
+ O << '+' << MO.getOffset();
+ else if (MO.getOffset() < 0)
+ O << MO.getOffset();
+
+ if (isCallOp && Subtarget->isTargetELF() &&
+ TM.getRelocationModel() == Reloc::PIC_)
+ O << "(PLT)";
if (GV->hasExternalWeakLinkage())
ExtWeakSymbols.insert(GV);
break;
bool isCallOp = Modifier && !strcmp(Modifier, "call");
std::string Name(TAI->getGlobalPrefix());
Name += MO.getSymbolName();
- if (isCallOp && Subtarget->isDarwin() &&
+ if (isCallOp && Subtarget->isTargetDarwin() &&
TM.getRelocationModel() != Reloc::Static) {
- O << TAI->getPrivateGlobalPrefix() << Name << "$stub";
+ printSuffixedName(Name, "$stub");
FnStubs.insert(Name);
} else
O << Name;
+ if (isCallOp && Subtarget->isTargetELF() &&
+ TM.getRelocationModel() == Reloc::PIC_)
+ O << "(PLT)";
break;
}
case MachineOperand::MO_ConstantPoolIndex:
O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
- << '_' << MO.getConstantPoolIndex();
+ << '_' << MO.getIndex();
break;
case MachineOperand::MO_JumpTableIndex:
O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
- << '_' << MO.getJumpTableIndex();
+ << '_' << MO.getIndex();
break;
default:
O << "<unknown operand type>"; abort (); break;
}
}
-/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
-/// immediate in bits 0-7.
-void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum) {
- const MachineOperand &MO = MI->getOperand(OpNum);
- assert(MO.isImmediate() && (MO.getImmedValue() < (1 << 12)) &&
- "Not a valid so_imm value!");
- unsigned Imm = ARM_AM::getSOImmValImm(MO.getImmedValue());
- unsigned Rot = ARM_AM::getSOImmValRot(MO.getImmedValue());
+static void printSOImm(std::ostream &O, int64_t V, const TargetAsmInfo *TAI) {
+ assert(V < (1 << 12) && "Not a valid so_imm value!");
+ unsigned Imm = ARM_AM::getSOImmValImm(V);
+ unsigned Rot = ARM_AM::getSOImmValRot(V);
// Print low-level immediate formation info, per
// A5.1.3: "Data-processing operands - Immediate".
}
}
+/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
+/// immediate in bits 0-7.
+void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum) {
+ const MachineOperand &MO = MI->getOperand(OpNum);
+ assert(MO.isImmediate() && "Not a valid so_imm value!");
+ printSOImm(O, MO.getImm(), TAI);
+}
+
+/// printSOImm2PartOperand - SOImm is broken into two pieces using a mov
+/// followed by a or to materialize.
+void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum) {
+ const MachineOperand &MO = MI->getOperand(OpNum);
+ assert(MO.isImmediate() && "Not a valid so_imm value!");
+ unsigned V1 = ARM_AM::getSOImmTwoPartFirst(MO.getImm());
+ unsigned V2 = ARM_AM::getSOImmTwoPartSecond(MO.getImm());
+ printSOImm(O, ARM_AM::getSOImmVal(V1), TAI);
+ O << "\n\torr";
+ printPredicateOperand(MI, 2);
+ O << " ";
+ printOperand(MI, 0);
+ O << ", ";
+ printOperand(MI, 0);
+ O << ", ";
+ printSOImm(O, ARM_AM::getSOImmVal(V2), TAI);
+}
+
// so_reg is a 4-operand unit corresponding to register forms of the A5.1
// "Addressing Mode 1 - Data-processing operands" forms. This includes:
// REG 0 0 - e.g. R5
const MachineOperand &MO2 = MI->getOperand(Op+1);
const MachineOperand &MO3 = MI->getOperand(Op+2);
- assert(MRegisterInfo::isPhysicalRegister(MO1.getReg()));
- O << TM.getRegisterInfo()->get(MO1.getReg()).Name;
+ assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
+ O << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
// Print the shift opc.
O << ", "
- << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImmedValue()))
+ << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()))
<< " ";
if (MO2.getReg()) {
- assert(MRegisterInfo::isPhysicalRegister(MO2.getReg()));
- O << TM.getRegisterInfo()->get(MO2.getReg()).Name;
+ assert(TargetRegisterInfo::isPhysicalRegister(MO2.getReg()));
+ O << TM.getRegisterInfo()->get(MO2.getReg()).AsmName;
assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
} else {
O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
return;
}
- O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
+ O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
if (!MO2.getReg()) {
if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
O << ", "
<< (char)ARM_AM::getAM2Op(MO3.getImm())
- << TM.getRegisterInfo()->get(MO2.getReg()).Name;
+ << TM.getRegisterInfo()->get(MO2.getReg()).AsmName;
if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
O << ", "
- << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImmedValue()))
+ << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
<< " #" << ShImm;
O << "]";
}
const MachineOperand &MO2 = MI->getOperand(Op+1);
if (!MO1.getReg()) {
- if (ARM_AM::getAM2Offset(MO2.getImm())) // Don't print +0.
- O << "#"
- << (char)ARM_AM::getAM2Op(MO2.getImm())
- << ARM_AM::getAM2Offset(MO2.getImm());
+ unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
+ assert(ImmOffs && "Malformed indexed load / store!");
+ O << "#"
+ << (char)ARM_AM::getAM2Op(MO2.getImm())
+ << ImmOffs;
return;
}
O << (char)ARM_AM::getAM2Op(MO2.getImm())
- << TM.getRegisterInfo()->get(MO1.getReg()).Name;
+ << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
O << ", "
- << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImmedValue()))
+ << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
<< " #" << ShImm;
}
const MachineOperand &MO2 = MI->getOperand(Op+1);
const MachineOperand &MO3 = MI->getOperand(Op+2);
- assert(MRegisterInfo::isPhysicalRegister(MO1.getReg()));
- O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
+ assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
+ O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
if (MO2.getReg()) {
O << ", "
<< (char)ARM_AM::getAM3Op(MO3.getImm())
- << TM.getRegisterInfo()->get(MO2.getReg()).Name
+ << TM.getRegisterInfo()->get(MO2.getReg()).AsmName
<< "]";
return;
}
if (MO1.getReg()) {
O << (char)ARM_AM::getAM3Op(MO2.getImm())
- << TM.getRegisterInfo()->get(MO1.getReg()).Name;
+ << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
return;
}
unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
+ assert(ImmOffs && "Malformed indexed load / store!");
O << "#"
- << (char)ARM_AM::getAM3Op(MO2.getImm())
+ << (char)ARM_AM::getAM3Op(MO2.getImm())
<< ImmOffs;
}
return;
}
- assert(MRegisterInfo::isPhysicalRegister(MO1.getReg()));
+ assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
if (Modifier && strcmp(Modifier, "submode") == 0) {
ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MO2.getImm());
return;
} else if (Modifier && strcmp(Modifier, "base") == 0) {
// Used for FSTM{D|S} and LSTM{D|S} operations.
- O << TM.getRegisterInfo()->get(MO1.getReg()).Name;
+ O << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
if (ARM_AM::getAM5WBFlag(MO2.getImm()))
O << "!";
return;
}
- O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
+ O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
O << ", #"
}
const MachineOperand &MO1 = MI->getOperand(Op);
- assert(MRegisterInfo::isPhysicalRegister(MO1.getReg()));
- O << "[pc, +" << TM.getRegisterInfo()->get(MO1.getReg()).Name << "]";
+ assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
+ O << "[pc, +" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName << "]";
}
void
ARMAsmPrinter::printThumbAddrModeRROperand(const MachineInstr *MI, int Op) {
const MachineOperand &MO1 = MI->getOperand(Op);
const MachineOperand &MO2 = MI->getOperand(Op+1);
- O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
- O << ", " << TM.getRegisterInfo()->get(MO2.getReg()).Name << "]";
+ O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
+ O << ", " << TM.getRegisterInfo()->get(MO2.getReg()).AsmName << "]";
}
void
unsigned Scale) {
const MachineOperand &MO1 = MI->getOperand(Op);
const MachineOperand &MO2 = MI->getOperand(Op+1);
+ const MachineOperand &MO3 = MI->getOperand(Op+2);
if (!MO1.isRegister()) { // FIXME: This is for CP entries, but isn't right.
printOperand(MI, Op);
return;
}
- O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
- if (unsigned ImmOffs = MO2.getImm()) {
+ O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
+ if (MO3.getReg())
+ O << ", " << TM.getRegisterInfo()->get(MO3.getReg()).AsmName;
+ else if (unsigned ImmOffs = MO2.getImm()) {
O << ", #" << ImmOffs;
if (Scale > 1)
O << " * " << Scale;
}
void
-ARMAsmPrinter::printThumbAddrModeRI5_1Operand(const MachineInstr *MI, int Op) {
+ARMAsmPrinter::printThumbAddrModeS1Operand(const MachineInstr *MI, int Op) {
printThumbAddrModeRI5Operand(MI, Op, 1);
}
void
-ARMAsmPrinter::printThumbAddrModeRI5_2Operand(const MachineInstr *MI, int Op) {
+ARMAsmPrinter::printThumbAddrModeS2Operand(const MachineInstr *MI, int Op) {
printThumbAddrModeRI5Operand(MI, Op, 2);
}
void
-ARMAsmPrinter::printThumbAddrModeRI5_4Operand(const MachineInstr *MI, int Op) {
+ARMAsmPrinter::printThumbAddrModeS4Operand(const MachineInstr *MI, int Op) {
printThumbAddrModeRI5Operand(MI, Op, 4);
}
void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op) {
const MachineOperand &MO1 = MI->getOperand(Op);
const MachineOperand &MO2 = MI->getOperand(Op+1);
- O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
+ O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
if (unsigned ImmOffs = MO2.getImm())
O << ", #" << ImmOffs << " * 4";
O << "]";
}
-void ARMAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
- int CC = (int)MI->getOperand(opNum).getImmedValue();
- O << ARMCondCodeToString((ARMCC::CondCodes)CC);
+void ARMAsmPrinter::printPredicateOperand(const MachineInstr *MI, int opNum) {
+ ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(opNum).getImm();
+ if (CC != ARMCC::AL)
+ O << ARMCondCodeToString(CC);
+}
+
+void ARMAsmPrinter::printSBitModifierOperand(const MachineInstr *MI, int opNum){
+ unsigned Reg = MI->getOperand(opNum).getReg();
+ if (Reg) {
+ assert(Reg == ARM::CPSR && "Expect ARM CPSR register!");
+ O << 's';
+ }
}
void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int opNum) {
- int Id = (int)MI->getOperand(opNum).getImmedValue();
+ int Id = (int)MI->getOperand(opNum).getImm();
O << TAI->getPrivateGlobalPrefix() << "PC" << Id;
}
<< '_' << ID << ":\n";
} else {
assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE");
- unsigned CPI = MI->getOperand(OpNo).getConstantPoolIndex();
+ unsigned CPI = MI->getOperand(OpNo).getIndex();
const MachineConstantPoolEntry &MCPE = // Chasing pointers is fun?
MI->getParent()->getParent()->getConstantPool()->getConstants()[CPI];
if (MCPE.isMachineConstantPoolEntry())
EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
- else
+ else {
EmitGlobalConstant(MCPE.Val.ConstVal);
+ // remember to emit the weak reference
+ if (const GlobalValue *GV = dyn_cast<GlobalValue>(MCPE.Val.ConstVal))
+ if (GV->hasExternalWeakLinkage())
+ ExtWeakSymbols.insert(GV);
+ }
}
}
void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNo) {
const MachineOperand &MO1 = MI->getOperand(OpNo);
const MachineOperand &MO2 = MI->getOperand(OpNo+1); // Unique Id
- unsigned JTI = MO1.getJumpTableIndex();
+ unsigned JTI = MO1.getIndex();
O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
- << '_' << JTI << '_' << MO2.getImmedValue() << ":\n";
+ << '_' << JTI << '_' << MO2.getImm() << ":\n";
const char *JTEntryDirective = TAI->getJumpTableDirective();
if (!JTEntryDirective)
for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
MachineBasicBlock *MBB = JTBBs[i];
if (UseSet && JTSets.insert(MBB).second)
- printSetLabel(JTI, MO2.getImmedValue(), MBB);
+ printPICJumpTableSetLabel(JTI, MO2.getImm(), MBB);
O << JTEntryDirective << ' ';
if (UseSet)
O << TAI->getPrivateGlobalPrefix() << getFunctionNumber()
- << '_' << JTI << '_' << MO2.getImmedValue()
+ << '_' << JTI << '_' << MO2.getImm()
<< "_set_" << MBB->getNumber();
else if (TM.getRelocationModel() == Reloc::PIC_) {
- printBasicBlockLabel(MBB, false, false);
+ printBasicBlockLabel(MBB, false, false, false);
// If the arch uses custom Jump Table directives, don't calc relative to JT
if (!TAI->getJumpTableDirective())
O << '-' << TAI->getPrivateGlobalPrefix() << "JTI"
- << getFunctionNumber() << '_' << JTI << '_' << MO2.getImmedValue();
+ << getFunctionNumber() << '_' << JTI << '_' << MO2.getImm();
} else
- printBasicBlockLabel(MBB, false, false);
- O << '\n';
+ printBasicBlockLabel(MBB, false, false, false);
+ if (i != e-1)
+ O << '\n';
}
}
switch (ExtraCode[0]) {
default: return true; // Unknown modifier.
+ case 'c': // Don't print "$" before a global var name or constant.
+ case 'P': // Print a VFP double precision register.
+ printOperand(MI, OpNo);
+ return false;
case 'Q':
if (TM.getTargetData()->isLittleEndian())
break;
void ARMAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
++EmittedInsts;
- if (MI->getOpcode() == ARM::CONSTPOOL_ENTRY) {
+ int Opc = MI->getOpcode();
+ switch (Opc) {
+ case ARM::CONSTPOOL_ENTRY:
if (!InCPMode && AFI->isThumbFunction()) {
EmitAlignment(2);
InCPMode = true;
}
- } else {
- if (InCPMode && AFI->isThumbFunction()) {
- EmitAlignment(1);
+ break;
+ default: {
+ if (InCPMode && AFI->isThumbFunction())
InCPMode = false;
+ switch (Opc) {
+ case ARM::PICADD:
+ case ARM::PICLD:
+ case ARM::PICLDZH:
+ case ARM::PICLDZB:
+ case ARM::PICLDH:
+ case ARM::PICLDB:
+ case ARM::PICLDSH:
+ case ARM::PICLDSB:
+ case ARM::PICSTR:
+ case ARM::PICSTRH:
+ case ARM::PICSTRB:
+ case ARM::tPICADD:
+ break;
+ default:
+ break;
}
- O << "\t";
- }
+ }}
// Call the autogenerated instruction printer routines.
printInstruction(MI);
}
bool ARMAsmPrinter::doInitialization(Module &M) {
- if (Subtarget->isDarwin()) {
- // Emit initial debug information.
- DW.BeginModule(&M);
- }
+ // Emit initial debug information.
+ DW.BeginModule(&M);
- return AsmPrinter::doInitialization(M);
+ bool Result = AsmPrinter::doInitialization(M);
+
+ // Darwin wants symbols to be quoted if they have complex names.
+ if (Subtarget->isTargetDarwin())
+ Mang->setUseQuotes(true);
+
+ return Result;
+}
+
+/// PrintUnmangledNameSafely - Print out the printable characters in the name.
+/// Don't print things like \n or \0.
+static void PrintUnmangledNameSafely(const Value *V, std::ostream &OS) {
+ for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen();
+ Name != E; ++Name)
+ if (isprint(*Name))
+ OS << *Name;
}
bool ARMAsmPrinter::doFinalization(Module &M) {
if (!I->hasInitializer()) // External global require no code
continue;
- if (EmitSpecialLLVMGlobal(I))
+ if (EmitSpecialLLVMGlobal(I)) {
+ if (Subtarget->isTargetDarwin() &&
+ TM.getRelocationModel() == Reloc::Static) {
+ if (I->getName() == "llvm.global_ctors")
+ O << ".reference .constructors_used\n";
+ else if (I->getName() == "llvm.global_dtors")
+ O << ".reference .destructors_used\n";
+ }
continue;
+ }
std::string name = Mang->getValueName(I);
Constant *C = I->getInitializer();
- unsigned Size = TD->getTypeSize(C->getType());
+ const Type *Type = C->getType();
+ unsigned Size = TD->getABITypeSize(Type);
unsigned Align = TD->getPreferredAlignmentLog(I);
- if (C->isNullValue() &&
- !I->hasSection() &&
- (I->hasInternalLinkage() || I->hasWeakLinkage() ||
- I->hasLinkOnceLinkage() ||
- (Subtarget->isDarwin() && I->hasExternalLinkage()))) {
- if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
+ const char *VisibilityDirective = NULL;
+ if (I->hasHiddenVisibility())
+ VisibilityDirective = TAI->getHiddenDirective();
+ else if (I->hasProtectedVisibility())
+ VisibilityDirective = TAI->getProtectedDirective();
+
+ if (VisibilityDirective)
+ O << VisibilityDirective << name << "\n";
+
+ if (Subtarget->isTargetELF())
+ O << "\t.type " << name << ",%object\n";
+
+ if (C->isNullValue() && !I->hasSection() && !I->isThreadLocal()) {
if (I->hasExternalLinkage()) {
+ if (const char *Directive = TAI->getZeroFillDirective()) {
O << "\t.globl\t" << name << "\n";
- O << "\t.zerofill __DATA__, __common, " << name << ", "
- << Size << ", " << Align;
- } else {
- SwitchToDataSection(TAI->getDataSection(), I);
+ O << Directive << "__DATA, __common, " << name << ", "
+ << Size << ", " << Align << "\n";
+ continue;
+ }
+ }
+
+ if (I->hasInternalLinkage() || I->hasWeakLinkage() ||
+ I->hasLinkOnceLinkage()) {
+ if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
+ if (!NoZerosInBSS && TAI->getBSSSection())
+ SwitchToDataSection(TAI->getBSSSection(), I);
+ else
+ SwitchToDataSection(TAI->getDataSection(), I);
if (TAI->getLCOMMDirective() != NULL) {
if (I->hasInternalLinkage()) {
O << TAI->getLCOMMDirective() << name << "," << Size;
- if (Subtarget->isDarwin())
+ if (Subtarget->isTargetDarwin())
O << "," << Align;
} else
O << TAI->getCOMMDirective() << name << "," << Size;
if (TAI->getCOMMDirectiveTakesAlignment())
O << "," << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
}
+ O << "\t\t" << TAI->getCommentString() << " ";
+ PrintUnmangledNameSafely(I, O);
+ O << "\n";
+ continue;
}
- O << "\t\t" << TAI->getCommentString() << " " << I->getName() << "\n";
- continue;
- } else {
- switch (I->getLinkage()) {
- default:
- assert(0 && "Unknown linkage type!");
- break;
- case GlobalValue::LinkOnceLinkage:
- case GlobalValue::WeakLinkage:
- if (Subtarget->isDarwin()) {
- O << "\t.globl " << name << "\n"
- << "\t.weak_definition " << name << "\n";
- SwitchToDataSection("\t.section __DATA,__const_coal,coalesced", I);
- } else {
- O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n"
- << "\t.weak " << name << "\n";
- }
- break;
- case GlobalValue::ExternalLinkage:
- O << "\t.globl " << name << "\n";
- // FALL THROUGH
- case GlobalValue::InternalLinkage:
- if (I->isConstant()) {
- const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
- if (TAI->getCStringSection() && CVA && CVA->isCString()) {
- SwitchToDataSection(TAI->getCStringSection(), I);
- break;
- }
- }
+ }
- if (I->hasSection() &&
- (I->getSection() == ".ctors" ||
- I->getSection() == ".dtors")) {
- assert(!Subtarget->isDarwin());
- std::string SectionName = ".section " + I->getSection();
- SectionName += ",\"aw\",@progbits";
- SwitchToDataSection(SectionName.c_str());
- } else {
- SwitchToDataSection(TAI->getDataSection(), I);
+ switch (I->getLinkage()) {
+ case GlobalValue::LinkOnceLinkage:
+ case GlobalValue::WeakLinkage:
+ if (Subtarget->isTargetDarwin()) {
+ O << "\t.globl " << name << "\n"
+ << "\t.weak_definition " << name << "\n";
+ SwitchToDataSection("\t.section __DATA,__datacoal_nt,coalesced", I);
+ } else {
+ std::string SectionName("\t.section\t.llvm.linkonce.d." +
+ name +
+ ",\"aw\",%progbits");
+ SwitchToDataSection(SectionName.c_str(), I);
+ O << "\t.weak " << name << "\n";
+ }
+ break;
+ case GlobalValue::AppendingLinkage:
+ // FIXME: appending linkage variables should go into a section of
+ // their name or something. For now, just emit them as external.
+ case GlobalValue::ExternalLinkage:
+ O << "\t.globl " << name << "\n";
+ // FALL THROUGH
+ case GlobalValue::InternalLinkage: {
+ if (I->isConstant()) {
+ const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
+ if (TAI->getCStringSection() && CVA && CVA->isCString()) {
+ SwitchToDataSection(TAI->getCStringSection(), I);
+ break;
+ }
+ }
+ // FIXME: special handling for ".ctors" & ".dtors" sections
+ if (I->hasSection() &&
+ (I->getSection() == ".ctors" ||
+ I->getSection() == ".dtors")) {
+ assert(!Subtarget->isTargetDarwin());
+ std::string SectionName = ".section " + I->getSection();
+ SectionName += ",\"aw\",%progbits";
+ SwitchToDataSection(SectionName.c_str());
+ } else if (I->hasSection() && Subtarget->isTargetDarwin()) {
+ // Honor all section names on Darwin; ObjC uses this
+ std::string SectionName = ".section " + I->getSection();
+ SwitchToDataSection(SectionName.c_str());
+ } else {
+ if (C->isNullValue() && !NoZerosInBSS && TAI->getBSSSection())
+ SwitchToDataSection(I->isThreadLocal() ? TAI->getTLSBSSSection() :
+ TAI->getBSSSection(), I);
+ else if (!I->isConstant())
+ SwitchToDataSection(I->isThreadLocal() ? TAI->getTLSDataSection() :
+ TAI->getDataSection(), I);
+ else if (I->isThreadLocal())
+ SwitchToDataSection(TAI->getTLSDataSection());
+ else {
+ // Read-only data.
+ bool HasReloc = C->ContainsRelocations();
+ if (HasReloc &&
+ Subtarget->isTargetDarwin() &&
+ TM.getRelocationModel() != Reloc::Static)
+ SwitchToDataSection("\t.const_data\n");
+ else if (!HasReloc && Size == 4 &&
+ TAI->getFourByteConstantSection())
+ SwitchToDataSection(TAI->getFourByteConstantSection(), I);
+ else if (!HasReloc && Size == 8 &&
+ TAI->getEightByteConstantSection())
+ SwitchToDataSection(TAI->getEightByteConstantSection(), I);
+ else if (!HasReloc && Size == 16 &&
+ TAI->getSixteenByteConstantSection())
+ SwitchToDataSection(TAI->getSixteenByteConstantSection(), I);
+ else if (TAI->getReadOnlySection())
+ SwitchToDataSection(TAI->getReadOnlySection(), I);
+ else
+ SwitchToDataSection(TAI->getDataSection(), I);
}
-
- break;
}
+
+ break;
+ }
+ default:
+ assert(0 && "Unknown linkage type!");
+ break;
}
EmitAlignment(Align, I);
- if (TAI->hasDotTypeDotSizeDirective()) {
- O << "\t.type " << name << ", %object\n";
+ O << name << ":\t\t\t\t" << TAI->getCommentString() << " ";
+ PrintUnmangledNameSafely(I, O);
+ O << "\n";
+ if (TAI->hasDotTypeDotSizeDirective())
O << "\t.size " << name << ", " << Size << "\n";
- }
- O << name << ":\n";
-
// If the initializer is a extern weak symbol, remember to emit the weak
// reference!
if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
O << '\n';
}
- if (Subtarget->isDarwin()) {
+ if (Subtarget->isTargetDarwin()) {
+ SwitchToDataSection("");
+
// Output stubs for dynamically-linked functions
unsigned j = 1;
for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end();
EmitAlignment(2);
O << "\t.code\t32\n";
- O << "L" << *i << "$stub:\n";
+ std::string p = *i;
+ printSuffixedName(p, "$stub");
+ O << ":\n";
O << "\t.indirect_symbol " << *i << "\n";
- O << "\tldr ip, L" << *i << "$slp\n";
+ O << "\tldr ip, ";
+ printSuffixedName(p, "$slp");
+ O << "\n";
if (TM.getRelocationModel() == Reloc::PIC_) {
- O << "L" << *i << "$scv:\n";
+ printSuffixedName(p, "$scv");
+ O << ":\n";
O << "\tadd ip, pc, ip\n";
}
O << "\tldr pc, [ip, #0]\n";
- O << "L" << *i << "$slp:\n";
- if (TM.getRelocationModel() == Reloc::PIC_)
- O << "\t.long\tL" << *i << "$lazy_ptr-(L" << *i << "$scv+8)\n";
- else
- O << "\t.long\tL" << *i << "$lazy_ptr\n";
+ printSuffixedName(p, "$slp");
+ O << ":\n";
+ O << "\t.long\t";
+ printSuffixedName(p, "$lazy_ptr");
+ if (TM.getRelocationModel() == Reloc::PIC_) {
+ O << "-(";
+ printSuffixedName(p, "$scv");
+ O << "+8)\n";
+ } else
+ O << "\n";
SwitchToDataSection(".lazy_symbol_pointer", 0);
- O << "L" << *i << "$lazy_ptr:\n";
+ printSuffixedName(p, "$lazy_ptr");
+ O << ":\n";
O << "\t.indirect_symbol " << *i << "\n";
O << "\t.long\tdyld_stub_binding_helper\n";
}
O << "\n";
// Output non-lazy-pointers for external and common global variables.
- if (GVNonLazyPtrs.begin() != GVNonLazyPtrs.end())
+ if (!GVNonLazyPtrs.empty())
SwitchToDataSection(".non_lazy_symbol_pointer", 0);
for (std::set<std::string>::iterator i = GVNonLazyPtrs.begin(),
e = GVNonLazyPtrs.end(); i != e; ++i) {
- O << "L" << *i << "$non_lazy_ptr:\n";
+ std::string p = *i;
+ printSuffixedName(p, "$non_lazy_ptr");
+ O << ":\n";
O << "\t.indirect_symbol " << *i << "\n";
O << "\t.long\t0\n";
}
// linker can safely perform dead code stripping. Since LLVM never
// generates code that does this, it is always safe to set.
O << "\t.subsections_via_symbols\n";
+ } else {
+ // Emit final debug information for ELF.
+ DW.EndModule();
}
- AsmPrinter::doFinalization(M);
- return false; // success
+ return AsmPrinter::doFinalization(M);
}