aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp')
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp155
1 files changed, 127 insertions, 28 deletions
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 7f314eed3ae6..1999f3608788 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -33,7 +33,6 @@
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/Mangler.h"
-#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetLowering.h"
@@ -45,6 +44,7 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Timer.h"
using namespace llvm;
@@ -290,10 +290,10 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
// Handle common and BSS local symbols (.lcomm).
if (GVKind.isCommon() || GVKind.isBSSLocal()) {
if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
+ unsigned Align = 1 << AlignLog;
// Handle common symbols.
if (GVKind.isCommon()) {
- unsigned Align = 1 << AlignLog;
if (!getObjFileLowering().getCommDirectiveSupportsAlignment())
Align = 0;
@@ -307,17 +307,17 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
const MCSection *TheSection =
getObjFileLowering().SectionForGlobal(GV, GVKind, Mang, TM);
// .zerofill __DATA, __bss, _foo, 400, 5
- OutStreamer.EmitZerofill(TheSection, GVSym, Size, 1 << AlignLog);
+ OutStreamer.EmitZerofill(TheSection, GVSym, Size, Align);
return;
}
- if (MAI->hasLCOMMDirective()) {
+ if (MAI->getLCOMMDirectiveType() != LCOMM::None &&
+ (MAI->getLCOMMDirectiveType() != LCOMM::NoAlignment || Align == 1)) {
// .lcomm _foo, 42
- OutStreamer.EmitLocalCommonSymbol(GVSym, Size);
+ OutStreamer.EmitLocalCommonSymbol(GVSym, Size, Align);
return;
}
- unsigned Align = 1 << AlignLog;
if (!getObjFileLowering().getCommDirectiveSupportsAlignment())
Align = 0;
@@ -474,8 +474,10 @@ void AsmPrinter::EmitFunctionHeader() {
void AsmPrinter::EmitFunctionEntryLabel() {
// The function label could have already been emitted if two symbols end up
// conflicting due to asm renaming. Detect this and emit an error.
- if (CurrentFnSym->isUndefined())
+ if (CurrentFnSym->isUndefined()) {
+ OutStreamer.ForceCodeRegion();
return OutStreamer.EmitLabel(CurrentFnSym);
+ }
report_fatal_error("'" + Twine(CurrentFnSym->getName()) +
"' label emitted multiple times to assembly file");
@@ -620,6 +622,9 @@ void AsmPrinter::emitPrologLabel(const MachineInstr &MI) {
if (needsCFIMoves() == CFI_M_None)
return;
+ if (MMI->getCompactUnwindEncoding() != 0)
+ OutStreamer.EmitCompactUnwindEncoding(MMI->getCompactUnwindEncoding());
+
MachineModuleInfo &MMI = MF->getMMI();
std::vector<MachineMove> &Moves = MMI.getFrameMoves();
bool FoundOne = false;
@@ -878,7 +883,7 @@ bool AsmPrinter::doFinalization(Module &M) {
I != E; ++I) {
MCSymbol *Name = Mang->getSymbol(I);
- const GlobalValue *GV = cast<GlobalValue>(I->getAliasedGlobal());
+ const GlobalValue *GV = I->getAliasedGlobal();
MCSymbol *Target = Mang->getSymbol(GV);
if (I->hasExternalLinkage() || !MAI->getWeakRefDirective())
@@ -1009,7 +1014,7 @@ void AsmPrinter::EmitConstantPool() {
unsigned NewOffset = (Offset + AlignMask) & ~AlignMask;
OutStreamer.EmitFill(NewOffset - Offset, 0/*fillval*/, 0/*addrspace*/);
- const Type *Ty = CPE.getType();
+ Type *Ty = CPE.getType();
Offset = NewOffset + TM.getTargetData()->getTypeAllocSize(Ty);
OutStreamer.EmitLabel(GetCPISymbol(CPI));
@@ -1055,6 +1060,15 @@ void AsmPrinter::EmitJumpTableInfo() {
EmitAlignment(Log2_32(MJTI->getEntryAlignment(*TM.getTargetData())));
+ // If we know the form of the jump table, go ahead and tag it as such.
+ if (!JTInDiffSection) {
+ if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32) {
+ OutStreamer.EmitJumpTable32Region();
+ } else {
+ OutStreamer.EmitDataRegion();
+ }
+ }
+
for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) {
const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
@@ -1226,22 +1240,53 @@ void AsmPrinter::EmitLLVMUsedList(const Constant *List) {
}
}
-/// EmitXXStructorList - Emit the ctor or dtor list. This just prints out the
-/// function pointers, ignoring the init priority.
+typedef std::pair<int, Constant*> Structor;
+
+static bool priority_order(const Structor& lhs, const Structor& rhs) {
+ return lhs.first < rhs.first;
+}
+
+/// EmitXXStructorList - Emit the ctor or dtor list taking into account the init
+/// priority.
void AsmPrinter::EmitXXStructorList(const Constant *List) {
// Should be an array of '{ int, void ()* }' structs. The first value is the
- // init priority, which we ignore.
+ // init priority.
if (!isa<ConstantArray>(List)) return;
- const 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));
- }
+
+ // Sanity check the structors list.
+ const ConstantArray *InitList = dyn_cast<ConstantArray>(List);
+ if (!InitList) return; // Not an array!
+ StructType *ETy = dyn_cast<StructType>(InitList->getType()->getElementType());
+ if (!ETy || ETy->getNumElements() != 2) return; // Not an array of pairs!
+ if (!isa<IntegerType>(ETy->getTypeAtIndex(0U)) ||
+ !isa<PointerType>(ETy->getTypeAtIndex(1U))) return; // Not (int, ptr).
+
+ // Gather the structors in a form that's convenient for sorting by priority.
+ SmallVector<Structor, 8> Structors;
+ for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
+ ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i));
+ if (!CS) continue; // Malformed.
+ if (CS->getOperand(1)->isNullValue())
+ break; // Found a null terminator, skip the rest.
+ ConstantInt *Priority = dyn_cast<ConstantInt>(CS->getOperand(0));
+ if (!Priority) continue; // Malformed.
+ Structors.push_back(std::make_pair(Priority->getLimitedValue(65535),
+ CS->getOperand(1)));
+ }
+
+ // Emit the function pointers in reverse priority order.
+ switch (MAI->getStructorOutputOrder()) {
+ case Structors::None:
+ break;
+ case Structors::PriorityOrder:
+ std::sort(Structors.begin(), Structors.end(), priority_order);
+ break;
+ case Structors::ReversePriorityOrder:
+ std::sort(Structors.rbegin(), Structors.rend(), priority_order);
+ break;
+ }
+ for (unsigned i = 0, e = Structors.size(); i != e; ++i)
+ EmitGlobalConstant(Structors[i].second);
}
//===--------------------------------------------------------------------===//
@@ -1406,8 +1451,7 @@ static const MCExpr *LowerConstant(const Constant *CV, AsmPrinter &AP) {
// 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());
+ int64_t Offset = TD.getIndexedOffset(PtrVal->getType(), IdxVec);
const MCExpr *Base = LowerConstant(CE->getOperand(0), AP);
if (Offset == 0)
@@ -1447,7 +1491,7 @@ static const MCExpr *LowerConstant(const Constant *CV, AsmPrinter &AP) {
// 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();
+ Type *Ty = CE->getType();
const MCExpr *OpExpr = LowerConstant(Op, AP);
@@ -1496,12 +1540,67 @@ static const MCExpr *LowerConstant(const Constant *CV, AsmPrinter &AP) {
static void EmitGlobalConstantImpl(const Constant *C, unsigned AddrSpace,
AsmPrinter &AP);
+/// isRepeatedByteSequence - Determine whether the given value is
+/// composed of a repeated sequence of identical bytes and return the
+/// byte value. If it is not a repeated sequence, return -1.
+static int isRepeatedByteSequence(const Value *V, TargetMachine &TM) {
+
+ if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
+ if (CI->getBitWidth() > 64) return -1;
+
+ uint64_t Size = TM.getTargetData()->getTypeAllocSize(V->getType());
+ uint64_t Value = CI->getZExtValue();
+
+ // Make sure the constant is at least 8 bits long and has a power
+ // of 2 bit width. This guarantees the constant bit width is
+ // always a multiple of 8 bits, avoiding issues with padding out
+ // to Size and other such corner cases.
+ if (CI->getBitWidth() < 8 || !isPowerOf2_64(CI->getBitWidth())) return -1;
+
+ uint8_t Byte = static_cast<uint8_t>(Value);
+
+ for (unsigned i = 1; i < Size; ++i) {
+ Value >>= 8;
+ if (static_cast<uint8_t>(Value) != Byte) return -1;
+ }
+ return Byte;
+ }
+ if (const ConstantArray *CA = dyn_cast<ConstantArray>(V)) {
+ // Make sure all array elements are sequences of the same repeated
+ // byte.
+ if (CA->getNumOperands() == 0) return -1;
+
+ int Byte = isRepeatedByteSequence(CA->getOperand(0), TM);
+ if (Byte == -1) return -1;
+
+ for (unsigned i = 1, e = CA->getNumOperands(); i != e; ++i) {
+ int ThisByte = isRepeatedByteSequence(CA->getOperand(i), TM);
+ if (ThisByte == -1) return -1;
+ if (Byte != ThisByte) return -1;
+ }
+ return Byte;
+ }
+
+ return -1;
+}
+
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)
- EmitGlobalConstantImpl(CA->getOperand(i), AddrSpace, AP);
+ // Not a string. Print the values in successive locations.
+
+ // See if we can aggregate some values. Make sure it can be
+ // represented as a series of bytes of the constant value.
+ int Value = isRepeatedByteSequence(CA, AP.TM);
+
+ if (Value != -1) {
+ uint64_t Bytes = AP.TM.getTargetData()->getTypeAllocSize(CA->getType());
+ AP.OutStreamer.EmitFill(Bytes, Value, AddrSpace);
+ }
+ else {
+ for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i)
+ EmitGlobalConstantImpl(CA->getOperand(i), AddrSpace, AP);
+ }
return;
}