#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.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/Mangler.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
#include <cctype>
using namespace llvm;
namespace {
struct VISIBILITY_HIDDEN ARMAsmPrinter : public AsmPrinter {
- ARMAsmPrinter(std::ostream &O, TargetMachine &TM, const TargetAsmInfo *T)
- : AsmPrinter(O, TM, T), DW(O, this, T), MMI(NULL), AFI(NULL),
+ ARMAsmPrinter(raw_ostream &O, TargetMachine &TM, const TargetAsmInfo *T)
+ : AsmPrinter(O, TM, T), DW(0), MMI(NULL), AFI(NULL), MCP(NULL),
InCPMode(false) {
Subtarget = &TM.getSubtarget<ARMSubtarget>();
}
- DwarfWriter DW;
+ DwarfWriter *DW;
MachineModuleInfo *MMI;
/// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
const ARMSubtarget *Subtarget;
/// AFI - Keep a pointer to ARMFunctionInfo for the current
- /// MachineFunction
+ /// MachineFunction.
ARMFunctionInfo *AFI;
+ /// MCP - Keep a pointer to constantpool entries of the current
+ /// MachineFunction.
+ const MachineConstantPool *MCP;
+
/// 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().
/// GVNonLazyPtrs - Keeps the set of GlobalValues that require
/// non-lazy-pointers for indirect access.
- std::set<std::string> GVNonLazyPtrs;
+ StringSet<> GVNonLazyPtrs;
+
+ /// HiddenGVNonLazyPtrs - Keeps the set of GlobalValues with hidden
+ /// visibility that require non-lazy-pointers for indirect access.
+ StringSet<> HiddenGVNonLazyPtrs;
/// FnStubs - Keeps the set of external function GlobalAddresses that the
/// asm printer should generate stubs for.
- std::set<std::string> FnStubs;
-
- /// PCRelGVs - Keeps the set of GlobalValues used in pc relative
- /// constantpool.
- SmallPtrSet<const GlobalValue*, 8> PCRelGVs;
+ StringSet<> FnStubs;
/// True if asm printer is printing a series of CONSTPOOL_ENTRY.
bool InCPMode;
bool doInitialization(Module &M);
bool doFinalization(Module &M);
- /// getSectionForFunction - Return the section that we should emit the
- /// specified function body into.
- virtual std::string getSectionForFunction(const Function &F) const;
-
/// EmitMachineConstantPoolValue - Print a machine constantpool value to
/// the .s file.
virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
if (!GV)
Name += ACPV->getSymbol();
if (ACPV->isNonLazyPointer()) {
- GVNonLazyPtrs.insert(Name);
+ if (GV->hasHiddenVisibility())
+ HiddenGVNonLazyPtrs.insert(Name);
+ else
+ GVNonLazyPtrs.insert(Name);
printSuffixedName(Name, "$non_lazy_ptr");
} else if (ACPV->isStub()) {
FnStubs.insert(Name);
AsmPrinter::getAnalysisUsage(AU);
AU.setPreservesAll();
AU.addRequired<MachineModuleInfo>();
+ AU.addRequired<DwarfWriter>();
}
};
} // end of anonymous namespace
#include "ARMGenAsmWriter.inc"
-// Substitute old hook with new one temporary
-std::string ARMAsmPrinter::getSectionForFunction(const Function &F) const {
- return TAI->SectionForGlobal(&F);
-}
-
/// runOnMachineFunction - This uses the printInstruction()
/// method to print assembly for each instruction.
///
bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
AFI = MF.getInfo<ARMFunctionInfo>();
+ MCP = MF.getConstantPool();
SetupMachineFunction(MF);
O << "\n";
const Function *F = MF.getFunction();
switch (F->getLinkage()) {
default: assert(0 && "Unknown linkage type!");
+ case Function::PrivateLinkage:
case Function::InternalLinkage:
SwitchToTextSection("\t.text", F);
break;
O << CurrentFnName << ":\n";
// Emit pre-function debug information.
- // FIXME: Dwarf support.
- //DW.BeginFunction(&MF);
+ DW->BeginFunction(&MF);
if (Subtarget->isTargetDarwin()) {
// If the function is empty, then we need to emit *something*. Otherwise,
O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n";
// Emit post-function debug information.
- // FIXME: Dwarf support.
- //DW.EndFunction();
+ DW->EndFunction(&MF);
+
+ O.flush();
return false;
}
FnStubs.insert(Name);
} else
O << Name;
-
- if (MO.getOffset() > 0)
- O << '+' << MO.getOffset();
- else if (MO.getOffset() < 0)
- O << MO.getOffset();
-
+
+ printOffset(MO.getOffset());
+
if (isCallOp && Subtarget->isTargetELF() &&
TM.getRelocationModel() == Reloc::PIC_)
O << "(PLT)";
}
}
-static void printSOImm(std::ostream &O, int64_t V, const TargetAsmInfo *TAI) {
+static void printSOImm(raw_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".
if (Rot) {
/// 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!");
+ assert(MO.isImm() && "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.
+/// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov'
+/// followed by an 'orr' 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!");
+ assert(MO.isImm() && "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);
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.
+ if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
printOperand(MI, Op);
return;
}
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.
+ if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
printOperand(MI, Op);
return;
}
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.
+ if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
printOperand(MI, Op);
return;
}
assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE");
unsigned CPI = MI->getOperand(OpNo).getIndex();
- const MachineConstantPoolEntry &MCPE = // Chasing pointers is fun?
- MI->getParent()->getParent()->getConstantPool()->getConstants()[CPI];
+ const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPI];
if (MCPE.isMachineConstantPoolEntry()) {
EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
- ARMConstantPoolValue *ACPV =
- static_cast<ARMConstantPoolValue*>(MCPE.Val.MachineCPVal);
- if (ACPV->getPCAdjustment() != 0) {
- const GlobalValue *GV = ACPV->getGV();
- PCRelGVs.insert(GV);
- }
} else {
EmitGlobalConstant(MCPE.Val.ConstVal);
// remember to emit the weak reference
// Fallthrough
case 'H': // Write second word of DI / DF reference.
// Verify that this operand has two consecutive registers.
- if (!MI->getOperand(OpNo).isRegister() ||
+ if (!MI->getOperand(OpNo).isReg() ||
OpNo+1 == MI->getNumOperands() ||
- !MI->getOperand(OpNo+1).isRegister())
+ !MI->getOperand(OpNo+1).isReg())
return true;
++OpNo; // Return the high-part.
}
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;
- }
}}
// Call the autogenerated instruction printer routines.
}
bool ARMAsmPrinter::doInitialization(Module &M) {
- // Emit initial debug information.
- // FIXME: Dwarf support.
- //DW.BeginModule(&M);
-
+
bool Result = AsmPrinter::doInitialization(M);
- // AsmPrinter::doInitialization should have done this analysis.
- MMI = getAnalysisToUpdate<MachineModuleInfo>();
+ // Emit initial debug information.
+ MMI = getAnalysisIfAvailable<MachineModuleInfo>();
assert(MMI);
- // FIXME: Dwarf support.
- //DW.SetModuleInfo(MMI);
+ DW = getAnalysisIfAvailable<DwarfWriter>();
+ assert(DW && "Dwarf Writer is not available");
+ DW->BeginModule(&M, MMI, O, this, TAI);
// Darwin wants symbols to be quoted if they have complex names.
if (Subtarget->isTargetDarwin())
/// 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) {
+static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) {
for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen();
Name != E; ++Name)
if (isprint(*Name))
return;
}
- std::string SectionName = TAI->SectionForGlobal(GVar);
std::string name = Mang->getValueName(GVar);
Constant *C = GVar->getInitializer();
const Type *Type = C->getType();
- unsigned Size = TD->getABITypeSize(Type);
+ unsigned Size = TD->getTypePaddedSize(Type);
unsigned Align = TD->getPreferredAlignmentLog(GVar);
+ bool isDarwin = Subtarget->isTargetDarwin();
printVisibility(name, GVar->getVisibility());
if (Subtarget->isTargetELF())
O << "\t.type " << name << ",%object\n";
- SwitchToDataSection(SectionName.c_str());
-
- if (C->isNullValue() && !GVar->hasSection() && !GVar->isThreadLocal()) {
+ if (C->isNullValue() && !GVar->hasSection() && !GVar->isThreadLocal() &&
+ !(isDarwin &&
+ TAI->SectionKindForGlobal(GVar) == SectionKind::RODataMergeStr)) {
// FIXME: This seems to be pretty darwin-specific
if (GVar->hasExternalLinkage()) {
+ SwitchToSection(TAI->SectionForGlobal(GVar));
if (const char *Directive = TAI->getZeroFillDirective()) {
O << "\t.globl\t" << name << "\n";
O << Directive << "__DATA, __common, " << name << ", "
}
}
- if (GVar->hasInternalLinkage() || GVar->isWeakForLinker()) {
+ if (GVar->hasLocalLinkage() || GVar->mayBeOverridden()) {
if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
- if (TAI->getLCOMMDirective() != NULL) {
- if (PCRelGVs.count(GVar) || GVar->hasInternalLinkage()) {
+ if (isDarwin) {
+ if (GVar->hasLocalLinkage()) {
+ O << TAI->getLCOMMDirective() << name << "," << Size
+ << ',' << Align;
+ } else if (GVar->hasCommonLinkage()) {
+ O << TAI->getCOMMDirective() << name << "," << Size
+ << ',' << Align;
+ } else {
+ SwitchToSection(TAI->SectionForGlobal(GVar));
+ O << "\t.globl " << name << '\n'
+ << TAI->getWeakDefDirective() << name << '\n';
+ EmitAlignment(Align, GVar);
+ O << name << ":\t\t\t\t" << TAI->getCommentString() << ' ';
+ PrintUnmangledNameSafely(GVar, O);
+ O << '\n';
+ EmitGlobalConstant(C);
+ return;
+ }
+ } else if (TAI->getLCOMMDirective() != NULL) {
+ if (GVar->hasLocalLinkage()) {
O << TAI->getLCOMMDirective() << name << "," << Size;
- if (Subtarget->isTargetDarwin())
- O << "," << Align;
- } else
+ } else {
O << TAI->getCOMMDirective() << name << "," << Size;
+ if (TAI->getCOMMDirectiveTakesAlignment())
+ O << ',' << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
+ }
} else {
- if (GVar->hasInternalLinkage())
+ SwitchToSection(TAI->SectionForGlobal(GVar));
+ if (GVar->hasLocalLinkage())
O << "\t.local\t" << name << "\n";
O << TAI->getCOMMDirective() << name << "," << Size;
if (TAI->getCOMMDirectiveTakesAlignment())
}
}
+ SwitchToSection(TAI->SectionForGlobal(GVar));
switch (GVar->getLinkage()) {
+ case GlobalValue::CommonLinkage:
case GlobalValue::LinkOnceLinkage:
case GlobalValue::WeakLinkage:
- if (Subtarget->isTargetDarwin()) {
+ if (isDarwin) {
O << "\t.globl " << name << "\n"
<< "\t.weak_definition " << name << "\n";
} else {
case GlobalValue::ExternalLinkage:
O << "\t.globl " << name << "\n";
// FALL THROUGH
+ case GlobalValue::PrivateLinkage:
case GlobalValue::InternalLinkage:
break;
default:
SwitchToDataSection("");
// 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) {
+ for (StringSet<>::iterator i = FnStubs.begin(), e = FnStubs.end();
+ i != e; ++i) {
if (TM.getRelocationModel() == Reloc::PIC_)
SwitchToTextSection(".section __TEXT,__picsymbolstub4,symbol_stubs,"
"none,16", 0);
EmitAlignment(2);
O << "\t.code\t32\n";
- std::string p = *i;
+ const char *p = i->getKeyData();
printSuffixedName(p, "$stub");
O << ":\n";
- O << "\t.indirect_symbol " << *i << "\n";
+ O << "\t.indirect_symbol " << p << "\n";
O << "\tldr ip, ";
printSuffixedName(p, "$slp");
O << "\n";
SwitchToDataSection(".lazy_symbol_pointer", 0);
printSuffixedName(p, "$lazy_ptr");
O << ":\n";
- O << "\t.indirect_symbol " << *i << "\n";
+ O << "\t.indirect_symbol " << p << "\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(".non_lazy_symbol_pointer", 0);
- for (std::set<std::string>::iterator i = GVNonLazyPtrs.begin(),
- e = GVNonLazyPtrs.end(); i != e; ++i) {
- std::string p = *i;
- printSuffixedName(p, "$non_lazy_ptr");
- O << ":\n";
- O << "\t.indirect_symbol " << *i << "\n";
- O << "\t.long\t0\n";
+ if (!GVNonLazyPtrs.empty()) {
+ SwitchToDataSection("\t.non_lazy_symbol_pointer", 0);
+ for (StringSet<>::iterator i = GVNonLazyPtrs.begin(),
+ e = GVNonLazyPtrs.end(); i != e; ++i) {
+ const char *p = i->getKeyData();
+ printSuffixedName(p, "$non_lazy_ptr");
+ O << ":\n";
+ O << "\t.indirect_symbol " << p << "\n";
+ O << "\t.long\t0\n";
+ }
}
+ if (!HiddenGVNonLazyPtrs.empty()) {
+ SwitchToSection(TAI->getDataSection());
+ for (StringSet<>::iterator i = HiddenGVNonLazyPtrs.begin(),
+ e = HiddenGVNonLazyPtrs.end(); i != e; ++i) {
+ const char *p = i->getKeyData();
+ EmitAlignment(2);
+ printSuffixedName(p, "$non_lazy_ptr");
+ O << ":\n";
+ O << "\t.long " << p << "\n";
+ }
+ }
+
+
// Emit initial debug information.
- // FIXME: Dwarf support.
- //DW.EndModule();
+ DW->EndModule();
// Funny Darwin hack: This flag tells the linker that no global symbols
// contain code that falls through to other global symbols (e.g. the obvious
O << "\t.subsections_via_symbols\n";
} else {
// Emit final debug information for ELF.
- // FIXME: Dwarf support.
- //DW.EndModule();
+ DW->EndModule();
}
return AsmPrinter::doFinalization(M);
/// using the given target machine description. This should work
/// regardless of whether the function is in SSA form.
///
-FunctionPass *llvm::createARMCodePrinterPass(std::ostream &o,
+FunctionPass *llvm::createARMCodePrinterPass(raw_ostream &o,
ARMTargetMachine &tm) {
return new ARMAsmPrinter(o, tm, tm.getTargetAsmInfo());
}