STATISTIC(EmittedInsts, "Number of machine instrs printed");
char AsmPrinter::ID = 0;
+
AsmPrinter::AsmPrinter(formatted_raw_ostream &o, TargetMachine &tm,
- MCContext &Ctx, MCStreamer &Streamer,
- const MCAsmInfo *T)
+ MCStreamer &Streamer)
: MachineFunctionPass(&ID), O(o),
- TM(tm), MAI(T), TRI(tm.getRegisterInfo()),
- OutContext(Ctx), OutStreamer(Streamer),
- LastMI(0), LastFn(0), Counter(~0U), PrevDLT(NULL) {
+ TM(tm), MAI(tm.getMCAsmInfo()), TRI(tm.getRegisterInfo()),
+ OutContext(Streamer.getContext()),
+ OutStreamer(Streamer),
+ LastMI(0), LastFn(0), Counter(~0U), SetCounter(0), PrevDLT(NULL) {
DW = 0; MMI = 0;
VerboseAsm = Streamer.isVerboseAsm();
}
delete I->second;
delete &OutStreamer;
- delete &OutContext;
}
/// getFunctionNumber - Return a unique ID for the current function.
void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
MachineFunctionPass::getAnalysisUsage(AU);
+ AU.addRequired<MachineModuleInfo>();
AU.addRequired<GCModuleInfo>();
if (VerboseAsm)
AU.addRequired<MachineLoopInfo>();
}
bool AsmPrinter::doInitialization(Module &M) {
+ MMI = getAnalysisIfAvailable<MachineModuleInfo>();
+ MMI->AnalyzeModule(M);
+
// Initialize TargetLoweringObjectFile.
const_cast<TargetLoweringObjectFile&>(getObjFileLowering())
.Initialize(OutContext, TM);
- Mang = new Mangler(*MAI);
+ Mang = new Mangler(OutContext, *TM.getTargetData());
// Allow the target to emit any magic that it wants at the start of the file.
EmitStartOfAsmFile(M);
<< '\n' << MAI->getCommentString()
<< " End of file scope inline assembly\n";
- MMI = getAnalysisIfAvailable<MachineModuleInfo>();
- if (MMI)
- MMI->AnalyzeModule(M);
DW = getAnalysisIfAvailable<DwarfWriter>();
if (DW)
DW->BeginModule(&M, MMI, O, this, MAI);
if (EmitSpecialLLVMGlobal(GV))
return;
- MCSymbol *GVSym = GetGlobalValueSymbol(GV);
+ MCSymbol *GVSym = Mang->getSymbol(GV);
EmitVisibility(GVSym, GV->getVisibility());
if (MAI->hasDotTypeDotSizeDirective())
OutStreamer.GetCommentOS() << '\n';
}
- // Emit the CurrentFnSym. This is is a virtual function to allow targets to
+ // Emit the CurrentFnSym. This is a virtual function to allow targets to
// do their wild and crazy things as required.
EmitFunctionEntryLabel();
// Print source line info.
DIScope Scope = DLT.getScope();
// Omit the directory, because it's likely to be long and uninteresting.
- if (!Scope.isNull())
+ if (Scope.Verify())
CommentOS << Scope.getFilename();
else
CommentOS << "<unknown>";
unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
if (TM.getInstrInfo()->isMoveInstr(MI, SrcReg, DstReg,
SrcSubIdx, DstSubIdx)) {
- if (MI.getAsmPrinterFlag(AsmPrinter::ReloadReuse))
+ if (MI.getAsmPrinterFlag(MachineInstr::ReloadReuse))
CommentOS << " Reload Reuse\n";
}
}
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
if (!I->hasExternalWeakLinkage()) continue;
- OutStreamer.EmitSymbolAttribute(GetGlobalValueSymbol(I),
- MCSA_WeakReference);
+ OutStreamer.EmitSymbolAttribute(Mang->getSymbol(I), MCSA_WeakReference);
}
for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) {
if (!I->hasExternalWeakLinkage()) continue;
- OutStreamer.EmitSymbolAttribute(GetGlobalValueSymbol(I),
- MCSA_WeakReference);
+ OutStreamer.EmitSymbolAttribute(Mang->getSymbol(I), MCSA_WeakReference);
}
}
OutStreamer.AddBlankLine();
for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end();
I != E; ++I) {
- MCSymbol *Name = GetGlobalValueSymbol(I);
+ MCSymbol *Name = Mang->getSymbol(I);
const GlobalValue *GV = cast<GlobalValue>(I->getAliasedGlobal());
- MCSymbol *Target = GetGlobalValueSymbol(GV);
+ MCSymbol *Target = Mang->getSymbol(GV);
if (I->hasExternalLinkage() || !MAI->getWeakRefDirective())
OutStreamer.EmitSymbolAttribute(Name, MCSA_Global);
void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
this->MF = &MF;
// Get the function symbol.
- CurrentFnSym = GetGlobalValueSymbol(MF.getFunction());
+ CurrentFnSym = Mang->getSymbol(MF.getFunction());
if (VerboseAsm)
LI = &getAnalysis<MachineLoopInfo>();
void AsmPrinter::EmitJumpTableInfo() {
const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
if (MJTI == 0) return;
+ if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_Inline) return;
const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
if (JT.empty()) return;
// .set LJTSet, LBB32-base
const MCExpr *LHS =
- MCSymbolRefExpr::Create(MBB->getSymbol(OutContext), OutContext);
+ MCSymbolRefExpr::Create(MBB->getSymbol(), OutContext);
OutStreamer.EmitAssignment(GetJTSetSymbol(JTI, MBB->getNumber()),
MCBinaryExpr::CreateSub(LHS, Base, OutContext));
}
unsigned UID) const {
const MCExpr *Value = 0;
switch (MJTI->getEntryKind()) {
+ case MachineJumpTableInfo::EK_Inline:
+ llvm_unreachable("Cannot emit EK_Inline jump table entry"); break;
case MachineJumpTableInfo::EK_Custom32:
Value = TM.getTargetLowering()->LowerCustomJumpTableEntry(MJTI, MBB, UID,
OutContext);
case MachineJumpTableInfo::EK_BlockAddress:
// EK_BlockAddress - Each entry is a plain address of block, e.g.:
// .word LBB123
- Value = MCSymbolRefExpr::Create(MBB->getSymbol(OutContext), OutContext);
+ Value = MCSymbolRefExpr::Create(MBB->getSymbol(), OutContext);
break;
case MachineJumpTableInfo::EK_GPRel32BlockAddress: {
// EK_GPRel32BlockAddress - Each entry is an address of block, encoded
// with a relocation as gp-relative, e.g.:
// .gprel32 LBB123
- MCSymbol *MBBSym = MBB->getSymbol(OutContext);
+ MCSymbol *MBBSym = MBB->getSymbol();
OutStreamer.EmitGPRel32Value(MCSymbolRefExpr::Create(MBBSym, OutContext));
return;
}
break;
}
// Otherwise, use the difference as the jump table entry.
- Value = MCSymbolRefExpr::Create(MBB->getSymbol(OutContext), OutContext);
+ Value = MCSymbolRefExpr::Create(MBB->getSymbol(), OutContext);
const MCExpr *JTI = MCSymbolRefExpr::Create(GetJTISymbol(UID), OutContext);
Value = MCBinaryExpr::CreateSub(Value, JTI, OutContext);
break;
const GlobalValue *GV =
dyn_cast<GlobalValue>(InitList->getOperand(i)->stripPointerCasts());
if (GV && getObjFileLowering().shouldEmitUsedDirectiveFor(GV, Mang))
- OutStreamer.EmitSymbolAttribute(GetGlobalValueSymbol(GV),
- MCSA_NoDeadStrip);
+ OutStreamer.EmitSymbolAttribute(Mang->getSymbol(GV), MCSA_NoDeadStrip);
}
}
OutStreamer.EmitIntValue(Value, 8, 0/*addrspace*/);
}
+/// EmitLabelDifference - Emit something like ".long Hi-Lo" where the size
+/// in bytes of the directive is specified by Size and Hi/Lo specify the
+/// labels. This implicitly uses .set if it is available.
+void AsmPrinter::EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo,
+ unsigned Size) const {
+ // Get the Hi-Lo expression.
+ const MCExpr *Diff =
+ MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(Hi, OutContext),
+ MCSymbolRefExpr::Create(Lo, OutContext),
+ OutContext);
+
+ if (!MAI->hasSetDirective()) {
+ OutStreamer.EmitValue(Diff, Size, 0/*AddrSpace*/);
+ return;
+ }
+
+ // Otherwise, emit with .set (aka assignment).
+ MCSymbol *SetLabel =
+ OutContext.GetOrCreateTemporarySymbol(Twine(MAI->getPrivateGlobalPrefix()) +
+ "set" + Twine(SetCounter++));
+ OutStreamer.EmitAssignment(SetLabel, Diff);
+ OutStreamer.EmitSymbolValue(SetLabel, Size, 0/*AddrSpace*/);
+}
+
+
//===----------------------------------------------------------------------===//
// EmitAlignment - Emit an alignment directive to the specified power of
if (NumBits == 0) return; // No need to emit alignment.
- unsigned FillValue = 0;
if (getCurrentSection()->getKind().isText())
- FillValue = MAI->getTextAlignFillValue();
-
- OutStreamer.EmitValueToAlignment(1 << NumBits, FillValue, 1, 0);
+ OutStreamer.EmitCodeAlignment(1 << NumBits);
+ else
+ OutStreamer.EmitValueToAlignment(1 << NumBits, 0, 1, 0);
}
/// LowerConstant - Lower the specified LLVM Constant to an MCExpr.
return MCConstantExpr::Create(CI->getZExtValue(), Ctx);
if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV))
- return MCSymbolRefExpr::Create(AP.GetGlobalValueSymbol(GV), Ctx);
+ return MCSymbolRefExpr::Create(AP.Mang->getSymbol(GV), Ctx);
if (const BlockAddress *BA = dyn_cast<BlockAddress>(CV))
return MCSymbolRefExpr::Create(AP.GetBlockAddressSymbol(BA), Ctx);
if (DL.isUnknown())
return;
DILocation CurDLT = MF->getDILocation(DL);
- if (CurDLT.getScope().isNull())
+ if (!CurDLT.getScope().Verify())
return;
if (!BeforePrintingInsn) {
// After printing instruction
DW->EndScope(MI);
} else if (CurDLT.getNode() != PrevDLT) {
- unsigned L = DW->RecordSourceLine(CurDLT.getLineNumber(),
- CurDLT.getColumnNumber(),
- CurDLT.getScope().getNode());
- printLabel(L);
- O << '\n';
+ MCSymbol *L = DW->RecordSourceLine(CurDLT.getLineNumber(),
+ CurDLT.getColumnNumber(),
+ CurDLT.getScope().getNode());
DW->BeginScope(MI, L);
PrevDLT = CurDLT.getNode();
}
++OpNo; // Skip over the ID number.
if (Modifier[0] == 'l') // labels are target independent
- O << *MI->getOperand(OpNo).getMBB()->getSymbol(OutContext);
+ O << *MI->getOperand(OpNo).getMBB()->getSymbol();
else {
AsmPrinter *AP = const_cast<AsmPrinter*>(this);
if ((OpFlags & 7) == 4) {
/// printLabel - This method prints a local label used by debug and
/// exception handling tables.
void AsmPrinter::printLabelInst(const MachineInstr *MI) const {
- printLabel(MI->getOperand(0).getImm());
- OutStreamer.AddBlankLine();
-}
-
-void AsmPrinter::printLabel(unsigned Id) const {
- O << MAI->getPrivateGlobalPrefix() << "label" << Id << ':';
+ OutStreamer.EmitLabel(MI->getOperand(0).getMCSymbol());
}
/// PrintAsmOperand - Print the specified operand of MI, an INLINEASM
}
MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BlockAddress *BA) const {
- return GetBlockAddressSymbol(BA->getFunction(), BA->getBasicBlock());
+ return MMI->getAddrLabelSymbol(BA->getBasicBlock());
}
-MCSymbol *AsmPrinter::GetBlockAddressSymbol(const Function *F,
- const BasicBlock *BB) const {
- assert(BB->hasName() &&
- "Address of anonymous basic block not supported yet!");
-
- // This code must use the function name itself, and not the function number,
- // since it must be possible to generate the label name from within other
- // functions.
- SmallString<60> FnName;
- Mang->getNameWithPrefix(FnName, F, false);
-
- // FIXME: THIS IS BROKEN IF THE LLVM BASIC BLOCK DOESN'T HAVE A NAME!
- SmallString<60> NameResult;
- Mang->getNameWithPrefix(NameResult,
- StringRef("BA") + Twine((unsigned)FnName.size()) +
- "_" + FnName.str() + "_" + BB->getName(),
- Mangler::Private);
-
- return OutContext.GetOrCreateSymbol(NameResult.str());
+MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BasicBlock *BB) const {
+ return MMI->getAddrLabelSymbol(BB);
}
/// GetCPISymbol - Return the symbol for the specified constant pool entry.
MCSymbol *AsmPrinter::GetCPISymbol(unsigned CPID) const {
- SmallString<60> Name;
- raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "CPI"
- << getFunctionNumber() << '_' << CPID;
- return OutContext.GetOrCreateSymbol(Name.str());
+ return OutContext.GetOrCreateTemporarySymbol
+ (Twine(MAI->getPrivateGlobalPrefix()) + "CPI" + Twine(getFunctionNumber())
+ + "_" + Twine(CPID));
}
/// GetJTISymbol - Return the symbol for the specified jump table entry.
/// GetJTSetSymbol - Return the symbol for the specified jump table .set
/// FIXME: privatize to AsmPrinter.
MCSymbol *AsmPrinter::GetJTSetSymbol(unsigned UID, unsigned MBBID) const {
- SmallString<60> Name;
- raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix()
- << getFunctionNumber() << '_' << UID << "_set_" << MBBID;
- return OutContext.GetOrCreateSymbol(Name.str());
-}
-
-/// GetGlobalValueSymbol - Return the MCSymbol for the specified global
-/// value.
-MCSymbol *AsmPrinter::GetGlobalValueSymbol(const GlobalValue *GV) const {
- SmallString<60> NameStr;
- Mang->getNameWithPrefix(NameStr, GV, false);
- return OutContext.GetOrCreateSymbol(NameStr.str());
+ return OutContext.GetOrCreateTemporarySymbol
+ (Twine(MAI->getPrivateGlobalPrefix()) + Twine(getFunctionNumber()) + "_" +
+ Twine(UID) + "_set_" + Twine(MBBID));
}
/// GetSymbolWithGlobalValueBase - Return the MCSymbol for a symbol with
SmallString<60> NameStr;
Mang->getNameWithPrefix(NameStr, GV, ForcePrivate);
NameStr.append(Suffix.begin(), Suffix.end());
- return OutContext.GetOrCreateSymbol(NameStr.str());
+ if (!GV->hasPrivateLinkage() && !ForcePrivate)
+ return OutContext.GetOrCreateSymbol(NameStr.str());
+ return OutContext.GetOrCreateTemporarySymbol(NameStr.str());
}
/// GetExternalSymbolSymbol - Return the MCSymbol for the specified
const BasicBlock *BB = MBB->getBasicBlock();
if (VerboseAsm)
OutStreamer.AddComment("Address Taken");
- OutStreamer.EmitLabel(GetBlockAddressSymbol(BB->getParent(), BB));
+ OutStreamer.EmitLabel(GetBlockAddressSymbol(BB));
}
// Print the main label for the block.
- if (MBB->pred_empty() || MBB->isOnlyReachableByFallthrough()) {
+ if (MBB->pred_empty() || isBlockOnlyReachableByFallthrough(MBB)) {
if (VerboseAsm) {
// NOTE: Want this comment at start of line.
O << MAI->getCommentString() << " BB#" << MBB->getNumber() << ':';
PrintBasicBlockLoopComments(*MBB, LI, *this);
}
- OutStreamer.EmitLabel(MBB->getSymbol(OutContext));
+ OutStreamer.EmitLabel(MBB->getSymbol());
}
}
O << Offset;
}
+/// isBlockOnlyReachableByFallthough - Return true if the basic block has
+/// exactly one predecessor and the control transfer mechanism between
+/// the predecessor and this block is a fall-through.
+bool AsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB)
+ const {
+ // If this is a landing pad, it isn't a fall through. If it has no preds,
+ // then nothing falls through to it.
+ if (MBB->isLandingPad() || MBB->pred_empty())
+ return false;
+
+ // If there isn't exactly one predecessor, it can't be a fall through.
+ MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI;
+ ++PI2;
+ if (PI2 != MBB->pred_end())
+ return false;
+
+ // The predecessor has to be immediately before this block.
+ const MachineBasicBlock *Pred = *PI;
+
+ if (!Pred->isLayoutSuccessor(MBB))
+ return false;
+
+ // If the block is completely empty, then it definitely does fall through.
+ if (Pred->empty())
+ return true;
+
+ // Otherwise, check the last instruction.
+ const MachineInstr &LastInst = Pred->back();
+ return !LastInst.getDesc().isBarrier();
+}
+
+
+
GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy *S) {
if (!S->usesMetadata())
return 0;