Skip to content
AsmPrinter.cpp 70.5 KiB
Newer Older
//===-- AsmPrinter.cpp - Common AsmPrinter code ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the AsmPrinter class.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/AsmPrinter.h"
#include "DwarfDebug.h"
#include "DwarfException.h"
#include "llvm/Module.h"
#include "llvm/CodeGen/GCMetadataPrinter.h"
#include "llvm/CodeGen/MachineConstantPool.h"
David Greene's avatar
 
David Greene committed
#include "llvm/CodeGen/MachineFrameInfo.h"
David Greene's avatar
 
David Greene committed
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
David Greene's avatar
 
David Greene committed
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/MC/MCAsmInfo.h"
David Greene's avatar
 
David Greene committed
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Target/Mangler.h"
David Greene's avatar
 
David Greene committed
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Timer.h"
static const char *DWARFGroupName = "DWARF Emission";
static const char *DbgTimerName = "DWARF Debug Writer";
static const char *EHTimerName = "DWARF Exception Writer";
STATISTIC(EmittedInsts, "Number of machine instrs printed");

Devang Patel's avatar
Devang Patel committed
char AsmPrinter::ID = 0;
typedef DenseMap<GCStrategy*,GCMetadataPrinter*> gcp_map_type;
static gcp_map_type &getGCMap(void *&P) {
  if (P == 0)
    P = new gcp_map_type();
  return *(gcp_map_type*)P;
}


/// getGVAlignmentLog2 - Return the alignment to use for the specified global
/// value in log2 form.  This rounds up to the preferred alignment if possible
/// and legal.
static unsigned getGVAlignmentLog2(const GlobalValue *GV, const TargetData &TD,
                                   unsigned InBits = 0) {
  unsigned NumBits = 0;
  if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV))
    NumBits = TD.getPreferredAlignmentLog(GVar);
  // If InBits is specified, round it to it.
  if (InBits > NumBits)
    NumBits = InBits;
  // If the GV has a specified alignment, take it into account.
  if (GV->getAlignment() == 0)
    return NumBits;
  unsigned GVAlign = Log2_32(GV->getAlignment());
  // If the GVAlign is larger than NumBits, or if we are required to obey
  // NumBits because the GV has an assigned section, obey it.
  if (GVAlign > NumBits || GV->hasSection())
    NumBits = GVAlign;
  return NumBits;
}




AsmPrinter::AsmPrinter(TargetMachine &tm, MCStreamer &Streamer)
    TM(tm), MAI(tm.getMCAsmInfo()),
    OutContext(Streamer.getContext()),
    OutStreamer(Streamer),
    LastMI(0), LastFn(0), Counter(~0U), SetCounter(0) {
  DD = 0; DE = 0; MMI = 0; LI = 0;
  VerboseAsm = Streamer.isVerboseAsm();
  assert(DD == 0 && DE == 0 && "Debug/EH info didn't get finalized");
  if (GCMetadataPrinters != 0) {
    gcp_map_type &GCMap = getGCMap(GCMetadataPrinters);
    for (gcp_map_type::iterator I = GCMap.begin(), E = GCMap.end(); I != E; ++I)
      delete I->second;
    delete &GCMap;
    GCMetadataPrinters = 0;
  }
/// getFunctionNumber - Return a unique ID for the current function.
///
unsigned AsmPrinter::getFunctionNumber() const {
  return MF->getFunctionNumber();
}

const TargetLoweringObjectFile &AsmPrinter::getObjFileLowering() const {
  return TM.getTargetLowering()->getObjFileLowering();
}


/// getTargetData - Return information about data layout.
const TargetData &AsmPrinter::getTargetData() const {
  return *TM.getTargetData();
}

/// getCurrentSection() - Return the current section we are emitting to.
const MCSection *AsmPrinter::getCurrentSection() const {
  return OutStreamer.getCurrentSection();
void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
  MachineFunctionPass::getAnalysisUsage(AU);
  AU.addRequired<MachineModuleInfo>();
David Greene's avatar
 
David Greene committed
    AU.addRequired<MachineLoopInfo>();
bool AsmPrinter::doInitialization(Module &M) {
Chris Lattner's avatar
Chris Lattner committed
  MMI = getAnalysisIfAvailable<MachineModuleInfo>();
  // Initialize TargetLoweringObjectFile.
  const_cast<TargetLoweringObjectFile&>(getObjFileLowering())
    .Initialize(OutContext, TM);
  Mang = new Mangler(OutContext, *TM.getTargetData());
  // Allow the target to emit any magic that it wants at the start of the file.
  EmitStartOfAsmFile(M);
Rafael Espindola's avatar
Rafael Espindola committed

  // Very minimal debug info. It is ignored if we emit actual debug info. If we
  // don't, this at least helps the user find where a global came from.
  if (MAI->hasSingleParameterDotFile()) {
    // .file "foo.c"
    OutStreamer.EmitFileDirective(M.getModuleIdentifier());
  GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>();
  assert(MI && "AsmPrinter didn't require GCModuleInfo?");
  for (GCModuleInfo::iterator I = MI->begin(), E = MI->end(); I != E; ++I)
    if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*I))
      MP->beginAssembly(*this);

  // Emit module-level inline asm if it exists.
  if (!M.getModuleInlineAsm().empty()) {
    OutStreamer.AddComment("Start of file scope inline assembly");
    OutStreamer.AddBlankLine();
    EmitInlineAsm(M.getModuleInlineAsm()+"\n");
    OutStreamer.AddComment("End of file scope inline assembly");
    OutStreamer.AddBlankLine();
  }
  if (MAI->doesSupportDebugInformation())
    DD = new DwarfDebug(this, &M);
  switch (MAI->getExceptionHandlingType()) {
  case ExceptionHandling::None:
    return false;
  case ExceptionHandling::SjLj:
  case ExceptionHandling::DwarfCFI:
    DE = new DwarfCFIException(this);
    return false;
  case ExceptionHandling::ARM:
    DE = new ARMException(this);
Loading
Loading full blame...