#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
: MachineFunctionPass(&ID), O(o),
TM(tm), MAI(T), TRI(tm.getRegisterInfo()),
OutContext(Ctx), OutStreamer(Streamer),
- LastMI(0), LastFn(0), Counter(~0U), PrevDLT(NULL) {
+ LastMI(0), LastFn(0), Counter(~0U), SetCounter(0), PrevDLT(NULL) {
DW = 0; MMI = 0;
VerboseAsm = Streamer.isVerboseAsm();
}
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();
}
+/// EmitComments - Pretty-print comments for instructions.
+static void EmitComments(const MachineInstr &MI, raw_ostream &CommentOS) {
+ const MachineFunction *MF = MI.getParent()->getParent();
+ const TargetMachine &TM = MF->getTarget();
+
+ if (!MI.getDebugLoc().isUnknown()) {
+ DILocation DLT = MF->getDILocation(MI.getDebugLoc());
+
+ // Print source line info.
+ DIScope Scope = DLT.getScope();
+ // Omit the directory, because it's likely to be long and uninteresting.
+ if (Scope.Verify())
+ CommentOS << Scope.getFilename();
+ else
+ CommentOS << "<unknown>";
+ CommentOS << ':' << DLT.getLineNumber();
+ if (DLT.getColumnNumber() != 0)
+ CommentOS << ':' << DLT.getColumnNumber();
+ CommentOS << '\n';
+ }
+
+ // Check for spills and reloads
+ int FI;
+
+ const MachineFrameInfo *FrameInfo = MF->getFrameInfo();
+
+ // We assume a single instruction only has a spill or reload, not
+ // both.
+ const MachineMemOperand *MMO;
+ if (TM.getInstrInfo()->isLoadFromStackSlotPostFE(&MI, FI)) {
+ if (FrameInfo->isSpillSlotObjectIndex(FI)) {
+ MMO = *MI.memoperands_begin();
+ CommentOS << MMO->getSize() << "-byte Reload\n";
+ }
+ } else if (TM.getInstrInfo()->hasLoadFromStackSlot(&MI, MMO, FI)) {
+ if (FrameInfo->isSpillSlotObjectIndex(FI))
+ CommentOS << MMO->getSize() << "-byte Folded Reload\n";
+ } else if (TM.getInstrInfo()->isStoreToStackSlotPostFE(&MI, FI)) {
+ if (FrameInfo->isSpillSlotObjectIndex(FI)) {
+ MMO = *MI.memoperands_begin();
+ CommentOS << MMO->getSize() << "-byte Spill\n";
+ }
+ } else if (TM.getInstrInfo()->hasStoreToStackSlot(&MI, MMO, FI)) {
+ if (FrameInfo->isSpillSlotObjectIndex(FI))
+ CommentOS << MMO->getSize() << "-byte Folded Spill\n";
+ }
+
+ // Check for spill-induced copies
+ unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
+ if (TM.getInstrInfo()->isMoveInstr(MI, SrcReg, DstReg,
+ SrcSubIdx, DstSubIdx)) {
+ if (MI.getAsmPrinterFlag(MachineInstr::ReloadReuse))
+ CommentOS << " Reload Reuse\n";
+ }
+}
+
+
+
/// EmitFunctionBody - This method emits the body and trailer for a
/// function.
void AsmPrinter::EmitFunctionBody() {
// FIXME: Clean up processDebugLoc.
processDebugLoc(II, true);
+ if (VerboseAsm)
+ EmitComments(*II, OutStreamer.GetCommentOS());
+
switch (II->getOpcode()) {
- case TargetInstrInfo::DBG_LABEL:
- case TargetInstrInfo::EH_LABEL:
- case TargetInstrInfo::GC_LABEL:
- printLabel(II);
+ case TargetOpcode::DBG_LABEL:
+ case TargetOpcode::EH_LABEL:
+ case TargetOpcode::GC_LABEL:
+ printLabelInst(II);
break;
- case TargetInstrInfo::INLINEASM:
+ case TargetOpcode::INLINEASM:
printInlineAsm(II);
break;
- case TargetInstrInfo::IMPLICIT_DEF:
+ case TargetOpcode::IMPLICIT_DEF:
printImplicitDef(II);
break;
- case TargetInstrInfo::KILL:
+ case TargetOpcode::KILL:
printKill(II);
break;
default:
EmitInstruction(II);
break;
}
- if (VerboseAsm)
- EmitComments(*II);
- O << '\n';
// FIXME: Clean up processDebugLoc.
processDebugLoc(II, false);
// Print out jump tables referenced by the function.
EmitJumpTableInfo();
+
+ OutStreamer.AddBlankLine();
}
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.GetOrCreateSymbol(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.
}
switch (CE->getOpcode()) {
- case Instruction::ZExt:
- case Instruction::SExt:
- case Instruction::FPTrunc:
- case Instruction::FPExt:
- case Instruction::UIToFP:
- case Instruction::SIToFP:
- case Instruction::FPToUI:
- case Instruction::FPToSI:
- default: llvm_unreachable("FIXME: Don't support this constant cast expr");
+ 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
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: {
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);
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 (DL.isUnknown())
return;
DILocation CurDLT = MF->getDILocation(DL);
- if (CurDLT.getScope().isNull())
+ if (!CurDLT.getScope().Verify())
return;
if (!BeforePrintingInsn) {
}
}
O << "\n\t" << MAI->getCommentString() << MAI->getInlineAsmEnd();
+ OutStreamer.AddBlankLine();
}
/// printImplicitDef - This method prints the specified machine instruction
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString() << " implicit-def: "
<< TRI->getName(MI->getOperand(0).getReg());
+ OutStreamer.AddBlankLine();
}
void AsmPrinter::printKill(const MachineInstr *MI) const {
assert(op.isReg() && "KILL instruction must have only register operands");
O << ' ' << TRI->getName(op.getReg()) << (op.isDef() ? "<def>" : "<kill>");
}
+ OutStreamer.AddBlankLine();
}
/// printLabel - This method prints a local label used by debug and
/// exception handling tables.
-void AsmPrinter::printLabel(const MachineInstr *MI) const {
+void AsmPrinter::printLabelInst(const MachineInstr *MI) const {
printLabel(MI->getOperand(0).getImm());
+ OutStreamer.AddBlankLine();
}
void AsmPrinter::printLabel(unsigned Id) const {
return true;
}
-MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BlockAddress *BA,
- const char *Suffix) const {
- return GetBlockAddressSymbol(BA->getFunction(), BA->getBasicBlock(), Suffix);
+MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BlockAddress *BA) const {
+ return GetBlockAddressSymbol(BA->getFunction(), BA->getBasicBlock());
}
MCSymbol *AsmPrinter::GetBlockAddressSymbol(const Function *F,
- const BasicBlock *BB,
- const char *Suffix) const {
+ const BasicBlock *BB) const {
assert(BB->hasName() &&
"Address of anonymous basic block not supported yet!");
SmallString<60> NameResult;
Mang->getNameWithPrefix(NameResult,
StringRef("BA") + Twine((unsigned)FnName.size()) +
- "_" + FnName.str() + "_" + BB->getName() + Suffix,
+ "_" + FnName.str() + "_" + BB->getName(),
Mangler::Private);
return OutContext.GetOrCreateSymbol(NameResult.str());
}
}
-/// EmitComments - Pretty-print comments for basic blocks.
+/// PrintBasicBlockLoopComments - Pretty-print comments for basic blocks.
static void PrintBasicBlockLoopComments(const MachineBasicBlock &MBB,
const MachineLoopInfo *LI,
const AsmPrinter &AP) {
}
// 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() << ':';
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;
return 0;
}
-/// EmitComments - Pretty-print comments for instructions
-void AsmPrinter::EmitComments(const MachineInstr &MI) const {
- if (!VerboseAsm)
- return;
-
- bool Newline = false;
-
- if (!MI.getDebugLoc().isUnknown()) {
- DILocation DLT = MF->getDILocation(MI.getDebugLoc());
-
- // Print source line info.
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << ' ';
- DIScope Scope = DLT.getScope();
- // Omit the directory, because it's likely to be long and uninteresting.
- if (!Scope.isNull())
- O << Scope.getFilename();
- else
- O << "<unknown>";
- O << ':' << DLT.getLineNumber();
- if (DLT.getColumnNumber() != 0)
- O << ':' << DLT.getColumnNumber();
- Newline = true;
- }
-
- // Check for spills and reloads
- int FI;
-
- const MachineFrameInfo *FrameInfo =
- MI.getParent()->getParent()->getFrameInfo();
-
- // We assume a single instruction only has a spill or reload, not
- // both.
- const MachineMemOperand *MMO;
- if (TM.getInstrInfo()->isLoadFromStackSlotPostFE(&MI, FI)) {
- if (FrameInfo->isSpillSlotObjectIndex(FI)) {
- MMO = *MI.memoperands_begin();
- if (Newline) O << '\n';
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << ' ' << MMO->getSize() << "-byte Reload";
- Newline = true;
- }
- }
- else if (TM.getInstrInfo()->hasLoadFromStackSlot(&MI, MMO, FI)) {
- if (FrameInfo->isSpillSlotObjectIndex(FI)) {
- if (Newline) O << '\n';
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << ' '
- << MMO->getSize() << "-byte Folded Reload";
- Newline = true;
- }
- }
- else if (TM.getInstrInfo()->isStoreToStackSlotPostFE(&MI, FI)) {
- if (FrameInfo->isSpillSlotObjectIndex(FI)) {
- MMO = *MI.memoperands_begin();
- if (Newline) O << '\n';
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << ' ' << MMO->getSize() << "-byte Spill";
- Newline = true;
- }
- }
- else if (TM.getInstrInfo()->hasStoreToStackSlot(&MI, MMO, FI)) {
- if (FrameInfo->isSpillSlotObjectIndex(FI)) {
- if (Newline) O << '\n';
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << ' '
- << MMO->getSize() << "-byte Folded Spill";
- Newline = true;
- }
- }
-
- // Check for spill-induced copies
- unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
- if (TM.getInstrInfo()->isMoveInstr(MI, SrcReg, DstReg,
- SrcSubIdx, DstSubIdx)) {
- if (MI.getAsmPrinterFlag(ReloadReuse)) {
- if (Newline) O << '\n';
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << " Reload Reuse";
- }
- }
-}
-