Skip to content
AsmPrinter.cpp 61.3 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 "llvm/DerivedTypes.h"
#include "llvm/Constants.h"
#include "llvm/Module.h"
#include "llvm/CodeGen/DwarfWriter.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"
David Greene's avatar
 
David Greene committed
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
David Greene's avatar
 
David Greene committed
#include "llvm/Support/FormattedStream.h"
#include "llvm/MC/MCAsmInfo.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/TargetOptions.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/ADT/SmallPtrSet.h"
static cl::opt<cl::boolOrDefault>
AsmVerbose("asm-verbose", cl::desc("Add comments to directives."),
           cl::init(cl::BOU_UNSET));

static bool getVerboseAsm(bool VDef) {
  switch (AsmVerbose) {
  default:
  case cl::BOU_UNSET: return VDef;
  case cl::BOU_TRUE:  return true;
  case cl::BOU_FALSE: return false;
  }      
}

Devang Patel's avatar
Devang Patel committed
char AsmPrinter::ID = 0;
David Greene's avatar
 
David Greene committed
AsmPrinter::AsmPrinter(formatted_raw_ostream &o, TargetMachine &tm,
                       const MCAsmInfo *T, bool VDef)
  : MachineFunctionPass(&ID), FunctionNumber(0), O(o),
    TM(tm), MAI(T), TRI(tm.getRegisterInfo()),
    // FIXME: Pass instprinter to streamer.
    OutStreamer(*createAsmStreamer(OutContext, O, *T,
                                   TM.getTargetData()->isLittleEndian(),
                                   getVerboseAsm(VDef), 0)),
    LastMI(0), LastFn(0), Counter(~0U), PrevDLT(NULL) {
  VerboseAsm = getVerboseAsm(VDef);
AsmPrinter::~AsmPrinter() {
  for (gcp_iterator I = GCMetadataPrinters.begin(),
                    E = GCMetadataPrinters.end(); I != E; ++I)
    delete I->second;
TargetLoweringObjectFile &AsmPrinter::getObjFileLowering() const {
  return TM.getTargetLowering()->getObjFileLowering();
}

/// 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);
David Greene's avatar
 
David Greene committed
  if (VerboseAsm)
David Greene's avatar
 
David Greene committed
    AU.addRequired<MachineLoopInfo>();
bool AsmPrinter::doInitialization(Module &M) {
  // Initialize TargetLoweringObjectFile.
  const_cast<TargetLoweringObjectFile&>(getObjFileLowering())
    .Initialize(OutContext, TM);
  
  // 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

  if (MAI->hasSingleParameterDotFile()) {
    // 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 function came from.
Rafael Espindola's avatar
Rafael Espindola committed
    O << "\t.file\t\"" << M.getModuleIdentifier() << "\"\n";
  }

  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(O, *this, *MAI);
Chris Lattner's avatar
Chris Lattner committed
  if (!M.getModuleInlineAsm().empty())
    O << MAI->getCommentString() << " Start of file scope inline assembly\n"
Chris Lattner's avatar
Chris Lattner committed
      << M.getModuleInlineAsm()
      << '\n' << MAI->getCommentString()
      << " End of file scope inline assembly\n";
  MMI = getAnalysisIfAvailable<MachineModuleInfo>();
  if (MMI)
    MMI->AnalyzeModule(M);
  DW = getAnalysisIfAvailable<DwarfWriter>();
  if (DW)
    DW->BeginModule(&M, MMI, O, this, MAI);
/// EmitGlobalVariable - Emit the specified global variable to the .s file.
void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
  if (!GV->hasInitializer())   // External globals require no code.
    return;
  
  // Check to see if this is a special global used by LLVM, if so, emit it.
  if (EmitSpecialLLVMGlobal(GV))
    return;

  MCSymbol *GVSym = GetGlobalValueSymbol(GV);
  printVisibility(GVSym, GV->getVisibility());

  if (MAI->hasDotTypeDotSizeDirective()) {
    O << "\t.type\t" << *GVSym;
    if (MAI->getCommentString()[0] != '@')
      O << ",@object\n";
    else
      O << ",%object\n";
  }
  
  SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GV, TM);

  const TargetData *TD = TM.getTargetData();
  unsigned Size = TD->getTypeAllocSize(GV->getType()->getElementType());
  unsigned AlignLog = TD->getPreferredAlignmentLog(GV);
  
Chris Lattner's avatar
Chris Lattner committed
  // Handle common and BSS local symbols (.lcomm).
  if (GVKind.isCommon() || GVKind.isBSSLocal()) {
    if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
    
    if (VerboseAsm) {
      WriteAsOperand(OutStreamer.GetCommentOS(), GV,
                     /*PrintType=*/false, GV->getParent());
      OutStreamer.GetCommentOS() << '\n';
Chris Lattner's avatar
Chris Lattner committed
    if (GVKind.isCommon()) {
      // .comm _foo, 42, 4
      OutStreamer.EmitCommonSymbol(GVSym, Size, 1 << AlignLog);
      return;
    }
    
    // Handle local BSS symbols.
    if (MAI->hasMachoZeroFillDirective()) {
      const MCSection *TheSection =
        getObjFileLowering().SectionForGlobal(GV, GVKind, Mang, TM);
      // .zerofill __DATA, __bss, _foo, 400, 5
      OutStreamer.EmitZerofill(TheSection, GVSym, Size, 1 << AlignLog);
      return;
    }
    
    if (const char *LComm = MAI->getLCOMMDirective()) {
      // .lcomm _foo, 42
Loading
Loading full blame...