#include "ARMMachineFunctionInfo.h"
#include "llvm/Constants.h"
#include "llvm/Module.h"
-#include "llvm/MDNode.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
+#include "llvm/MC/MCSection.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
-#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
const char *Modifier);
void printJTBlockOperand(const MachineInstr *MI, int OpNum);
void printJT2BlockOperand(const MachineInstr *MI, int OpNum);
+ void printTBAddrMode(const MachineInstr *MI, int OpNum);
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
unsigned AsmVariant, const char *ExtraCode);
const char *ExtraCode);
void PrintGlobalVariable(const GlobalVariable* GVar);
- bool printInstruction(const MachineInstr *MI); // autogenerated.
+ void printInstruction(const MachineInstr *MI); // autogenerated.
void printMachineInstruction(const MachineInstr *MI);
bool runOnMachineFunction(MachineFunction &F);
bool doInitialization(Module &M);
if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";
if (ACPV->getPCAdjustment() != 0) {
O << "-(" << TAI->getPrivateGlobalPrefix() << "PC"
- << utostr(ACPV->getLabelId())
+ << ACPV->getLabelId()
<< "+" << (unsigned)ACPV->getPCAdjustment();
if (ACPV->mustAddCurrentAddress())
O << "-.";
// NOTE: we don't print out constant pools here, they are handled as
// instructions.
- O << "\n";
+ O << '\n';
+
// Print out labels for the function.
const Function *F = MF.getFunction();
+ SwitchToSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
+
switch (F->getLinkage()) {
default: llvm_unreachable("Unknown linkage type!");
case Function::PrivateLinkage:
case Function::LinkerPrivateLinkage:
case Function::InternalLinkage:
- SwitchToTextSection("\t.text", F);
break;
case Function::ExternalLinkage:
- SwitchToTextSection("\t.text", F);
O << "\t.globl\t" << CurrentFnName << "\n";
break;
case Function::WeakAnyLinkage:
case Function::LinkOnceAnyLinkage:
case Function::LinkOnceODRLinkage:
if (Subtarget->isTargetDarwin()) {
- SwitchToTextSection(
- ".section __TEXT,__textcoal_nt,coalesced,pure_instructions", F);
O << "\t.globl\t" << CurrentFnName << "\n";
O << "\t.weak_definition\t" << CurrentFnName << "\n";
} else {
// Emit post-function debug information.
DW->EndFunction(&MF);
- O.flush();
-
return false;
}
O << '{'
<< TRI->getAsmName(DRegLo) << ',' << TRI->getAsmName(DRegHi)
<< '}';
- } else if (Modifier && strcmp(Modifier, "dregsingle") == 0) {
- O << '{' << TRI->getAsmName(Reg) << '}';
+ } else if (Modifier && strcmp(Modifier, "lane") == 0) {
+ unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(Reg);
+ unsigned DReg = TRI->getMatchingSuperReg(Reg, RegNum & 1 ? 0 : 1,
+ &ARM::DPRRegClass);
+ O << TRI->getAsmName(DReg) << '[' << (RegNum & 1) << ']';
} else {
O << TRI->getAsmName(Reg);
}
}
case MachineOperand::MO_Immediate: {
if (!Modifier || strcmp(Modifier, "no_hash") != 0)
- O << "#";
+ O << '#';
O << MO.getImm();
break;
ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
if (Modifier && strcmp(Modifier, "submode") == 0) {
if (MO1.getReg() == ARM::SP) {
+ // FIXME
bool isLDM = (MI->getOpcode() == ARM::LDM ||
- MI->getOpcode() == ARM::LDM_RET);
+ MI->getOpcode() == ARM::LDM_RET ||
+ MI->getOpcode() == ARM::t2LDM ||
+ MI->getOpcode() == ARM::t2LDM_RET);
O << ARM_AM::getAMSubModeAltStr(Mode, isLDM);
} else
O << ARM_AM::getAMSubModeStr(Mode);
+ } else if (Modifier && strcmp(Modifier, "wide") == 0) {
+ ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
+ if (Mode == ARM_AM::ia)
+ O << ".w";
} else {
printOperand(MI, Op);
if (ARM_AM::getAM4WBFlag(MO2.getImm()))
const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
+ bool ByteOffset = false, HalfWordOffset = false;
+ if (MI->getOpcode() == ARM::t2TBB)
+ ByteOffset = true;
+ else if (MI->getOpcode() == ARM::t2TBH)
+ HalfWordOffset = true;
+
for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
MachineBasicBlock *MBB = JTBBs[i];
- O << "\tb.w ";
- printBasicBlockLabel(MBB, false, false, false);
+ if (ByteOffset)
+ O << TAI->getData8bitsDirective();
+ else if (HalfWordOffset)
+ O << TAI->getData16bitsDirective();
+ if (ByteOffset || HalfWordOffset) {
+ O << '(';
+ printBasicBlockLabel(MBB, false, false, false);
+ O << "-" << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
+ << '_' << JTI << '_' << MO2.getImm() << ")/2";
+ } else {
+ O << "\tb.w ";
+ printBasicBlockLabel(MBB, false, false, false);
+ }
if (i != e-1)
O << '\n';
}
+
+ // Make sure the instruction that follows TBB is 2-byte aligned.
+ // FIXME: Constant island pass should insert an "ALIGN" instruction instead.
+ if (ByteOffset && (JTBBs.size() & 1)) {
+ O << '\n';
+ EmitAlignment(1);
+ }
+}
+
+void ARMAsmPrinter::printTBAddrMode(const MachineInstr *MI, int OpNum) {
+ O << "[pc, " << TRI->getAsmName(MI->getOperand(OpNum).getReg());
+ if (MI->getOpcode() == ARM::t2TBH)
+ O << ", lsl #1";
+ O << ']';
}
O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_align8_needed << ", 1\n"
<< "\t.eabi_attribute " << ARMBuildAttrs::ABI_align8_preserved << ", 1\n";
+ // Hard float. Use both S and D registers and conform to AAPCS-VFP.
+ if (Subtarget->isAAPCS_ABI() && FloatABIType == FloatABI::Hard)
+ O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_HardFP_use << ", 3\n"
+ << "\t.eabi_attribute " << ARMBuildAttrs::ABI_VFP_args << ", 1\n";
+
// FIXME: Should we signal R9 usage?
}
std::string name = Mang->getMangledName(GVar);
Constant *C = GVar->getInitializer();
- if (isa<MDNode>(C) || isa<MDString>(C))
- return;
const Type *Type = C->getType();
unsigned Size = TD->getTypeAllocSize(Type);
unsigned Align = TD->getPreferredAlignmentLog(GVar);
if (Subtarget->isTargetELF())
O << "\t.type " << name << ",%object\n";
- const Section *TheSection = getObjFileLowering().SectionForGlobal(GVar, TM);
+ const MCSection *TheSection =
+ getObjFileLowering().SectionForGlobal(GVar, Mang, TM);
SwitchToSection(TheSection);
// FIXME: get this stuff from section kind flags.
O << TAI->getCOMMDirective() << name << "," << Size
<< ',' << Align;
} else {
- SwitchToSection(getObjFileLowering().SectionForGlobal(GVar, TM));
+ SwitchToSection(getObjFileLowering().SectionForGlobal(GVar, Mang,TM));
O << "\t.globl " << name << '\n'
<< TAI->getWeakDefDirective() << name << '\n';
EmitAlignment(Align, GVar);
bool ARMAsmPrinter::doFinalization(Module &M) {
if (Subtarget->isTargetDarwin()) {
- SwitchToDataSection("");
-
+ // All darwin targets use mach-o.
+ TargetLoweringObjectFileMachO &TLOFMacho =
+ static_cast<TargetLoweringObjectFileMachO &>(getObjFileLowering());
+
O << '\n';
- // Output stubs for dynamically-linked functions
- for (StringMap<FnStubInfo>::iterator I = FnStubs.begin(), E = FnStubs.end();
- I != E; ++I) {
- const FnStubInfo &Info = I->second;
+
+ if (!FnStubs.empty()) {
+ const MCSection *StubSection;
if (TM.getRelocationModel() == Reloc::PIC_)
- SwitchToTextSection(".section __TEXT,__picsymbolstub4,symbol_stubs,"
- "none,16", 0);
+ StubSection = TLOFMacho.getMachOSection(".section __TEXT,__picsymbolstu"
+ "b4,symbol_stubs,none,16", true,
+ SectionKind::getText());
else
- SwitchToTextSection(".section __TEXT,__symbol_stub4,symbol_stubs,"
- "none,12", 0);
+ StubSection = TLOFMacho.getMachOSection(".section __TEXT,__symbol_stub4"
+ ",symbol_stubs,none,12", true,
+ SectionKind::getText());
- EmitAlignment(2);
- O << "\t.code\t32\n";
-
- O << Info.Stub << ":\n";
- O << "\t.indirect_symbol " << I->getKeyData() << '\n';
- O << "\tldr ip, " << Info.SLP << '\n';
- if (TM.getRelocationModel() == Reloc::PIC_) {
- O << Info.SCV << ":\n";
- O << "\tadd ip, pc, ip\n";
+ const MCSection *LazySymbolPointerSection
+ = TLOFMacho.getMachOSection(".lazy_symbol_pointer", true,
+ SectionKind::getMetadata());
+
+ // Output stubs for dynamically-linked functions
+ for (StringMap<FnStubInfo>::iterator I = FnStubs.begin(),
+ E = FnStubs.end(); I != E; ++I) {
+ const FnStubInfo &Info = I->second;
+
+ SwitchToSection(StubSection);
+ EmitAlignment(2);
+ O << "\t.code\t32\n";
+
+ O << Info.Stub << ":\n";
+ O << "\t.indirect_symbol " << I->getKeyData() << '\n';
+ O << "\tldr ip, " << Info.SLP << '\n';
+ if (TM.getRelocationModel() == Reloc::PIC_) {
+ O << Info.SCV << ":\n";
+ O << "\tadd ip, pc, ip\n";
+ }
+ O << "\tldr pc, [ip, #0]\n";
+ O << Info.SLP << ":\n";
+ O << "\t.long\t" << Info.LazyPtr;
+ if (TM.getRelocationModel() == Reloc::PIC_)
+ O << "-(" << Info.SCV << "+8)";
+ O << '\n';
+
+ SwitchToSection(LazySymbolPointerSection);
+ O << Info.LazyPtr << ":\n";
+ O << "\t.indirect_symbol " << I->getKeyData() << "\n";
+ O << "\t.long\tdyld_stub_binding_helper\n";
}
- O << "\tldr pc, [ip, #0]\n";
- O << Info.SLP << ":\n";
- O << "\t.long\t" << Info.LazyPtr;
- if (TM.getRelocationModel() == Reloc::PIC_)
- O << "-(" << Info.SCV << "+8)";
O << '\n';
-
- SwitchToDataSection(".lazy_symbol_pointer", 0);
- O << Info.LazyPtr << ":\n";
- O << "\t.indirect_symbol " << I->getKeyData() << "\n";
- O << "\t.long\tdyld_stub_binding_helper\n";
}
- O << '\n';
-
+
// Output non-lazy-pointers for external and common global variables.
if (!GVNonLazyPtrs.empty()) {
- SwitchToDataSection("\t.non_lazy_symbol_pointer", 0);
- for (StringMap<std::string>::iterator I = GVNonLazyPtrs.begin(),
- E = GVNonLazyPtrs.end(); I != E; ++I) {
+ SwitchToSection(TLOFMacho.getMachOSection(".non_lazy_symbol_pointer",
+ true,
+ SectionKind::getMetadata()));
+ for (StringMap<std::string>::iterator I = GVNonLazyPtrs.begin(),
+ E = GVNonLazyPtrs.end(); I != E; ++I) {
O << I->second << ":\n";
O << "\t.indirect_symbol " << I->getKeyData() << "\n";
O << "\t.long\t0\n";