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/Assembly/Writer.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Constants.h"
#include "llvm/CodeGen/GCMetadataPrinter.h"
Chris Lattner
committed
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/DwarfWriter.h"
Argyrios Kyrtzidis
committed
#include "llvm/Analysis/DebugInfo.h"
Chris Lattner
committed
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
Evan Cheng
committed
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Target/TargetAsmInfo.h"
Owen Anderson
committed
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include <cerrno>
using namespace llvm;
Evan Cheng
committed
static cl::opt<cl::boolOrDefault>
AsmVerbose("asm-verbose", cl::desc("Add comments to directives."),
cl::init(cl::BOU_UNSET));
const TargetAsmInfo *T, bool VDef)
: MachineFunctionPass(&ID), FunctionNumber(0), O(o),
TM(tm), TAI(T), TRI(tm.getRegisterInfo()),
Chris Lattner
committed
OutContext(*new MCContext()),
OutStreamer(*createAsmStreamer(OutContext, O)),
IsInTextSection(false), LastMI(0), LastFn(0), Counter(~0U),
PrevDLT(0, ~0U, ~0U) {
Chris Lattner
committed
DW = 0; MMI = 0;
Evan Cheng
committed
switch (AsmVerbose) {
case cl::BOU_UNSET: VerboseAsm = VDef; break;
case cl::BOU_TRUE: VerboseAsm = true; break;
case cl::BOU_FALSE: VerboseAsm = false; break;
}
}
Gordon Henriksen
committed
AsmPrinter::~AsmPrinter() {
for (gcp_iterator I = GCMetadataPrinters.begin(),
E = GCMetadataPrinters.end(); I != E; ++I)
delete I->second;
Chris Lattner
committed
delete &OutStreamer;
delete &OutContext;
Gordon Henriksen
committed
}
TargetLoweringObjectFile &AsmPrinter::getObjFileLowering() const {
return TM.getTargetLowering()->getObjFileLowering();
}
/// SwitchToSection - Switch to the specified section of the executable if we
/// are not already in it! If "NS" is null, then this causes us to exit the
/// current section and not reenter another one. This is generally used for
/// asmprinter hacks.
///
/// FIXME: Remove support for null sections.
///
void AsmPrinter::SwitchToSection(const MCSection *NS) {
const std::string &NewSection = NS ? NS->getName() : "";
// If we're already in this section, we're done.
if (CurrentSection == NewSection) return;
// Close the current section, if applicable.
if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty())
O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << '\n';
// FIXME: Make CurrentSection a Section* in the future
CurrentSection = NewSection;
CurrentSection_ = NS;
Anton Korobeynikov
committed
if (!CurrentSection.empty()) {
// If section is named we need to switch into it via special '.section'
// directive and also append funky flags. Otherwise - section name is just
// some magic assembler directive.
if (!NS->isDirective()) {
Chris Lattner
committed
SmallString<32> FlagsStr;
getObjFileLowering().getSectionFlagsAsString(NS->getKind(), FlagsStr);
O << TAI->getSwitchToSectionDirective()
<< CurrentSection
<< FlagsStr.c_str();
Chris Lattner
committed
} else {
Anton Korobeynikov
committed
O << CurrentSection;
Chris Lattner
committed
}
Anton Korobeynikov
committed
O << TAI->getDataSectionStartSuffix() << '\n';
}
IsInTextSection = NS ? NS->getKind().isText() : false;
Gordon Henriksen
committed
void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
Gordon Henriksen
committed
MachineFunctionPass::getAnalysisUsage(AU);
AU.addRequired<GCModuleInfo>();
Gordon Henriksen
committed
}
bool AsmPrinter::doInitialization(Module &M) {
// Initialize TargetLoweringObjectFile.
const_cast<TargetLoweringObjectFile&>(getObjFileLowering())
.Initialize(OutContext, TM);
Mang = new Mangler(M, TAI->getGlobalPrefix(), TAI->getPrivateGlobalPrefix(),
TAI->getLinkerPrivateGlobalPrefix());
if (TAI->doesAllowQuotesInName())
Mang->setUseQuotes(true);
GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>();
assert(MI && "AsmPrinter didn't require GCModuleInfo?");
if (TAI->hasSingleParameterDotFile()) {
/* Very minimal debug info. It is ignored if we emit actual
debug info. If we don't, this at helps the user find where
a function came from. */
O << "\t.file\t\"" << M.getModuleIdentifier() << "\"\n";
}
for (GCModuleInfo::iterator I = MI->begin(), E = MI->end(); I != E; ++I)
if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*I))
MP->beginAssembly(O, *this, *TAI);
Gordon Henriksen
committed
O << TAI->getCommentString() << " Start of file scope inline assembly\n"
<< '\n' << TAI->getCommentString()
<< " End of file scope inline assembly\n";
SwitchToSection(0); // Reset back to no section to close off sections.
Chris Lattner
committed
if (TAI->doesSupportDebugInformation() ||
TAI->doesSupportExceptionHandling()) {
MMI = getAnalysisIfAvailable<MachineModuleInfo>();
if (MMI)
MMI->AnalyzeModule(M);
Chris Lattner
committed
DW = getAnalysisIfAvailable<DwarfWriter>();
if (DW)
DW->BeginModule(&M, MMI, O, this, TAI);
return false;
}
bool AsmPrinter::doFinalization(Module &M) {
// Emit global variables.
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I)
PrintGlobalVariable(I);
// Emit final debug information.
if (TAI->doesSupportDebugInformation() || TAI->doesSupportExceptionHandling())
DW->EndModule();
// If the target wants to know about weak references, print them all.
// FIXME: This is not lazy, it would be nice to only print weak references
// to stuff that is actually used. Note that doing so would require targets
// to notice uses in operands (due to constant exprs etc). This should
// happen with the MC stuff eventually.
SwitchToSection(0);
// Print out module-level global variables here.
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
if (I->hasExternalWeakLinkage())
O << TAI->getWeakRefDirective() << Mang->getMangledName(I) << '\n';
for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) {
Loading
Loading full blame...