Newer
Older
}
if (GV->getName() == "llvm.global_dtors") {
OutStreamer.SwitchSection(getObjFileLowering().getStaticDtorSection());
EmitAlignment(Align, 0);
EmitXXStructorList(GV->getInitializer());
if (TM.getRelocationModel() == Reloc::Static &&
MAI->hasStaticCtorDtorReferenceInStaticMode()) {
StringRef Sym(".destructors_used");
OutStreamer.EmitSymbolAttribute(OutContext.GetOrCreateSymbol(Sym),
MCSA_Reference);
return true;
}
return false;
}
/// EmitLLVMUsedList - For targets that define a MAI::UsedDirective, mark each
/// global in the specified llvm.used list for which emitUsedDirectiveFor
/// is true, as being used with this directive.
void AsmPrinter::EmitLLVMUsedList(Constant *List) {
ConstantArray *InitList = dyn_cast<ConstantArray>(List);
if (InitList == 0) return;
for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
Chris Lattner
committed
const GlobalValue *GV =
dyn_cast<GlobalValue>(InitList->getOperand(i)->stripPointerCasts());
if (GV && getObjFileLowering().shouldEmitUsedDirectiveFor(GV, Mang))
OutStreamer.EmitSymbolAttribute(Mang->getSymbol(GV), MCSA_NoDeadStrip);
}
}
/// EmitXXStructorList - Emit the ctor or dtor list. This just prints out the
/// function pointers, ignoring the init priority.
void AsmPrinter::EmitXXStructorList(Constant *List) {
// Should be an array of '{ int, void ()* }' structs. The first value is the
// init priority, which we ignore.
if (!isa<ConstantArray>(List)) return;
ConstantArray *InitList = cast<ConstantArray>(List);
for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i)
if (ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i))){
if (CS->getNumOperands() != 2) return; // Not array of 2-element structs.
if (CS->getOperand(1)->isNullValue())
return; // Found a null terminator, exit printing.
// Emit the function pointer.
EmitGlobalConstant(CS->getOperand(1));
}
}
Chris Lattner
committed
//===--------------------------------------------------------------------===//
// Emission and print routines
//
/// EmitInt8 - Emit a byte directive and value.
///
void AsmPrinter::EmitInt8(int Value) const {
OutStreamer.EmitIntValue(Value, 1, 0/*addrspace*/);
}
/// EmitInt16 - Emit a short directive and value.
///
void AsmPrinter::EmitInt16(int Value) const {
OutStreamer.EmitIntValue(Value, 2, 0/*addrspace*/);
}
/// EmitInt32 - Emit a long directive and value.
///
void AsmPrinter::EmitInt32(int Value) const {
OutStreamer.EmitIntValue(Value, 4, 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 = GetTempSymbol("set", SetCounter++);
OutStreamer.EmitAssignment(SetLabel, Diff);
OutStreamer.EmitSymbolValue(SetLabel, Size, 0/*AddrSpace*/);
}
//===----------------------------------------------------------------------===//
// EmitAlignment - Emit an alignment directive to the specified power of
// two boundary. For example, if you pass in 3 here, you will get an 8
// byte alignment. If a global value is specified, and if that global has
// an explicit alignment requested, it will unconditionally override the
// alignment request. However, if ForcedAlignBits is specified, this value
// has final say: the ultimate alignment will be the max of ForcedAlignBits
// and the alignment computed with NumBits and the global.
//
// The algorithm is:
// Align = NumBits;
// if (GV && GV->hasalignment) Align = GV->getalignment();
// Align = std::max(Align, ForcedAlignBits);
//
void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalValue *GV,
unsigned ForcedAlignBits,
bool UseFillExpr) const {
NumBits = Log2_32(GV->getAlignment());
NumBits = std::max(NumBits, ForcedAlignBits);
if (NumBits == 0) return; // No need to emit alignment.
Chris Lattner
committed
if (getCurrentSection()->getKind().isText())
OutStreamer.EmitCodeAlignment(1 << NumBits);
else
OutStreamer.EmitValueToAlignment(1 << NumBits, 0, 1, 0);
/// LowerConstant - Lower the specified LLVM Constant to an MCExpr.
///
static const MCExpr *LowerConstant(const Constant *CV, AsmPrinter &AP) {
MCContext &Ctx = AP.OutContext;
if (CV->isNullValue() || isa<UndefValue>(CV))
return MCConstantExpr::Create(0, Ctx);
if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV))
return MCConstantExpr::Create(CI->getZExtValue(), Ctx);
if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV))
return MCSymbolRefExpr::Create(AP.Mang->getSymbol(GV), Ctx);
if (const BlockAddress *BA = dyn_cast<BlockAddress>(CV))
return MCSymbolRefExpr::Create(AP.GetBlockAddressSymbol(BA), Ctx);
const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV);
if (CE == 0) {
llvm_unreachable("Unknown constant value to lower!");
return MCConstantExpr::Create(0, Ctx);
}
switch (CE->getOpcode()) {
default:
// If the code isn't optimized, there may be outstanding folding
// opportunities. Attempt to fold the expression using TargetData as a
// last resort before giving up.
if (Constant *C =
ConstantFoldConstantExpression(CE, AP.TM.getTargetData()))
if (C != CE)
return LowerConstant(C, AP);
#ifndef NDEBUG
CE->dump();
#endif
llvm_unreachable("FIXME: Don't support this constant expr");
case Instruction::GetElementPtr: {
const TargetData &TD = *AP.TM.getTargetData();
// Generate a symbolic expression for the byte address
const Constant *PtrVal = CE->getOperand(0);
SmallVector<Value*, 8> IdxVec(CE->op_begin()+1, CE->op_end());
int64_t Offset = TD.getIndexedOffset(PtrVal->getType(), &IdxVec[0],
IdxVec.size());
const MCExpr *Base = LowerConstant(CE->getOperand(0), AP);
if (Offset == 0)
return Base;
// Truncate/sext the offset to the pointer size.
if (TD.getPointerSizeInBits() != 64) {
int SExtAmount = 64-TD.getPointerSizeInBits();
Offset = (Offset << SExtAmount) >> SExtAmount;
return MCBinaryExpr::CreateAdd(Base, MCConstantExpr::Create(Offset, Ctx),
Ctx);
}
case Instruction::Trunc:
// We emit the value and depend on the assembler to truncate the generated
// expression properly. This is important for differences between
// blockaddress labels. Since the two labels are in the same function, it
// is reasonable to treat their delta as a 32-bit value.
// FALL THROUGH.
case Instruction::BitCast:
return LowerConstant(CE->getOperand(0), AP);
case Instruction::IntToPtr: {
const TargetData &TD = *AP.TM.getTargetData();
// Handle casts to pointers by changing them into casts to the appropriate
// integer type. This promotes constant folding and simplifies this code.
Constant *Op = CE->getOperand(0);
Op = ConstantExpr::getIntegerCast(Op, TD.getIntPtrType(CV->getContext()),
false/*ZExt*/);
return LowerConstant(Op, AP);
}
case Instruction::PtrToInt: {
const TargetData &TD = *AP.TM.getTargetData();
// Support only foldable casts to/from pointers that can be eliminated by
// changing the pointer to the appropriately sized integer type.
Constant *Op = CE->getOperand(0);
const Type *Ty = CE->getType();
const MCExpr *OpExpr = LowerConstant(Op, AP);
// We can emit the pointer value into this slot if the slot is an
// integer slot equal to the size of the pointer.
if (TD.getTypeAllocSize(Ty) == TD.getTypeAllocSize(Op->getType()))
return OpExpr;
// Otherwise the pointer is smaller than the resultant integer, mask off
// the high bits so we are sure to get a proper truncation if the input is
// a constant expr.
unsigned InBits = TD.getTypeAllocSizeInBits(Op->getType());
const MCExpr *MaskExpr = MCConstantExpr::Create(~0ULL >> (64-InBits), Ctx);
return MCBinaryExpr::CreateAnd(OpExpr, MaskExpr, Ctx);
}
// The MC library also has a right-shift operator, but it isn't consistently
// signed or unsigned between different targets.
case Instruction::Add:
case Instruction::Sub:
case Instruction::Mul:
case Instruction::SDiv:
case Instruction::SRem:
case Instruction::Shl:
case Instruction::And:
case Instruction::Or:
case Instruction::Xor: {
const MCExpr *LHS = LowerConstant(CE->getOperand(0), AP);
const MCExpr *RHS = LowerConstant(CE->getOperand(1), AP);
switch (CE->getOpcode()) {
default: llvm_unreachable("Unknown binary operator constant cast expr");
case Instruction::Add: return MCBinaryExpr::CreateAdd(LHS, RHS, Ctx);
case Instruction::Sub: return MCBinaryExpr::CreateSub(LHS, RHS, Ctx);
case Instruction::Mul: return MCBinaryExpr::CreateMul(LHS, RHS, Ctx);
case Instruction::SDiv: return MCBinaryExpr::CreateDiv(LHS, RHS, Ctx);
case Instruction::SRem: return MCBinaryExpr::CreateMod(LHS, RHS, Ctx);
case Instruction::Shl: return MCBinaryExpr::CreateShl(LHS, RHS, Ctx);
case Instruction::And: return MCBinaryExpr::CreateAnd(LHS, RHS, Ctx);
case Instruction::Or: return MCBinaryExpr::CreateOr (LHS, RHS, Ctx);
case Instruction::Xor: return MCBinaryExpr::CreateXor(LHS, RHS, Ctx);
}
static void EmitGlobalConstantArray(const ConstantArray *CA, unsigned AddrSpace,
AsmPrinter &AP) {
if (AddrSpace != 0 || !CA->isString()) {
// Not a string. Print the values in successive locations
for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i)
AP.EmitGlobalConstant(CA->getOperand(i), AddrSpace);
}
// Otherwise, it can be emitted as .ascii.
SmallVector<char, 128> TmpVec;
TmpVec.reserve(CA->getNumOperands());
for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i)
TmpVec.push_back(cast<ConstantInt>(CA->getOperand(i))->getZExtValue());
AP.OutStreamer.EmitBytes(StringRef(TmpVec.data(), TmpVec.size()), AddrSpace);
}
static void EmitGlobalConstantVector(const ConstantVector *CV,
unsigned AddrSpace, AsmPrinter &AP) {
for (unsigned i = 0, e = CV->getType()->getNumElements(); i != e; ++i)
AP.EmitGlobalConstant(CV->getOperand(i), AddrSpace);
}
static void EmitGlobalConstantStruct(const ConstantStruct *CS,
unsigned AddrSpace, AsmPrinter &AP) {
// Print the fields in successive locations. Pad to align if needed!
const TargetData *TD = AP.TM.getTargetData();
unsigned Size = TD->getTypeAllocSize(CS->getType());
const StructLayout *Layout = TD->getStructLayout(CS->getType());
uint64_t SizeSoFar = 0;
for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i) {
const Constant *Field = CS->getOperand(i);
// Check if padding is needed and insert one or more 0s.
uint64_t FieldSize = TD->getTypeAllocSize(Field->getType());
uint64_t PadSize = ((i == e-1 ? Size : Layout->getElementOffset(i+1))
- Layout->getElementOffset(i)) - FieldSize;
SizeSoFar += FieldSize + PadSize;
// Now print the actual field value.
AP.EmitGlobalConstant(Field, AddrSpace);
// Insert padding - this may include padding to increase the size of the
// current field up to the ABI size (if the struct is not packed) as well
// as padding to ensure that the next field starts at the right offset.
AP.OutStreamer.EmitZeros(PadSize, AddrSpace);
}
assert(SizeSoFar == Layout->getSizeInBytes() &&
"Layout of constant struct may be incorrect!");
}
static void EmitGlobalConstantUnion(const ConstantUnion *CU,
unsigned AddrSpace, AsmPrinter &AP) {
const TargetData *TD = AP.TM.getTargetData();
unsigned Size = TD->getTypeAllocSize(CU->getType());
const Constant *Contents = CU->getOperand(0);
unsigned FilledSize = TD->getTypeAllocSize(Contents->getType());
// Print the actually filled part
AP.EmitGlobalConstant(Contents, AddrSpace);
// And pad with enough zeroes
AP.OutStreamer.EmitZeros(Size-FilledSize, AddrSpace);
}
static void EmitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace,
AsmPrinter &AP) {
// FP Constants are printed as integer constants to avoid losing
// precision.
if (CFP->getType()->isDoubleTy()) {
if (AP.isVerbose()) {
double Val = CFP->getValueAPF().convertToDouble();
AP.OutStreamer.GetCommentOS() << "double " << Val << '\n';
uint64_t Val = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
AP.OutStreamer.EmitIntValue(Val, 8, AddrSpace);
return;
}
if (CFP->getType()->isFloatTy()) {
if (AP.isVerbose()) {
float Val = CFP->getValueAPF().convertToFloat();
AP.OutStreamer.GetCommentOS() << "float " << Val << '\n';
uint64_t Val = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
AP.OutStreamer.EmitIntValue(Val, 4, AddrSpace);
return;
}
if (CFP->getType()->isX86_FP80Ty()) {
// all long double variants are printed as hex
// API needed to prevent premature destruction
APInt API = CFP->getValueAPF().bitcastToAPInt();
const uint64_t *p = API.getRawData();
if (AP.isVerbose()) {
// Convert to double so we can print the approximate val as a comment.
APFloat DoubleVal = CFP->getValueAPF();
bool ignored;
DoubleVal.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven,
&ignored);
AP.OutStreamer.GetCommentOS() << "x86_fp80 ~= "
<< DoubleVal.convertToDouble() << '\n';
if (AP.TM.getTargetData()->isBigEndian()) {
AP.OutStreamer.EmitIntValue(p[1], 2, AddrSpace);
AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace);
AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace);
AP.OutStreamer.EmitIntValue(p[1], 2, AddrSpace);
}
// Emit the tail padding for the long double.
const TargetData &TD = *AP.TM.getTargetData();
AP.OutStreamer.EmitZeros(TD.getTypeAllocSize(CFP->getType()) -
TD.getTypeStoreSize(CFP->getType()), AddrSpace);
return;
}
assert(CFP->getType()->isPPC_FP128Ty() &&
"Floating point constant type not handled");
// All long double variants are printed as hex
// API needed to prevent premature destruction.
APInt API = CFP->getValueAPF().bitcastToAPInt();
const uint64_t *p = API.getRawData();
if (AP.TM.getTargetData()->isBigEndian()) {
AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace);
AP.OutStreamer.EmitIntValue(p[1], 8, AddrSpace);
AP.OutStreamer.EmitIntValue(p[1], 8, AddrSpace);
AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace);
}
static void EmitGlobalConstantLargeInt(const ConstantInt *CI,
unsigned AddrSpace, AsmPrinter &AP) {
const TargetData *TD = AP.TM.getTargetData();
unsigned BitWidth = CI->getBitWidth();
assert((BitWidth & 63) == 0 && "only support multiples of 64-bits");
// We don't expect assemblers to support integer data directives
// for more than 64 bits, so we emit the data in at most 64-bit
// quantities at a time.
const uint64_t *RawData = CI->getValue().getRawData();
for (unsigned i = 0, e = BitWidth / 64; i != e; ++i) {
uint64_t Val = TD->isBigEndian() ? RawData[e - i - 1] : RawData[i];
AP.OutStreamer.EmitIntValue(Val, 8, AddrSpace);
}
}
/// EmitGlobalConstant - Print a general LLVM constant to the .s file.
Sanjiv Gupta
committed
void AsmPrinter::EmitGlobalConstant(const Constant *CV, unsigned AddrSpace) {
if (isa<ConstantAggregateZero>(CV) || isa<UndefValue>(CV)) {
uint64_t Size = TM.getTargetData()->getTypeAllocSize(CV->getType());
if (Size == 0) Size = 1; // An empty "_foo:" followed by a section is undef.
return OutStreamer.EmitZeros(Size, AddrSpace);
}
if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
unsigned Size = TM.getTargetData()->getTypeAllocSize(CV->getType());
switch (Size) {
case 1:
case 2:
case 4:
case 8:
if (isVerbose())
OutStreamer.GetCommentOS() << format("0x%llx\n", CI->getZExtValue());
OutStreamer.EmitIntValue(CI->getZExtValue(), Size, AddrSpace);
return;
default:
EmitGlobalConstantLargeInt(CI, AddrSpace, *this);
return;
}
}
if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV))
return EmitGlobalConstantArray(CVA, AddrSpace, *this);
if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV))
return EmitGlobalConstantStruct(CVS, AddrSpace, *this);
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV))
return EmitGlobalConstantFP(CFP, AddrSpace, *this);
if (isa<ConstantPointerNull>(CV)) {
unsigned Size = TM.getTargetData()->getTypeAllocSize(CV->getType());
OutStreamer.EmitIntValue(0, Size, AddrSpace);
return;
}
if (const ConstantUnion *CVU = dyn_cast<ConstantUnion>(CV))
return EmitGlobalConstantUnion(CVU, AddrSpace, *this);
if (const ConstantVector *V = dyn_cast<ConstantVector>(CV))
return EmitGlobalConstantVector(V, AddrSpace, *this);
// Otherwise, it must be a ConstantExpr. Lower it to an MCExpr, then emit it
// thread the streamer with EmitValue.
OutStreamer.EmitValue(LowerConstant(CV, *this),
TM.getTargetData()->getTypeAllocSize(CV->getType()),
AddrSpace);
void AsmPrinter::EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
// Target doesn't support this yet!
llvm_unreachable("Target does not support EmitMachineConstantPoolValue");
}
void AsmPrinter::printOffset(int64_t Offset, raw_ostream &OS) const {
if (Offset > 0)
OS << '+' << Offset;
else if (Offset < 0)
OS << Offset;
}
//===----------------------------------------------------------------------===//
// Symbol Lowering Routines.
//===----------------------------------------------------------------------===//
/// GetTempSymbol - Return the MCSymbol corresponding to the assembler
/// temporary label with the specified stem and unique ID.
MCSymbol *AsmPrinter::GetTempSymbol(StringRef Name, unsigned ID) const {
return OutContext.GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) +
Name + Twine(ID));
}
/// GetTempSymbol - Return an assembler temporary label with the specified
/// stem.
MCSymbol *AsmPrinter::GetTempSymbol(StringRef Name) const {
return OutContext.GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix())+
Name);
}
MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BlockAddress *BA) const {
return MMI->getAddrLabelSymbol(BA->getBasicBlock());
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 {
return OutContext.GetOrCreateSymbol
(Twine(MAI->getPrivateGlobalPrefix()) + "CPI" + Twine(getFunctionNumber())
+ "_" + Twine(CPID));
}
/// GetJTISymbol - Return the symbol for the specified jump table entry.
MCSymbol *AsmPrinter::GetJTISymbol(unsigned JTID, bool isLinkerPrivate) const {
return MF->getJTISymbol(JTID, OutContext, isLinkerPrivate);
}
/// GetJTSetSymbol - Return the symbol for the specified jump table .set
/// FIXME: privatize to AsmPrinter.
MCSymbol *AsmPrinter::GetJTSetSymbol(unsigned UID, unsigned MBBID) const {
return OutContext.GetOrCreateSymbol
(Twine(MAI->getPrivateGlobalPrefix()) + Twine(getFunctionNumber()) + "_" +
Twine(UID) + "_set_" + Twine(MBBID));
/// GetSymbolWithGlobalValueBase - Return the MCSymbol for a symbol with
/// global value name as its base, with the specified suffix, and where the
/// symbol is forced to have private linkage if ForcePrivate is true.
MCSymbol *AsmPrinter::GetSymbolWithGlobalValueBase(const GlobalValue *GV,
StringRef Suffix,
bool ForcePrivate) const {
Mang->getNameWithPrefix(NameStr, GV, ForcePrivate);
return OutContext.GetOrCreateSymbol(NameStr.str());
/// GetExternalSymbolSymbol - Return the MCSymbol for the specified
/// ExternalSymbol.
MCSymbol *AsmPrinter::GetExternalSymbolSymbol(StringRef Sym) const {
SmallString<60> NameStr;
Mang->getNameWithPrefix(NameStr, Sym);
return OutContext.GetOrCreateSymbol(NameStr.str());
}
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
/// PrintParentLoopComment - Print comments about parent loops of this one.
static void PrintParentLoopComment(raw_ostream &OS, const MachineLoop *Loop,
unsigned FunctionNumber) {
if (Loop == 0) return;
PrintParentLoopComment(OS, Loop->getParentLoop(), FunctionNumber);
OS.indent(Loop->getLoopDepth()*2)
<< "Parent Loop BB" << FunctionNumber << "_"
<< Loop->getHeader()->getNumber()
<< " Depth=" << Loop->getLoopDepth() << '\n';
}
/// PrintChildLoopComment - Print comments about child loops within
/// the loop for this basic block, with nesting.
static void PrintChildLoopComment(raw_ostream &OS, const MachineLoop *Loop,
unsigned FunctionNumber) {
// Add child loop information
for (MachineLoop::iterator CL = Loop->begin(), E = Loop->end();CL != E; ++CL){
OS.indent((*CL)->getLoopDepth()*2)
<< "Child Loop BB" << FunctionNumber << "_"
<< (*CL)->getHeader()->getNumber() << " Depth " << (*CL)->getLoopDepth()
<< '\n';
PrintChildLoopComment(OS, *CL, FunctionNumber);
}
}
/// EmitBasicBlockLoopComments - Pretty-print comments for basic blocks.
static void EmitBasicBlockLoopComments(const MachineBasicBlock &MBB,
const MachineLoopInfo *LI,
const AsmPrinter &AP) {
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
// Add loop depth information
const MachineLoop *Loop = LI->getLoopFor(&MBB);
if (Loop == 0) return;
MachineBasicBlock *Header = Loop->getHeader();
assert(Header && "No header for loop");
// If this block is not a loop header, just print out what is the loop header
// and return.
if (Header != &MBB) {
AP.OutStreamer.AddComment(" in Loop: Header=BB" +
Twine(AP.getFunctionNumber())+"_" +
Twine(Loop->getHeader()->getNumber())+
" Depth="+Twine(Loop->getLoopDepth()));
return;
}
// Otherwise, it is a loop header. Print out information about child and
// parent loops.
raw_ostream &OS = AP.OutStreamer.GetCommentOS();
PrintParentLoopComment(OS, Loop->getParentLoop(), AP.getFunctionNumber());
OS << "=>";
OS.indent(Loop->getLoopDepth()*2-2);
OS << "This ";
if (Loop->empty())
OS << "Inner ";
OS << "Loop Header: Depth=" + Twine(Loop->getLoopDepth()) << '\n';
PrintChildLoopComment(OS, Loop, AP.getFunctionNumber());
}
/// EmitBasicBlockStart - This method prints the label for the specified
/// MachineBasicBlock, an alignment (if present) and a comment describing
/// it if appropriate.
void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock *MBB) const {
// Emit an alignment directive for this block, if needed.
if (unsigned Align = MBB->getAlignment())
EmitAlignment(Log2_32(Align));
Evan Cheng
committed
// If the block has its address taken, emit any labels that were used to
// reference the block. It is possible that there is more than one label
// here, because multiple LLVM BB's may have been RAUW'd to this block after
// the references were generated.
if (MBB->hasAddressTaken()) {
const BasicBlock *BB = MBB->getBasicBlock();
if (isVerbose())
OutStreamer.AddComment("Block address taken");
std::vector<MCSymbol*> Syms = MMI->getAddrLabelSymbolToEmit(BB);
for (unsigned i = 0, e = Syms.size(); i != e; ++i)
OutStreamer.EmitLabel(Syms[i]);
if (MBB->pred_empty() || isBlockOnlyReachableByFallthrough(MBB)) {
if (isVerbose() && OutStreamer.hasRawTextSupport()) {
if (const BasicBlock *BB = MBB->getBasicBlock())
if (BB->hasName())
OutStreamer.AddComment("%" + BB->getName());
// NOTE: Want this comment at start of line, don't emit with AddComment.
OutStreamer.EmitRawText(Twine(MAI->getCommentString()) + " BB#" +
Twine(MBB->getNumber()) + ":");
if (isVerbose()) {
if (const BasicBlock *BB = MBB->getBasicBlock())
if (BB->hasName())
OutStreamer.AddComment("%" + BB->getName());
OutStreamer.EmitLabel(MBB->getSymbol());
}
void AsmPrinter::EmitVisibility(MCSymbol *Sym, unsigned Visibility) const {
MCSymbolAttr Attr = MCSA_Invalid;
switch (Visibility) {
default: break;
case GlobalValue::HiddenVisibility:
Attr = MAI->getHiddenVisibilityAttr();
break;
case GlobalValue::ProtectedVisibility:
Attr = MAI->getProtectedVisibilityAttr();
break;
if (Attr != MCSA_Invalid)
OutStreamer.EmitSymbolAttribute(Sym, Attr);
}
/// 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 {
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
// 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())
Gordon Henriksen
committed
return 0;
gcp_map_type &GCMap = getGCMap(GCMetadataPrinters);
gcp_map_type::iterator GCPI = GCMap.find(S);
if (GCPI != GCMap.end())
Gordon Henriksen
committed
return GCPI->second;
const char *Name = S->getName().c_str();
Gordon Henriksen
committed
for (GCMetadataPrinterRegistry::iterator
I = GCMetadataPrinterRegistry::begin(),
E = GCMetadataPrinterRegistry::end(); I != E; ++I)
if (strcmp(Name, I->getName()) == 0) {
GCMetadataPrinter *GMP = I->instantiate();
GMP->S = S;
GCMap.insert(std::make_pair(S, GMP));
return GMP;
Gordon Henriksen
committed
}
llvm_report_error("no GCMetadataPrinter registered for GC: " + Twine(Name));
return 0;
Gordon Henriksen
committed
}