aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/ARM/ARMAsmPrinter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/ARM/ARMAsmPrinter.cpp')
-rw-r--r--lib/Target/ARM/ARMAsmPrinter.cpp858
1 files changed, 682 insertions, 176 deletions
diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp
index 653d5007ab..a6ceb85cb3 100644
--- a/lib/Target/ARM/ARMAsmPrinter.cpp
+++ b/lib/Target/ARM/ARMAsmPrinter.cpp
@@ -15,54 +15,49 @@
#define DEBUG_TYPE "asm-printer"
#include "ARM.h"
-#include "ARMInstrInfo.h"
+#include "ARMTargetMachine.h"
+#include "ARMAddressingModes.h"
+#include "ARMConstantPoolValue.h"
+#include "ARMMachineFunctionInfo.h"
#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/DwarfWriter.h"
+#include "llvm/CodeGen/MachineDebugInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineConstantPool.h"
-#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
-#include "llvm/Support/Mangler.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/CommandLine.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");
namespace {
- static const char *ARMCondCodeToString(ARMCC::CondCodes CC) {
- switch (CC) {
- default: assert(0 && "Unknown condition code");
- case ARMCC::EQ: return "eq";
- case ARMCC::NE: return "ne";
- case ARMCC::CS: return "cs";
- case ARMCC::CC: return "cc";
- case ARMCC::MI: return "mi";
- case ARMCC::PL: return "pl";
- case ARMCC::VS: return "vs";
- case ARMCC::VC: return "vc";
- case ARMCC::HI: return "hi";
- case ARMCC::LS: return "ls";
- case ARMCC::GE: return "ge";
- case ARMCC::LT: return "lt";
- case ARMCC::GT: return "gt";
- case ARMCC::LE: return "le";
- case ARMCC::AL: return "al";
- }
- }
-
struct VISIBILITY_HIDDEN ARMAsmPrinter : public AsmPrinter {
ARMAsmPrinter(std::ostream &O, TargetMachine &TM, const TargetAsmInfo *T)
- : AsmPrinter(O, TM, T) {
+ : AsmPrinter(O, TM, T), DW(O, this, T), AFI(NULL), InCPMode(false) {
+ Subtarget = &TM.getSubtarget<ARMSubtarget>();
}
+ DwarfWriter DW;
+
+ /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
+ /// make the right decision when printing asm code for different targets.
+ const ARMSubtarget *Subtarget;
+
+ /// AFI - Keep a pointer to ARMFunctionInfo for the current
+ /// MachineFunction
+ ARMFunctionInfo *AFI;
+
/// We name each basic block in a Function with a unique number, so
/// that we can consistently refer to them later. This is cleared
/// at the beginning of each call to runOnMachineFunction().
@@ -70,22 +65,79 @@ namespace {
typedef std::map<const Value *, unsigned> ValueMapTy;
ValueMapTy NumberForBB;
+ /// Keeps the set of GlobalValues that require non-lazy-pointers for
+ /// indirect access.
+ std::set<std::string> GVNonLazyPtrs;
+
+ /// Keeps the set of external function GlobalAddresses that the asm
+ /// printer should generate stubs for.
+ std::set<std::string> FnStubs;
+
+ /// True if asm printer is printing a series of CONSTPOOL_ENTRY.
+ bool InCPMode;
+
virtual const char *getPassName() const {
return "ARM Assembly Printer";
}
- void printAddrMode1(const MachineInstr *MI, int opNum);
- void printAddrMode2(const MachineInstr *MI, int opNum);
- void printAddrMode5(const MachineInstr *MI, int opNum);
- void printOperand(const MachineInstr *MI, int opNum);
- void printMemOperand(const MachineInstr *MI, int opNum,
- const char *Modifier = 0);
+ void printOperand(const MachineInstr *MI, int opNum,
+ const char *Modifier = 0);
+ void printSOImmOperand(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 printAddrMode3Operand(const MachineInstr *MI, int OpNo);
+ void printAddrMode3OffsetOperand(const MachineInstr *MI, int OpNo);
+ void printAddrMode4Operand(const MachineInstr *MI, int OpNo,
+ const char *Modifier = 0);
+ void printAddrMode5Operand(const MachineInstr *MI, int OpNo,
+ const char *Modifier = 0);
+ void printAddrModePCOperand(const MachineInstr *MI, int OpNo,
+ const char *Modifier = 0);
+ 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 printThumbAddrModeSPOperand(const MachineInstr *MI, int OpNo);
void printCCOperand(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,
+ const char *Modifier);
+ void printJTBlockOperand(const MachineInstr *MI, int opNum);
+
+ virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+ unsigned AsmVariant, const char *ExtraCode);
bool printInstruction(const MachineInstr *MI); // autogenerated.
+ void printMachineInstruction(const MachineInstr *MI);
bool runOnMachineFunction(MachineFunction &F);
bool doInitialization(Module &M);
bool doFinalization(Module &M);
+
+ virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
+ printDataDirective(MCPV->getType());
+
+ ARMConstantPoolValue *ACPV = (ARMConstantPoolValue*)MCPV;
+ std::string Name = Mang->getValueName(ACPV->getGV());
+ if (ACPV->isNonLazyPointer()) {
+ GVNonLazyPtrs.insert(Name);
+ O << TAI->getPrivateGlobalPrefix() << Name << "$non_lazy_ptr";
+ } else
+ O << Name;
+ if (ACPV->getPCAdjustment() != 0)
+ O << "-(" << TAI->getPrivateGlobalPrefix() << "PC"
+ << utostr(ACPV->getLabelId())
+ << "+" << (unsigned)ACPV->getPCAdjustment() << ")";
+ O << "\n";
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ AU.addRequired<MachineDebugInfo>();
+ }
};
} // end of anonymous namespace
@@ -97,55 +149,64 @@ namespace {
/// regardless of whether the function is in SSA form.
///
FunctionPass *llvm::createARMCodePrinterPass(std::ostream &o,
- TargetMachine &tm) {
+ ARMTargetMachine &tm) {
return new ARMAsmPrinter(o, tm, tm.getTargetAsmInfo());
}
-/// runOnMachineFunction - This uses the printMachineInstruction()
+/// runOnMachineFunction - This uses the printInstruction()
/// method to print assembly for each instruction.
///
bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
- SetupMachineFunction(MF);
- O << "\n\n";
-
- // Print out constants referenced by the function
- EmitConstantPool(MF.getConstantPool());
-
- const std::vector<MachineConstantPoolEntry>
- &CP = MF.getConstantPool()->getConstants();
- for (unsigned i = 0, e = CP.size(); i != e; ++i) {
- MachineConstantPoolEntry CPE = CP[i];
- if (!CPE.isMachineConstantPoolEntry()){
- Constant *CV = CPE.Val.ConstVal;
- if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
- if (GV->hasExternalWeakLinkage()) {
- ExtWeakSymbols.insert(GV);
- }
- }
- }
+ AFI = MF.getInfo<ARMFunctionInfo>();
+
+ if (Subtarget->isDarwin()) {
+ DW.SetDebugInfo(&getAnalysis<MachineDebugInfo>());
}
- // Print out jump tables referenced by the function
- EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
+ SetupMachineFunction(MF);
+ O << "\n";
+
+ // NOTE: we don't print out constant pools here, they are handled as
+ // instructions.
+ O << "\n";
// Print out labels for the function.
const Function *F = MF.getFunction();
- SwitchToTextSection(getSectionForFunction(*F).c_str(), F);
-
switch (F->getLinkage()) {
default: assert(0 && "Unknown linkage type!");
case Function::InternalLinkage:
+ SwitchToTextSection("\t.text", F);
break;
case Function::ExternalLinkage:
+ SwitchToTextSection("\t.text", F);
O << "\t.globl\t" << CurrentFnName << "\n";
break;
case Function::WeakLinkage:
case Function::LinkOnceLinkage:
- O << TAI->getWeakRefDirective() << CurrentFnName << "\n";
+ if (Subtarget->isDarwin()) {
+ SwitchToTextSection(
+ ".section __TEXT,__textcoal_nt,coalesced,pure_instructions", F);
+ O << "\t.globl\t" << CurrentFnName << "\n";
+ O << "\t.weak_definition\t" << CurrentFnName << "\n";
+ } else {
+ O << TAI->getWeakRefDirective() << CurrentFnName << "\n";
+ }
break;
}
- EmitAlignment(2, F);
+
+ if (AFI->isThumbFunction()) {
+ EmitAlignment(1, F);
+ O << "\t.code\t16\n";
+ O << "\t.thumb_func\t" << CurrentFnName << "\n";
+ InCPMode = false;
+ } else
+ EmitAlignment(2, F);
+
O << CurrentFnName << ":\n";
+ if (Subtarget->isDarwin()) {
+ // Emit pre-function debug information.
+ DW.BeginFunction(&MF);
+ }
// Print out code for the function.
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
@@ -158,127 +219,340 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
II != E; ++II) {
// Print the assembly for the instruction.
- O << "\t";
- ++EmittedInsts;
- printInstruction(II);
- }
- }
-
- return false;
-}
-
-void ARMAsmPrinter::printAddrMode1(const MachineInstr *MI, int opNum) {
- const MachineOperand &Arg = MI->getOperand(opNum);
- const MachineOperand &Shift = MI->getOperand(opNum + 1);
- const MachineOperand &ShiftType = MI->getOperand(opNum + 2);
-
- if(Arg.isImmediate()) {
- assert(Shift.getImmedValue() == 0);
- printOperand(MI, opNum);
- } else {
- assert(Arg.isRegister());
- printOperand(MI, opNum);
- if(Shift.isRegister() || Shift.getImmedValue() != 0) {
- const char *s = NULL;
- switch(ShiftType.getImmedValue()) {
- case ARMShift::LSL:
- s = ", lsl ";
- break;
- case ARMShift::LSR:
- s = ", lsr ";
- break;
- case ARMShift::ASR:
- s = ", asr ";
- break;
- case ARMShift::ROR:
- s = ", ror ";
- break;
- case ARMShift::RRX:
- s = ", rrx ";
- break;
- }
- O << s;
- printOperand(MI, opNum + 1);
+ printMachineInstruction(II);
}
}
-}
-void ARMAsmPrinter::printAddrMode2(const MachineInstr *MI, int opNum) {
- const MachineOperand &Arg = MI->getOperand(opNum);
- const MachineOperand &Offset = MI->getOperand(opNum + 1);
- assert(Offset.isImmediate());
+ if (TAI->hasDotTypeDotSizeDirective())
+ O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n";
- if (Arg.isConstantPoolIndex()) {
- assert(Offset.getImmedValue() == 0);
- printOperand(MI, opNum);
- } else {
- assert(Arg.isRegister());
- O << '[';
- printOperand(MI, opNum);
- O << ", ";
- printOperand(MI, opNum + 1);
- O << ']';
+ if (Subtarget->isDarwin()) {
+ // Emit post-function debug information.
+ DW.EndFunction();
}
-}
-
-void ARMAsmPrinter::printAddrMode5(const MachineInstr *MI, int opNum) {
- const MachineOperand &Arg = MI->getOperand(opNum);
- const MachineOperand &Offset = MI->getOperand(opNum + 1);
- assert(Offset.isImmediate());
- if (Arg.isConstantPoolIndex()) {
- assert(Offset.getImmedValue() == 0);
- printOperand(MI, opNum);
- } else {
- assert(Arg.isRegister());
- O << '[';
- printOperand(MI, opNum);
- O << ", ";
- printOperand(MI, opNum + 1);
- O << ']';
- }
+ return false;
}
-void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
- const MachineOperand &MO = MI->getOperand (opNum);
- const MRegisterInfo &RI = *TM.getRegisterInfo();
+void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
+ const char *Modifier) {
+ const MachineOperand &MO = MI->getOperand(opNum);
switch (MO.getType()) {
case MachineOperand::MO_Register:
if (MRegisterInfo::isPhysicalRegister(MO.getReg()))
- O << LowercaseString (RI.get(MO.getReg()).Name);
+ O << TM.getRegisterInfo()->get(MO.getReg()).Name;
else
assert(0 && "not implemented");
break;
- case MachineOperand::MO_Immediate:
- O << "#" << (int)MO.getImmedValue();
+ case MachineOperand::MO_Immediate: {
+ if (!Modifier || strcmp(Modifier, "no_hash") != 0)
+ O << "#";
+
+ O << (int)MO.getImmedValue();
break;
+ }
case MachineOperand::MO_MachineBasicBlock:
printBasicBlockLabel(MO.getMachineBasicBlock());
return;
case MachineOperand::MO_GlobalAddress: {
+ bool isCallOp = Modifier && !strcmp(Modifier, "call");
GlobalValue *GV = MO.getGlobal();
std::string Name = Mang->getValueName(GV);
- O << Name;
- if (GV->hasExternalWeakLinkage()) {
+ bool isExt = (GV->isExternal() || GV->hasWeakLinkage() ||
+ GV->hasLinkOnceLinkage());
+ if (isExt && isCallOp && Subtarget->isDarwin() &&
+ TM.getRelocationModel() != Reloc::Static) {
+ O << TAI->getPrivateGlobalPrefix() << Name << "$stub";
+ FnStubs.insert(Name);
+ } else
+ O << Name;
+
+ if (GV->hasExternalWeakLinkage())
ExtWeakSymbols.insert(GV);
- }
- }
break;
- case MachineOperand::MO_ExternalSymbol:
- O << TAI->getGlobalPrefix() << MO.getSymbolName();
+ }
+ case MachineOperand::MO_ExternalSymbol: {
+ bool isCallOp = Modifier && !strcmp(Modifier, "call");
+ std::string Name(TAI->getGlobalPrefix());
+ Name += MO.getSymbolName();
+ if (isCallOp && Subtarget->isDarwin() &&
+ TM.getRelocationModel() != Reloc::Static) {
+ O << TAI->getPrivateGlobalPrefix() << Name << "$stub";
+ FnStubs.insert(Name);
+ } else
+ O << Name;
break;
+ }
case MachineOperand::MO_ConstantPoolIndex:
O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
<< '_' << MO.getConstantPoolIndex();
break;
+ case MachineOperand::MO_JumpTableIndex:
+ O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
+ << '_' << MO.getJumpTableIndex();
+ break;
default:
O << "<unknown operand type>"; abort (); break;
}
}
-void ARMAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
- const char *Modifier) {
- assert(0 && "not implemented");
+/// 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());
+
+ // Print low-level immediate formation info, per
+ // A5.1.3: "Data-processing operands - Immediate".
+ if (Rot) {
+ O << "#" << Imm << ", " << Rot;
+ // Pretty printed version.
+ O << ' ' << TAI->getCommentString() << ' ' << (int)ARM_AM::rotr32(Imm, Rot);
+ } else {
+ O << "#" << Imm;
+ }
+}
+
+// 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
+// REG REG 0,SH_OPC - e.g. R5, ROR R3
+// REG 0 IMM,SH_OPC - e.g. R5, LSL #3
+void ARMAsmPrinter::printSORegOperand(const MachineInstr *MI, int Op) {
+ const MachineOperand &MO1 = MI->getOperand(Op);
+ 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;
+
+ // Print the shift opc.
+ O << ", "
+ << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImmedValue()))
+ << " ";
+
+ if (MO2.getReg()) {
+ assert(MRegisterInfo::isPhysicalRegister(MO2.getReg()));
+ O << TM.getRegisterInfo()->get(MO2.getReg()).Name;
+ assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
+ } else {
+ O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
+ }
+}
+
+void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op) {
+ 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 (!MO2.getReg()) {
+ if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
+ O << ", #"
+ << (char)ARM_AM::getAM2Op(MO3.getImm())
+ << ARM_AM::getAM2Offset(MO3.getImm());
+ O << "]";
+ return;
+ }
+
+ O << ", "
+ << (char)ARM_AM::getAM2Op(MO3.getImm())
+ << TM.getRegisterInfo()->get(MO2.getReg()).Name;
+
+ if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
+ O << ", "
+ << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImmedValue()))
+ << " #" << ShImm;
+ O << "]";
+}
+
+void ARMAsmPrinter::printAddrMode2OffsetOperand(const MachineInstr *MI, int Op){
+ const MachineOperand &MO1 = MI->getOperand(Op);
+ 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());
+ return;
+ }
+
+ O << (char)ARM_AM::getAM2Op(MO2.getImm())
+ << TM.getRegisterInfo()->get(MO1.getReg()).Name;
+
+ if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
+ O << ", "
+ << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImmedValue()))
+ << " #" << ShImm;
+}
+
+void ARMAsmPrinter::printAddrMode3Operand(const MachineInstr *MI, int Op) {
+ const MachineOperand &MO1 = MI->getOperand(Op);
+ 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;
+
+ if (MO2.getReg()) {
+ O << ", "
+ << (char)ARM_AM::getAM3Op(MO3.getImm())
+ << TM.getRegisterInfo()->get(MO2.getReg()).Name
+ << "]";
+ return;
+ }
+
+ if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
+ O << ", #"
+ << (char)ARM_AM::getAM3Op(MO3.getImm())
+ << ImmOffs;
+ O << "]";
+}
+
+void ARMAsmPrinter::printAddrMode3OffsetOperand(const MachineInstr *MI, int Op){
+ const MachineOperand &MO1 = MI->getOperand(Op);
+ const MachineOperand &MO2 = MI->getOperand(Op+1);
+
+ if (MO1.getReg()) {
+ O << (char)ARM_AM::getAM3Op(MO2.getImm())
+ << TM.getRegisterInfo()->get(MO1.getReg()).Name;
+ return;
+ }
+
+ unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
+ O << "#"
+ << (char)ARM_AM::getAM3Op(MO2.getImm())
+ << ImmOffs;
+}
+
+void ARMAsmPrinter::printAddrMode4Operand(const MachineInstr *MI, int Op,
+ const char *Modifier) {
+ const MachineOperand &MO1 = MI->getOperand(Op);
+ const MachineOperand &MO2 = MI->getOperand(Op+1);
+ ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
+ if (Modifier && strcmp(Modifier, "submode") == 0) {
+ if (MO1.getReg() == ARM::SP) {
+ bool isLDM = (MI->getOpcode() == ARM::LDM ||
+ MI->getOpcode() == ARM::LDM_RET);
+ O << ARM_AM::getAMSubModeAltStr(Mode, isLDM);
+ } else
+ O << ARM_AM::getAMSubModeStr(Mode);
+ } else {
+ printOperand(MI, Op);
+ if (ARM_AM::getAM4WBFlag(MO2.getImm()))
+ O << "!";
+ }
+}
+
+void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op,
+ const char *Modifier) {
+ const MachineOperand &MO1 = MI->getOperand(Op);
+ const MachineOperand &MO2 = MI->getOperand(Op+1);
+
+ if (!MO1.isRegister()) { // FIXME: This is for CP entries, but isn't right.
+ printOperand(MI, Op);
+ return;
+ }
+
+ assert(MRegisterInfo::isPhysicalRegister(MO1.getReg()));
+
+ if (Modifier && strcmp(Modifier, "submode") == 0) {
+ ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MO2.getImm());
+ if (MO1.getReg() == ARM::SP) {
+ bool isFLDM = (MI->getOpcode() == ARM::FLDMD ||
+ MI->getOpcode() == ARM::FLDMS);
+ O << ARM_AM::getAMSubModeAltStr(Mode, isFLDM);
+ } else
+ O << ARM_AM::getAMSubModeStr(Mode);
+ 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;
+ if (ARM_AM::getAM5WBFlag(MO2.getImm()))
+ O << "!";
+ return;
+ }
+
+ O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
+
+ if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
+ O << ", #"
+ << (char)ARM_AM::getAM5Op(MO2.getImm())
+ << ImmOffs*4;
+ }
+ O << "]";
+}
+
+void ARMAsmPrinter::printAddrModePCOperand(const MachineInstr *MI, int Op,
+ const char *Modifier) {
+ if (Modifier && strcmp(Modifier, "label") == 0) {
+ printPCLabel(MI, Op+1);
+ return;
+ }
+
+ const MachineOperand &MO1 = MI->getOperand(Op);
+ assert(MRegisterInfo::isPhysicalRegister(MO1.getReg()));
+ O << "[pc, +" << TM.getRegisterInfo()->get(MO1.getReg()).Name << "]";
+}
+
+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 << "]";
+}
+
+void
+ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr *MI, int Op,
+ unsigned Scale) {
+ const MachineOperand &MO1 = MI->getOperand(Op);
+ const MachineOperand &MO2 = MI->getOperand(Op+1);
+
+ 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 << ", #" << ImmOffs;
+ if (Scale > 1)
+ O << " * " << Scale;
+ }
+ O << "]";
+}
+
+void
+ARMAsmPrinter::printThumbAddrModeRI5_1Operand(const MachineInstr *MI, int Op) {
+ printThumbAddrModeRI5Operand(MI, Op, 1);
+}
+void
+ARMAsmPrinter::printThumbAddrModeRI5_2Operand(const MachineInstr *MI, int Op) {
+ printThumbAddrModeRI5Operand(MI, Op, 2);
+}
+void
+ARMAsmPrinter::printThumbAddrModeRI5_4Operand(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;
+ if (unsigned ImmOffs = MO2.getImm())
+ O << ", #" << ImmOffs << " * 4";
+ O << "]";
}
void ARMAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
@@ -286,9 +560,140 @@ void ARMAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
O << ARMCondCodeToString((ARMCC::CondCodes)CC);
}
+void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int opNum) {
+ int Id = (int)MI->getOperand(opNum).getImmedValue();
+ O << TAI->getPrivateGlobalPrefix() << "PC" << Id;
+}
+
+void ARMAsmPrinter::printRegisterList(const MachineInstr *MI, int opNum) {
+ O << "{";
+ for (unsigned i = opNum, e = MI->getNumOperands(); i != e; ++i) {
+ printOperand(MI, i);
+ if (i != e-1) O << ", ";
+ }
+ O << "}";
+}
+
+void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNo,
+ const char *Modifier) {
+ assert(Modifier && "This operand only works with a modifier!");
+ // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the
+ // data itself.
+ if (!strcmp(Modifier, "label")) {
+ unsigned ID = MI->getOperand(OpNo).getImm();
+ O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
+ << '_' << ID << ":\n";
+ } else {
+ assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE");
+ unsigned CPI = MI->getOperand(OpNo).getConstantPoolIndex();
+
+ const MachineConstantPoolEntry &MCPE = // Chasing pointers is fun?
+ MI->getParent()->getParent()->getConstantPool()->getConstants()[CPI];
+
+ if (MCPE.isMachineConstantPoolEntry())
+ EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
+ else
+ EmitGlobalConstant(MCPE.Val.ConstVal);
+ }
+}
+
+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();
+ O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
+ << '_' << JTI << '_' << MO2.getImmedValue() << ":\n";
+
+ const char *JTEntryDirective = TAI->getJumpTableDirective();
+ if (!JTEntryDirective)
+ JTEntryDirective = TAI->getData32bitsDirective();
+
+ const MachineFunction *MF = MI->getParent()->getParent();
+ MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
+ const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
+ const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
+ bool UseSet= TAI->getSetDirective() && TM.getRelocationModel() == Reloc::PIC_;
+ std::set<MachineBasicBlock*> JTSets;
+ 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);
+
+ O << JTEntryDirective << ' ';
+ if (UseSet)
+ O << TAI->getPrivateGlobalPrefix() << getFunctionNumber()
+ << '_' << JTI << '_' << MO2.getImmedValue()
+ << "_set_" << MBB->getNumber();
+ else if (TM.getRelocationModel() == Reloc::PIC_) {
+ printBasicBlockLabel(MBB, 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();
+ } else
+ printBasicBlockLabel(MBB, false, false);
+ O << '\n';
+ }
+}
+
+
+bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+ unsigned AsmVariant, const char *ExtraCode){
+ // Does this asm operand have a single letter operand modifier?
+ if (ExtraCode && ExtraCode[0]) {
+ if (ExtraCode[1] != 0) return true; // Unknown modifier.
+
+ switch (ExtraCode[0]) {
+ default: return true; // Unknown modifier.
+ case 'Q':
+ if (TM.getTargetData()->isLittleEndian())
+ break;
+ // Fallthrough
+ case 'R':
+ if (TM.getTargetData()->isBigEndian())
+ break;
+ // Fallthrough
+ case 'H': // Write second word of DI / DF reference.
+ // Verify that this operand has two consecutive registers.
+ if (!MI->getOperand(OpNo).isRegister() ||
+ OpNo+1 == MI->getNumOperands() ||
+ !MI->getOperand(OpNo+1).isRegister())
+ return true;
+ ++OpNo; // Return the high-part.
+ }
+ }
+
+ printOperand(MI, OpNo);
+ return false;
+}
+
+void ARMAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
+ ++EmittedInsts;
+
+ if (MI->getOpcode() == ARM::CONSTPOOL_ENTRY) {
+ if (!InCPMode && AFI->isThumbFunction()) {
+ EmitAlignment(2);
+ InCPMode = true;
+ }
+ } else {
+ if (InCPMode && AFI->isThumbFunction()) {
+ EmitAlignment(1);
+ InCPMode = false;
+ }
+ O << "\t";
+ }
+
+ // Call the autogenerated instruction printer routines.
+ printInstruction(MI);
+}
+
bool ARMAsmPrinter::doInitialization(Module &M) {
- AsmPrinter::doInitialization(M);
- return false; // success
+ if (Subtarget->isDarwin()) {
+ // Emit initial debug information.
+ DW.BeginModule(&M);
+ }
+
+ return AsmPrinter::doInitialization(M);
}
bool ARMAsmPrinter::doFinalization(Module &M) {
@@ -302,53 +707,154 @@ bool ARMAsmPrinter::doFinalization(Module &M) {
if (EmitSpecialLLVMGlobal(I))
continue;
- O << "\n\n";
std::string name = Mang->getValueName(I);
Constant *C = I->getInitializer();
unsigned Size = TD->getTypeSize(C->getType());
- unsigned Align = Log2_32(TD->getTypeAlignment(C->getType()));
+ unsigned Align = TD->getPreferredAlignmentLog(I);
if (C->isNullValue() &&
!I->hasSection() &&
- (I->hasLinkOnceLinkage() || I->hasInternalLinkage() ||
- I->hasWeakLinkage())) {
- SwitchToDataSection(".data", I);
- if (I->hasInternalLinkage())
- O << "\t.local " << name << "\n";
-
- O << "\t.comm " << name << "," << Size
- << "," << (unsigned) (1 << Align);
- O << "\n";
+ (I->hasInternalLinkage() || I->hasWeakLinkage() ||
+ I->hasLinkOnceLinkage() ||
+ (Subtarget->isDarwin() && I->hasExternalLinkage()))) {
+ if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
+ if (I->hasExternalLinkage()) {
+ O << "\t.globl\t" << name << "\n";
+ O << "\t.zerofill __DATA__, __common, " << name << ", "
+ << Size << ", " << Align;
+ } else {
+ SwitchToDataSection(TAI->getDataSection(), I);
+ if (TAI->getLCOMMDirective() != NULL) {
+ if (I->hasInternalLinkage()) {
+ O << TAI->getLCOMMDirective() << name << "," << Size;
+ if (Subtarget->isDarwin())
+ O << "," << Align;
+ } else
+ O << TAI->getCOMMDirective() << name << "," << Size;
+ } else {
+ if (I->hasInternalLinkage())
+ O << "\t.local\t" << name << "\n";
+ O << TAI->getCOMMDirective() << name << "," << Size;
+ if (TAI->getCOMMDirectiveTakesAlignment())
+ O << "," << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
+ }
+ }
+ 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";
- break;
+ // FALL THROUGH
case GlobalValue::InternalLinkage:
- break;
- }
-
- if (I->hasSection() &&
- (I->getSection() == ".ctors" ||
- I->getSection() == ".dtors")) {
- std::string SectionName = ".section " + I->getSection();
+ if (I->isConstant()) {
+ const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
+ if (TAI->getCStringSection() && CVA && CVA->isCString()) {
+ SwitchToDataSection(TAI->getCStringSection(), I);
+ break;
+ }
+ }
- SectionName += ",\"aw\",%progbits";
+ 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);
+ }
- SwitchToDataSection(SectionName.c_str());
- } else {
- SwitchToDataSection(TAI->getDataSection(), I);
+ break;
}
+ }
- EmitAlignment(Align, I);
+ EmitAlignment(Align, I);
+ if (TAI->hasDotTypeDotSizeDirective()) {
O << "\t.type " << name << ", %object\n";
O << "\t.size " << name << ", " << Size << "\n";
- O << name << ":\n";
- EmitGlobalConstant(C);
}
+ 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))
+ if (GV->hasExternalWeakLinkage())
+ ExtWeakSymbols.insert(GV);
+
+ EmitGlobalConstant(C);
+ O << '\n';
+ }
+
+ if (Subtarget->isDarwin()) {
+ // Output stubs for dynamically-linked functions
+ unsigned j = 1;
+ for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end();
+ i != e; ++i, ++j) {
+ if (TM.getRelocationModel() == Reloc::PIC_)
+ SwitchToTextSection(".section __TEXT,__picsymbolstub4,symbol_stubs,"
+ "none,16", 0);
+ else
+ SwitchToTextSection(".section __TEXT,__symbol_stub4,symbol_stubs,"
+ "none,12", 0);
+
+ EmitAlignment(2);
+ O << "\