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/DwarfWriter.h"
#include "llvm/CodeGen/GCMetadataPrinter.h"
Chris Lattner
committed
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
Argyrios Kyrtzidis
committed
#include "llvm/Analysis/DebugInfo.h"
Chris Lattner
committed
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
Evan Cheng
committed
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Target/Mangler.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 <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));
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;
}
}
const MCAsmInfo *T, bool VDef)
: MachineFunctionPass(&ID), O(o),
TM(tm), MAI(T), TRI(tm.getRegisterInfo()),
Chris Lattner
committed
OutContext(*new MCContext()),
// FIXME: Pass instprinter to streamer.
OutStreamer(*createAsmStreamer(OutContext, O, *T,
TM.getTargetData()->isLittleEndian(),
getVerboseAsm(VDef), 0)),
Chris Lattner
committed
LastMI(0), LastFn(0), Counter(~0U), PrevDLT(NULL) {
Chris Lattner
committed
DW = 0; MMI = 0;
VerboseAsm = getVerboseAsm(VDef);
Evan Cheng
committed
}
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
}
/// getFunctionNumber - Return a unique ID for the current function.
///
unsigned AsmPrinter::getFunctionNumber() const {
return MF->getFunctionNumber();
}
TargetLoweringObjectFile &AsmPrinter::getObjFileLowering() const {
return TM.getTargetLowering()->getObjFileLowering();
}
Chris Lattner
committed
/// getCurrentSection() - Return the current section we are emitting to.
const MCSection *AsmPrinter::getCurrentSection() const {
return OutStreamer.getCurrentSection();
Chris Lattner
committed
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(*MAI);
// Allow the target to emit any magic that it wants at the start of the file.
EmitStartOfAsmFile(M);
// 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(O, *this, *MAI);
Gordon Henriksen
committed
O << MAI->getCommentString() << " Start of file scope inline assembly\n"
<< '\n' << MAI->getCommentString()
<< " End of file scope inline assembly\n";
Chris Lattner
committed
MMI = getAnalysisIfAvailable<MachineModuleInfo>();
if (MMI)
MMI->AnalyzeModule(M);
DW = getAnalysisIfAvailable<DwarfWriter>();
Chris Lattner
committed
DW->BeginModule(&M, MMI, O, this, MAI);
return false;
}
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
void AsmPrinter::EmitLinkage(unsigned Linkage, MCSymbol *GVSym) {
switch ((GlobalValue::LinkageTypes)Linkage) {
case GlobalValue::CommonLinkage:
case GlobalValue::LinkOnceAnyLinkage:
case GlobalValue::LinkOnceODRLinkage:
case GlobalValue::WeakAnyLinkage:
case GlobalValue::WeakODRLinkage:
case GlobalValue::LinkerPrivateLinkage:
if (MAI->getWeakDefDirective() != 0) {
// .globl _foo
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global);
// .weak_definition _foo
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_WeakDefinition);
} else if (const char *LinkOnce = MAI->getLinkOnceDirective()) {
// .globl _foo
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global);
// FIXME: linkonce should be a section attribute, handled by COFF Section
// assignment.
// http://sourceware.org/binutils/docs-2.20/as/Linkonce.html#Linkonce
// .linkonce same_size
O << LinkOnce;
} else {
// .weak _foo
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak);
}
break;
case GlobalValue::DLLExportLinkage:
case GlobalValue::AppendingLinkage:
// FIXME: appending linkage variables should go into a section of
// their name or something. For now, just emit them as external.
case GlobalValue::ExternalLinkage:
// If external or appending, declare as a global symbol.
// .globl _foo
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global);
break;
case GlobalValue::PrivateLinkage:
case GlobalValue::InternalLinkage:
break;
default:
llvm_unreachable("Unknown linkage type!");
}
}
/// 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;
Loading
Loading full blame...