//===- 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/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCFixupKindInfo.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCValue.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
namespace {
namespace stats {
STATISTIC(EmittedFragments, "Number of emitted assembler fragments - total");
STATISTIC(EmittedRelaxableFragments,
"Number of emitted assembler fragments - relaxable");
STATISTIC(EmittedDataFragments,
"Number of emitted assembler fragments - data");
STATISTIC(EmittedCompactEncodedInstFragments,
"Number of emitted assembler fragments - compact encoded inst");
STATISTIC(EmittedAlignFragments,
"Number of emitted assembler fragments - align");
STATISTIC(EmittedFillFragments,
"Number of emitted assembler fragments - fill");
STATISTIC(EmittedOrgFragments,
"Number of emitted assembler fragments - org");
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");
}
}
// 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()
{
// Compute the section layout order. Virtual sections must go last.
for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it)
if (!it->getSection().isVirtualSection())
SectionOrder.push_back(&*it);
for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it)
if (it->getSection().isVirtualSection())
SectionOrder.push_back(&*it);
}
bool MCAsmLayout::isFragmentValid(const MCFragment *F) const {
const MCSectionData &SD = *F->getParent();
const MCFragment *LastValid = LastValidFragment.lookup(&SD);
if (!LastValid)
return false;
assert(LastValid->getParent() == F->getParent());
return F->getLayoutOrder() <= LastValid->getLayoutOrder();
}
void MCAsmLayout::invalidateFragmentsFrom(MCFragment *F) {
// If this fragment wasn't already valid, we don't need to do anything.
if (!isFragmentValid(F))
return;
// Otherwise, reset the last valid fragment to the previous fragment
// (if this is the first fragment, it will be NULL).
const MCSectionData &SD = *F->getParent();
LastValidFragment[&SD] = F->getPrevNode();
}
void MCAsmLayout::ensureValid(const MCFragment *F) const {
MCSectionData &SD = *F->getParent();
MCFragment *Cur = LastValidFragment[&SD];
if (!Cur)
Cur = &*SD.begin();
else
Cur = Cur->getNextNode();
// A