//===- lib/MC/MCAssembler.cpp - Assembler Backend Implementation ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "assembler"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCValue.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/Target/TargetAsmBackend.h"
#include <vector>
using namespace llvm;
namespace {
namespace stats {
STATISTIC(EmittedFragments, "Number of emitted assembler fragments");
STATISTIC(EvaluateFixup, "Number of evaluated fixups");
STATISTIC(FragmentLayouts, "Number of fragment layouts");
STATISTIC(ObjectBytes, "Number of emitted object file bytes");
STATISTIC(RelaxationSteps, "Number of assembler layout and relaxation steps");
STATISTIC(RelaxedInstructions, "Number of relaxed instructions");
STATISTIC(SectionLayouts, "Number of section layouts");
}
}
// FIXME FIXME FIXME: There are number of places in this file where we convert
// what is a 64-bit assembler value used for computation into a value in the
// object file, which may truncate it. We should detect that truncation where
// invalid and report errors back.
/* *** */
MCAsmLayout::MCAsmLayout(MCAssembler &Asm) : Assembler(Asm) {
// Compute the section layout order. Virtual sections must go last.
for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it)
if (!Asm.getBackend().isVirtualSection(it->getSection()))
SectionOrder.push_back(&*it);
for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it)
if (Asm.getBackend().isVirtualSection(it->getSection()))
SectionOrder.push_back(&*it);
}
void MCAsmLayout::UpdateForSlide(MCFragment *F, int SlideAmount) {
// We shouldn't have to do anything special to support negative slides, and it
// is a perfectly valid thing to do as long as other parts of the system can
// guarantee convergence.
assert(SlideAmount >= 0 && "Negative slides not yet supported");
// Update the layout by simply recomputing the layout for the entire
// file. This is trivially correct, but very slow.
//
// FIXME-PERF: This is O(N^2), but will be eliminated once we get smarter.
// Layout the sections in order.
for (unsigned i = 0, e = getSectionOrder().size(); i != e; ++i)
getAssembler().LayoutSection(*this, i);
}
void MCAsmLayout::FragmentReplaced(MCFragment *Src, MCFragment *Dst) {
Dst->Offset = Src->Offset;
Dst->EffectiveSize = Src->EffectiveSize;
}
uint64_t MCAsmLayout::getFragmentAddress(const MCFragment *F) const {
assert(F->getParent() && "Missing section()!");
return getSectionAddress(F->getParent()) + getFragmentOffset(F);
}
uint64_t MCAsmLayout::getFragmentEffectiveSize(const MCFragment *F) const {
assert(F->EffectiveSize != ~UINT64_C(0) && "Address not set!");
return F->EffectiveSize;
}
void MCAsmLayout::setFragmentEffectiveSize(MCFragment *F, uint64_t Value) {
F->EffectiveSize = Value;
}
uint64_t MCAsmLayout::getFragmentOffset(const MCFragment *F) const {
assert(F->Offset != ~UINT64_C(0) && "Address not set!");
return F->Offset;
}
void MCAsmLayout::setFragmentOffset(MCFragment *F, uint64_t Value) {
F->Offset = Value;
}
uint64_t MCAsmLayout::getSymbolAddress(const MCSymbolData *SD) const {
assert(SD->getFragment() && "Invalid getAddress() on undefined symbol!");
return getFragmentAddress(SD->getFragment()) + SD->getOffset();
}
uint64_t MCAsmLayout::getSectionAddress(const MCSectionData *SD) const {
assert(SD->Address != ~UINT64_C(0) && "Address not set!");
return SD->Address;
}
void MCAsmLayout::setSectionAddress(MCSectionData *SD, uint64_t Value) {
SD->Address = Value;
}
uint64_t MCAsmLayout::getSectionAddressSize(const MCSectionData *SD) const {
// Otherwise, the size is the last fragment's end offset.
const MCFragment &F = SD->getFragmentList().back();
return getFragmentOffset(&F) + getFragmentEffectiveSize(&F);
}
uint64_t MCAsmLayout::getSectionFileSize(const MCSectionData *SD) const {
// Virtual sections have no file size.
if (getAssembler().getBackend().isVirtualSection(SD->getSection()))
return 0;
// Otherwise, the file size is the same as the address space size.