#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Timer.h"
#include "llvm/Target/Mangler.h"
+#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetRegisterInfo.h"
using namespace llvm;
-static const char *DWARFGroupName = "DWARF Emission";
-static const char *DbgTimerName = "DWARF Debug Writer";
-static const char *EHTimerName = "DWARF Exception Writer";
+static const char *const DWARFGroupName = "DWARF Emission";
+static const char *const DbgTimerName = "DWARF Debug Writer";
+static const char *const EHTimerName = "DWARF Exception Writer";
STATISTIC(EmittedInsts, "Number of machine instrs printed");
AsmPrinter::AsmPrinter(TargetMachine &tm, MCStreamer &Streamer)
: MachineFunctionPass(ID),
- TM(tm), MAI(tm.getMCAsmInfo()),
+ TM(tm), MAI(tm.getMCAsmInfo()), MII(tm.getInstrInfo()),
OutContext(Streamer.getContext()),
OutStreamer(Streamer),
LastMI(0), LastFn(0), Counter(~0U), SetCounter(0) {
- DD = 0; DE = 0; MMI = 0; LI = 0;
+ DD = 0; DE = 0; MMI = 0; LI = 0; MF = 0;
CurrentFnSym = CurrentFnSymForSize = 0;
GCMetadataPrinters = 0;
VerboseAsm = Streamer.isVerboseAsm();
}
bool AsmPrinter::doInitialization(Module &M) {
- OutStreamer.InitStreamer();
-
MMI = getAnalysisIfAvailable<MachineModuleInfo>();
MMI->AnalyzeModule(M);
const_cast<TargetLoweringObjectFile&>(getObjFileLowering())
.Initialize(OutContext, TM);
- Mang = new Mangler(OutContext, *TM.getDataLayout());
+ OutStreamer.InitStreamer();
+
+ Mang = new Mangler(OutContext, &TM);
// Allow the target to emit any magic that it wants at the start of the file.
EmitStartOfAsmFile(M);
SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GV, TM);
- const DataLayout *TD = TM.getDataLayout();
- uint64_t Size = TD->getTypeAllocSize(GV->getType()->getElementType());
+ const DataLayout *DL = TM.getDataLayout();
+ uint64_t Size = DL->getTypeAllocSize(GV->getType()->getElementType());
// If the alignment is specified, we *must* obey it. Overaligning a global
// with a specified alignment is a prompt way to break globals emitted to
// sections and expected to be contiguous (e.g. ObjC metadata).
- unsigned AlignLog = getGVAlignmentLog2(GV, *TD);
+ unsigned AlignLog = getGVAlignmentLog2(GV, *DL);
+
+ if (DD)
+ DD->setSymbolSize(GVSym, Size);
// Handle common and BSS local symbols (.lcomm).
if (GVKind.isCommon() || GVKind.isBSSLocal()) {
MCSymbol *MangSym =
OutContext.GetOrCreateSymbol(GVSym->getName() + Twine("$tlv$init"));
- if (GVKind.isThreadBSS())
+ if (GVKind.isThreadBSS()) {
+ TheSection = getObjFileLowering().getTLSBSSSection();
OutStreamer.EmitTBSSSymbol(TheSection, MangSym, Size, 1 << AlignLog);
- else if (GVKind.isThreadData()) {
+ } else if (GVKind.isThreadData()) {
OutStreamer.SwitchSection(TheSection);
EmitAlignment(AlignLog, GV);
// - __tlv_bootstrap - used to make sure support exists
// - spare pointer, used when mapped by the runtime
// - pointer to mangled symbol above with initializer
- unsigned PtrSize = TD->getPointerSizeInBits()/8;
+ unsigned PtrSize = DL->getPointerSizeInBits()/8;
OutStreamer.EmitSymbolValue(GetExternalSymbolSymbol("_tlv_bootstrap"),
- PtrSize);
+ PtrSize);
OutStreamer.EmitIntValue(0, PtrSize);
OutStreamer.EmitSymbolValue(MangSym, PtrSize);
OutStreamer.EmitLabel(DeadBlockSyms[i]);
}
- // Add some workaround for linkonce linkage on Cygwin\MinGW.
- if (MAI->getLinkOnceDirective() != 0 &&
- (F->hasLinkOnceLinkage() || F->hasWeakLinkage())) {
- // FIXME: What is this?
- MCSymbol *FakeStub =
- OutContext.GetOrCreateSymbol(Twine("Lllvm$workaround$fake$stub$")+
- CurrentFnSym->getName());
- OutStreamer.EmitLabel(FakeStub);
- }
+ // Emit the prefix data.
+ if (F->hasPrefixData())
+ EmitGlobalConstant(F->getPrefixData());
// Emit pre-function debug and/or EH information.
if (DE) {
// cast away const; DIetc do not take const operands for some reason.
DIVariable V(const_cast<MDNode*>(MI->getOperand(2).getMetadata()));
- if (V.getContext().isSubprogram())
- OS << DISubprogram(V.getContext()).getDisplayName() << ":";
+ if (V.getContext().isSubprogram()) {
+ StringRef Name = DISubprogram(V.getContext()).getDisplayName();
+ if (!Name.empty())
+ OS << Name << ":";
+ }
OS << V.getName() << " <- ";
+ // The second operand is only an offset if it's an immediate.
+ bool Deref = MI->getOperand(0).isReg() && MI->getOperand(1).isImm();
+ int64_t Offset = Deref ? MI->getOperand(1).getImm() : 0;
+
// Register or immediate value. Register 0 means undef.
if (MI->getOperand(0).isFPImm()) {
APFloat APF = APFloat(MI->getOperand(0).getFPImm()->getValueAPF());
} else if (MI->getOperand(0).isCImm()) {
MI->getOperand(0).getCImm()->getValue().print(OS, false /*isSigned*/);
} else {
- assert(MI->getOperand(0).isReg() && "Unknown operand type");
- if (MI->getOperand(0).getReg() == 0) {
+ unsigned Reg;
+ if (MI->getOperand(0).isReg()) {
+ Reg = MI->getOperand(0).getReg();
+ } else {
+ assert(MI->getOperand(0).isFI() && "Unknown operand type");
+ const TargetFrameLowering *TFI = AP.TM.getFrameLowering();
+ Offset += TFI->getFrameIndexReference(*AP.MF,
+ MI->getOperand(0).getIndex(), Reg);
+ Deref = true;
+ }
+ if (Reg == 0) {
// Suppress offset, it is not meaningful here.
OS << "undef";
// NOTE: Want this comment at start of line, don't emit with AddComment.
AP.OutStreamer.EmitRawText(OS.str());
return true;
}
- OS << AP.TM.getRegisterInfo()->getName(MI->getOperand(0).getReg());
+ if (Deref)
+ OS << '[';
+ OS << AP.TM.getRegisterInfo()->getName(Reg);
}
- OS << '+' << MI->getOperand(1).getImm();
+ if (Deref)
+ OS << '+' << Offset << ']';
+
// NOTE: Want this comment at start of line, don't emit with AddComment.
AP.OutStreamer.EmitRawText(OS.str());
return true;
}
void AsmPrinter::emitPrologLabel(const MachineInstr &MI) {
- MCSymbol *Label = MI.getOperand(0).getMCSymbol();
+ const MCSymbol *Label = MI.getOperand(0).getMCSymbol();
if (MAI->getExceptionHandlingType() != ExceptionHandling::DwarfCFI)
return;
if (MMI->getCompactUnwindEncoding() != 0)
OutStreamer.EmitCompactUnwindEncoding(MMI->getCompactUnwindEncoding());
- MachineModuleInfo &MMI = MF->getMMI();
- const std::vector<MachineMove> &Moves = MMI.getFrameMoves();
+ const MachineModuleInfo &MMI = MF->getMMI();
+ const std::vector<MCCFIInstruction> &Instrs = MMI.getFrameInstructions();
bool FoundOne = false;
(void)FoundOne;
- for (std::vector<MachineMove>::const_iterator I = Moves.begin(),
- E = Moves.end();
- I != E; ++I) {
+ for (std::vector<MCCFIInstruction>::const_iterator I = Instrs.begin(),
+ E = Instrs.end(); I != E; ++I) {
if (I->getLabel() == Label) {
- EmitCFIFrameMove(*I);
+ emitCFIInstruction(*I);
FoundOne = true;
}
}
OutStreamer.AddBlankLine();
}
-/// getDebugValueLocation - Get location information encoded by DBG_VALUE
-/// operands.
-MachineLocation AsmPrinter::
-getDebugValueLocation(const MachineInstr *MI) const {
- // Target specific DBG_VALUE instructions are handled by each target.
- return MachineLocation();
-}
-
/// EmitDwarfRegOp - Emit dwarf register operation.
-void AsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc) const {
+void AsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc,
+ bool Indirect) const {
const TargetRegisterInfo *TRI = TM.getRegisterInfo();
int Reg = TRI->getDwarfRegNum(MLoc.getReg(), false);
// caller might be in the middle of an dwarf expression. We should
// probably assert that Reg >= 0 once debug info generation is more mature.
- if (MLoc.isIndirect()) {
+ if (MLoc.isIndirect() || Indirect) {
if (Reg < 32) {
OutStreamer.AddComment(
dwarf::OperationEncodingString(dwarf::DW_OP_breg0 + Reg));
OutStreamer.AddComment(Twine(Reg));
EmitULEB128(Reg);
}
- EmitSLEB128(MLoc.getOffset());
+ EmitSLEB128(!MLoc.isIndirect() ? 0 : MLoc.getOffset());
+ if (MLoc.isIndirect() && Indirect)
+ EmitInt8(dwarf::DW_OP_deref);
} else {
if (Reg < 32) {
OutStreamer.AddComment(
if (!ModuleFlags.empty())
getObjFileLowering().emitModuleFlags(OutStreamer, ModuleFlags, Mang, TM);
+ // Make sure we wrote out everything we need.
+ OutStreamer.Flush();
+
// Finalize debug and EH information.
if (DE) {
{
}
}
-typedef std::pair<unsigned, 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, bool isCtor) {
!isa<PointerType>(ETy->getTypeAtIndex(1U))) return; // Not (int, ptr).
// Gather the structors in a form that's convenient for sorting by priority.
+ typedef std::pair<unsigned, Constant *> Structor;
SmallVector<Structor, 8> Structors;
for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i));
}
// Emit the function pointers in the target-specific order
- const DataLayout *TD = TM.getDataLayout();
- unsigned Align = Log2_32(TD->getPointerPrefAlignment());
- std::stable_sort(Structors.begin(), Structors.end(), priority_order);
+ const DataLayout *DL = TM.getDataLayout();
+ unsigned Align = Log2_32(DL->getPointerPrefAlignment());
+ std::stable_sort(Structors.begin(), Structors.end(), less_first());
for (unsigned i = 0, e = Structors.size(); i != e; ++i) {
const MCSection *OutputSection =
(isCtor ?
/// where the size in bytes of the directive is specified by Size and Label
/// specifies the label. This implicitly uses .set if it is available.
void AsmPrinter::EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset,
- unsigned Size)
+ unsigned Size, bool IsSectionRelative)
const {
+ if (MAI->needsDwarfSectionOffsetDirective() && IsSectionRelative) {
+ OutStreamer.EmitCOFFSecRel32(Label);
+ return;
+ }
// Emit Label+Offset (or just Label if Offset is zero)
const MCExpr *Expr = MCSymbolRefExpr::Create(Label, OutContext);
report_fatal_error(OS.str());
}
case Instruction::GetElementPtr: {
- const DataLayout &TD = *AP.TM.getDataLayout();
+ const DataLayout &DL = *AP.TM.getDataLayout();
// Generate a symbolic expression for the byte address
- APInt OffsetAI(TD.getPointerSizeInBits(), 0);
- cast<GEPOperator>(CE)->accumulateConstantOffset(TD, OffsetAI);
+ APInt OffsetAI(DL.getPointerSizeInBits(), 0);
+ cast<GEPOperator>(CE)->accumulateConstantOffset(DL, OffsetAI);
const MCExpr *Base = lowerConstant(CE->getOperand(0), AP);
if (!OffsetAI)
return lowerConstant(CE->getOperand(0), AP);
case Instruction::IntToPtr: {
- const DataLayout &TD = *AP.TM.getDataLayout();
+ const DataLayout &DL = *AP.TM.getDataLayout();
// 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()),
+ Op = ConstantExpr::getIntegerCast(Op, DL.getIntPtrType(CV->getContext()),
false/*ZExt*/);
return lowerConstant(Op, AP);
}
case Instruction::PtrToInt: {
- const DataLayout &TD = *AP.TM.getDataLayout();
+ const DataLayout &DL = *AP.TM.getDataLayout();
// 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);
// 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()))
+ if (DL.getTypeAllocSize(Ty) == DL.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());
+ unsigned InBits = DL.getTypeAllocSizeInBits(Op->getType());
const MCExpr *MaskExpr = MCConstantExpr::Create(~0ULL >> (64-InBits), Ctx);
return MCBinaryExpr::CreateAnd(OpExpr, MaskExpr, Ctx);
}
}
}
-static void emitGlobalConstantImpl(const Constant *C, unsigned AddrSpace,
- AsmPrinter &AP);
+static void emitGlobalConstantImpl(const Constant *C, AsmPrinter &AP);
/// isRepeatedByteSequence - Determine whether the given value is
/// composed of a repeated sequence of identical bytes and return the
}
static void emitGlobalConstantDataSequential(const ConstantDataSequential *CDS,
- unsigned AddrSpace,AsmPrinter &AP){
+ AsmPrinter &AP){
// See if we can aggregate this into a .fill, if so, emit it as such.
int Value = isRepeatedByteSequence(CDS, AP.TM);
uint64_t Bytes = AP.TM.getDataLayout()->getTypeAllocSize(CDS->getType());
// Don't emit a 1-byte object as a .fill.
if (Bytes > 1)
- return AP.OutStreamer.EmitFill(Bytes, Value, AddrSpace);
+ return AP.OutStreamer.EmitFill(Bytes, Value);
}
// If this can be emitted with .ascii/.asciz, emit it as such.
if (CDS->isString())
- return AP.OutStreamer.EmitBytes(CDS->getAsString(), AddrSpace);
+ return AP.OutStreamer.EmitBytes(CDS->getAsString());
// Otherwise, emit the values in successive locations.
unsigned ElementByteSize = CDS->getElementByteSize();
AP.OutStreamer.GetCommentOS() << format("0x%" PRIx64 "\n",
CDS->getElementAsInteger(i));
AP.OutStreamer.EmitIntValue(CDS->getElementAsInteger(i),
- ElementByteSize, AddrSpace);
+ ElementByteSize);
}
} else if (ElementByteSize == 4) {
// FP Constants are printed as integer constants to avoid losing
F = CDS->getElementAsFloat(i);
if (AP.isVerbose())
AP.OutStreamer.GetCommentOS() << "float " << F << '\n';
- AP.OutStreamer.EmitIntValue(I, 4, AddrSpace);
+ AP.OutStreamer.EmitIntValue(I, 4);
}
} else {
assert(CDS->getElementType()->isDoubleTy());
F = CDS->getElementAsDouble(i);
if (AP.isVerbose())
AP.OutStreamer.GetCommentOS() << "double " << F << '\n';
- AP.OutStreamer.EmitIntValue(I, 8, AddrSpace);
+ AP.OutStreamer.EmitIntValue(I, 8);
}
}
- const DataLayout &TD = *AP.TM.getDataLayout();
- unsigned Size = TD.getTypeAllocSize(CDS->getType());
- unsigned EmittedSize = TD.getTypeAllocSize(CDS->getType()->getElementType()) *
+ const DataLayout &DL = *AP.TM.getDataLayout();
+ unsigned Size = DL.getTypeAllocSize(CDS->getType());
+ unsigned EmittedSize = DL.getTypeAllocSize(CDS->getType()->getElementType()) *
CDS->getNumElements();
if (unsigned Padding = Size - EmittedSize)
- AP.OutStreamer.EmitZeros(Padding, AddrSpace);
+ AP.OutStreamer.EmitZeros(Padding);
}
-static void emitGlobalConstantArray(const ConstantArray *CA, unsigned AddrSpace,
- AsmPrinter &AP) {
+static void emitGlobalConstantArray(const ConstantArray *CA, AsmPrinter &AP) {
// 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.getDataLayout()->getTypeAllocSize(CA->getType());
- AP.OutStreamer.EmitFill(Bytes, Value, AddrSpace);
+ AP.OutStreamer.EmitFill(Bytes, Value);
}
else {
for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i)
- emitGlobalConstantImpl(CA->getOperand(i), AddrSpace, AP);
+ emitGlobalConstantImpl(CA->getOperand(i), AP);
}
}
-static void emitGlobalConstantVector(const ConstantVector *CV,
- unsigned AddrSpace, AsmPrinter &AP) {
+static void emitGlobalConstantVector(const ConstantVector *CV, AsmPrinter &AP) {
for (unsigned i = 0, e = CV->getType()->getNumElements(); i != e; ++i)
- emitGlobalConstantImpl(CV->getOperand(i), AddrSpace, AP);
+ emitGlobalConstantImpl(CV->getOperand(i), AP);
- const DataLayout &TD = *AP.TM.getDataLayout();
- unsigned Size = TD.getTypeAllocSize(CV->getType());
- unsigned EmittedSize = TD.getTypeAllocSize(CV->getType()->getElementType()) *
+ const DataLayout &DL = *AP.TM.getDataLayout();
+ unsigned Size = DL.getTypeAllocSize(CV->getType());
+ unsigned EmittedSize = DL.getTypeAllocSize(CV->getType()->getElementType()) *
CV->getType()->getNumElements();
if (unsigned Padding = Size - EmittedSize)
- AP.OutStreamer.EmitZeros(Padding, AddrSpace);
+ AP.OutStreamer.EmitZeros(Padding);
}
-static void emitGlobalConstantStruct(const ConstantStruct *CS,
- unsigned AddrSpace, AsmPrinter &AP) {
+static void emitGlobalConstantStruct(const ConstantStruct *CS, AsmPrinter &AP) {
// Print the fields in successive locations. Pad to align if needed!
- const DataLayout *TD = AP.TM.getDataLayout();
- unsigned Size = TD->getTypeAllocSize(CS->getType());
- const StructLayout *Layout = TD->getStructLayout(CS->getType());
+ const DataLayout *DL = AP.TM.getDataLayout();
+ unsigned Size = DL->getTypeAllocSize(CS->getType());
+ const StructLayout *Layout = DL->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 FieldSize = DL->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.
- emitGlobalConstantImpl(Field, AddrSpace, AP);
+ emitGlobalConstantImpl(Field, AP);
// 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);
+ AP.OutStreamer.EmitZeros(PadSize);
}
assert(SizeSoFar == Layout->getSizeInBytes() &&
"Layout of constant struct may be incorrect!");
}
-static void emitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace,
- AsmPrinter &AP) {
+static void emitGlobalConstantFP(const ConstantFP *CFP, AsmPrinter &AP) {
APInt API = CFP->getValueAPF().bitcastToAPInt();
// First print a comment with what we think the original floating-point value
int Chunk = API.getNumWords() - 1;
if (TrailingBytes)
- AP.OutStreamer.EmitIntValue(p[Chunk--], TrailingBytes, AddrSpace);
+ AP.OutStreamer.EmitIntValue(p[Chunk--], TrailingBytes);
for (; Chunk >= 0; --Chunk)
- AP.OutStreamer.EmitIntValue(p[Chunk], sizeof(uint64_t), AddrSpace);
+ AP.OutStreamer.EmitIntValue(p[Chunk], sizeof(uint64_t));
} else {
unsigned Chunk;
for (Chunk = 0; Chunk < NumBytes / sizeof(uint64_t); ++Chunk)
- AP.OutStreamer.EmitIntValue(p[Chunk], sizeof(uint64_t), AddrSpace);
+ AP.OutStreamer.EmitIntValue(p[Chunk], sizeof(uint64_t));
if (TrailingBytes)
- AP.OutStreamer.EmitIntValue(p[Chunk], TrailingBytes, AddrSpace);
+ AP.OutStreamer.EmitIntValue(p[Chunk], TrailingBytes);
}
// Emit the tail padding for the long double.
- const DataLayout &TD = *AP.TM.getDataLayout();
- AP.OutStreamer.EmitZeros(TD.getTypeAllocSize(CFP->getType()) -
- TD.getTypeStoreSize(CFP->getType()), AddrSpace);
+ const DataLayout &DL = *AP.TM.getDataLayout();
+ AP.OutStreamer.EmitZeros(DL.getTypeAllocSize(CFP->getType()) -
+ DL.getTypeStoreSize(CFP->getType()));
}
-static void emitGlobalConstantLargeInt(const ConstantInt *CI,
- unsigned AddrSpace, AsmPrinter &AP) {
- const DataLayout *TD = AP.TM.getDataLayout();
+static void emitGlobalConstantLargeInt(const ConstantInt *CI, AsmPrinter &AP) {
+ const DataLayout *DL = AP.TM.getDataLayout();
unsigned BitWidth = CI->getBitWidth();
- assert((BitWidth & 63) == 0 && "only support multiples of 64-bits");
+
+ // Copy the value as we may massage the layout for constants whose bit width
+ // is not a multiple of 64-bits.
+ APInt Realigned(CI->getValue());
+ uint64_t ExtraBits = 0;
+ unsigned ExtraBitsSize = BitWidth & 63;
+
+ if (ExtraBitsSize) {
+ // The bit width of the data is not a multiple of 64-bits.
+ // The extra bits are expected to be at the end of the chunk of the memory.
+ // Little endian:
+ // * Nothing to be done, just record the extra bits to emit.
+ // Big endian:
+ // * Record the extra bits to emit.
+ // * Realign the raw data to emit the chunks of 64-bits.
+ if (DL->isBigEndian()) {
+ // Basically the structure of the raw data is a chunk of 64-bits cells:
+ // 0 1 BitWidth / 64
+ // [chunk1][chunk2] ... [chunkN].
+ // The most significant chunk is chunkN and it should be emitted first.
+ // However, due to the alignment issue chunkN contains useless bits.
+ // Realign the chunks so that they contain only useless information:
+ // ExtraBits 0 1 (BitWidth / 64) - 1
+ // chu[nk1 chu][nk2 chu] ... [nkN-1 chunkN]
+ ExtraBits = Realigned.getRawData()[0] &
+ (((uint64_t)-1) >> (64 - ExtraBitsSize));
+ Realigned = Realigned.lshr(ExtraBitsSize);
+ } else
+ ExtraBits = Realigned.getRawData()[BitWidth / 64];
+ }
// 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();
+ const uint64_t *RawData = Realigned.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);
+ uint64_t Val = DL->isBigEndian() ? RawData[e - i - 1] : RawData[i];
+ AP.OutStreamer.EmitIntValue(Val, 8);
+ }
+
+ if (ExtraBitsSize) {
+ // Emit the extra bits after the 64-bits chunks.
+
+ // Emit a directive that fills the expected size.
+ uint64_t Size = AP.TM.getDataLayout()->getTypeAllocSize(CI->getType());
+ Size -= (BitWidth / 64) * 8;
+ assert(Size && Size * 8 >= ExtraBitsSize &&
+ (ExtraBits & (((uint64_t)-1) >> (64 - ExtraBitsSize)))
+ == ExtraBits && "Directive too small for extra bits.");
+ AP.OutStreamer.EmitIntValue(ExtraBits, Size);
}
}
-static void emitGlobalConstantImpl(const Constant *CV, unsigned AddrSpace,
- AsmPrinter &AP) {
- const DataLayout *TD = AP.TM.getDataLayout();
- uint64_t Size = TD->getTypeAllocSize(CV->getType());
+static void emitGlobalConstantImpl(const Constant *CV, AsmPrinter &AP) {
+ const DataLayout *DL = AP.TM.getDataLayout();
+ uint64_t Size = DL->getTypeAllocSize(CV->getType());
if (isa<ConstantAggregateZero>(CV) || isa<UndefValue>(CV))
- return AP.OutStreamer.EmitZeros(Size, AddrSpace);
+ return AP.OutStreamer.EmitZeros(Size);
if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
switch (Size) {
if (AP.isVerbose())
AP.OutStreamer.GetCommentOS() << format("0x%" PRIx64 "\n",
CI->getZExtValue());
- AP.OutStreamer.EmitIntValue(CI->getZExtValue(), Size, AddrSpace);
+ AP.OutStreamer.EmitIntValue(CI->getZExtValue(), Size);
return;
default:
- emitGlobalConstantLargeInt(CI, AddrSpace, AP);
+ emitGlobalConstantLargeInt(CI, AP);
return;
}
}
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV))
- return emitGlobalConstantFP(CFP, AddrSpace, AP);
+ return emitGlobalConstantFP(CFP, AP);
if (isa<ConstantPointerNull>(CV)) {
- AP.OutStreamer.EmitIntValue(0, Size, AddrSpace);
+ AP.OutStreamer.EmitIntValue(0, Size);
return;
}
if (const ConstantDataSequential *CDS = dyn_cast<ConstantDataSequential>(CV))
- return emitGlobalConstantDataSequential(CDS, AddrSpace, AP);
+ return emitGlobalConstantDataSequential(CDS, AP);
if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV))
- return emitGlobalConstantArray(CVA, AddrSpace, AP);
+ return emitGlobalConstantArray(CVA, AP);
if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV))
- return emitGlobalConstantStruct(CVS, AddrSpace, AP);
+ return emitGlobalConstantStruct(CVS, AP);
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
// Look through bitcasts, which might not be able to be MCExpr'ized (e.g. of
// vectors).
if (CE->getOpcode() == Instruction::BitCast)
- return emitGlobalConstantImpl(CE->getOperand(0), AddrSpace, AP);
+ return emitGlobalConstantImpl(CE->getOperand(0), AP);
if (Size > 8) {
// If the constant expression's size is greater than 64-bits, then we have
// to emit the value in chunks. Try to constant fold the value and emit it
// that way.
- Constant *New = ConstantFoldConstantExpression(CE, TD);
+ Constant *New = ConstantFoldConstantExpression(CE, DL);
if (New && New != CE)
- return emitGlobalConstantImpl(New, AddrSpace, AP);
+ return emitGlobalConstantImpl(New, AP);
}
}
if (const ConstantVector *V = dyn_cast<ConstantVector>(CV))
- return emitGlobalConstantVector(V, AddrSpace, AP);
+ return emitGlobalConstantVector(V, AP);
// Otherwise, it must be a ConstantExpr. Lower it to an MCExpr, then emit it
// thread the streamer with EmitValue.
- AP.OutStreamer.EmitValue(lowerConstant(CV, AP), Size, AddrSpace);
+ AP.OutStreamer.EmitValue(lowerConstant(CV, AP), Size);
}
/// EmitGlobalConstant - Print a general LLVM constant to the .s file.
-void AsmPrinter::EmitGlobalConstant(const Constant *CV, unsigned AddrSpace) {
+void AsmPrinter::EmitGlobalConstant(const Constant *CV) {
uint64_t Size = TM.getDataLayout()->getTypeAllocSize(CV->getType());
if (Size)
- emitGlobalConstantImpl(CV, AddrSpace, *this);
+ emitGlobalConstantImpl(CV, *this);
else if (MAI->hasSubsectionsViaSymbols()) {
// If the global has zero size, emit a single byte so that two labels don't
// look like they are at the same location.
- OutStreamer.EmitIntValue(0, 1, AddrSpace);
+ OutStreamer.EmitIntValue(0, 1);
}
}