//===- 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/MCSection.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/MCDwarf.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), LastValidFragment(0)
{
// 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);
}
bool MCAsmLayout::isSectionUpToDate(const MCSectionData *SD) const {
// The first section is always up-to-date.
unsigned Index = SD->getLayoutOrder();
if (!Index)
return true;
// Otherwise, sections are always implicitly computed when the preceeding
// fragment is layed out.
const MCSectionData *Prev = getSectionOrder()[Index - 1];
return isFragmentUpToDate(&(Prev->getFragmentList().back()));
}
bool MCAsmLayout::isFragmentUpToDate(const MCFragment *F) const {
return (LastValidFragment &&
F->getLayoutOrder() <= LastValidFragment->getLayoutOrder());
}
void MCAsmLayout::UpdateForSlide(MCFragment *F, int SlideAmount) {
// If this fragment wasn't already up-to-date, we don't need to do anything.
if (!isFragmentUpToDate(F))
return;
// Otherwise, reset the last valid fragment to the predecessor of the
// invalidated fragment.
LastValidFragment = F->getPrevNode();
if (!LastValidFragment) {
unsigned Index = F->getParent()->getLayoutOrder();
if (Index != 0) {
MCSectionData *Prev = getSectionOrder()[Index - 1];
LastValidFragment = &(Prev->getFragmentList().back());
}
}
}
void MCAsmLayout::EnsureValid(const MCFragment *F) const {
// Advance the layout position until the fragment is up-to-date.
while (!isFragmentUpToDate(F)) {
// Advance to the next fragment.
MCFragment *Cur = LastValidFragment;
if (Cur)
Cur = Cur->getNextNode();
if (!Cur) {
unsigned NextIndex = 0;
if (LastValidFragment)
NextIndex = LastValidFragment->getParent()->getLayoutOrder() + 1;
Cur = SectionOrder[NextIndex]->begin();
}
const_cast<MCAsmLayout*>(this)->LayoutFragment(Cur);
}
}
void MCAsmLayout::FragmentReplaced(MCFragment *Src, MCFragment *Dst) {
if (LastValidFragment == Src)
LastValidFragment = Dst;