"llvm/lib/Target/git@repo.hca.bsc.es:rferrer/llvm-epi-0.8.git" did not exist on "e97bd81f074cf3eae8a12678bc11faa712b03983"
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.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "asm-printer"
#include "llvm/CodeGen/AsmPrinter.h"
#include "DwarfDebug.h"
#include "DwarfException.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/Analysis/ConstantFolding.h"
Argyrios Kyrtzidis
committed
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/MC/MCAsmInfo.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"
#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/TargetRegisterInfo.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Timer.h"
using namespace llvm;
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");
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;
}
AsmPrinter::AsmPrinter(TargetMachine &tm, MCStreamer &Streamer)
: MachineFunctionPass(&ID),
TM(tm), MAI(tm.getMCAsmInfo()),
OutContext(Streamer.getContext()),
OutStreamer(Streamer),
Devang Patel
committed
LastMI(0), LastFn(0), Counter(~0U), SetCounter(0) {
DD = 0; DE = 0; MMI = 0; LI = 0;
GCMetadataPrinters = 0;
VerboseAsm = Streamer.isVerboseAsm();
Evan Cheng
committed
}
Gordon Henriksen
committed
AsmPrinter::~AsmPrinter() {
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;
}
Chris Lattner
committed
delete &OutStreamer;
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();
}
/// getTargetData - Return information about data layout.
const TargetData &AsmPrinter::getTargetData() const {
return *TM.getTargetData();
}
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<MachineModuleInfo>();
AU.addRequired<GCModuleInfo>();
if (isVerbose())
Gordon Henriksen
committed
}
bool AsmPrinter::doInitialization(Module &M) {
MMI->AnalyzeModule(M);
// 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);
// 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))
// 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(), 0/*no loc cookie*/);
OutStreamer.AddComment("End of file scope inline assembly");
OutStreamer.AddBlankLine();
}
if (MAI->doesSupportDebugInformation())
DD = new DwarfDebug(this, &M);
if (MAI->doesSupportExceptionHandling())
DE = new DwarfException(this);
return false;
}
void AsmPrinter::EmitLinkage(unsigned Linkage, MCSymbol *GVSym) const {
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 discard
// FIXME: It would be nice to use .linkonce samesize for non-common
// globals.
OutStreamer.EmitRawText(StringRef(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;
// Check to see if this is a special global used by LLVM, if so, emit it.
if (EmitSpecialLLVMGlobal(GV))
return;
MCSymbol *GVSym = Mang->getSymbol(GV);
EmitVisibility(GVSym, GV->getVisibility());
if (MAI->hasDotTypeDotSizeDirective())
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject);
SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GV, TM);
const TargetData *TD = TM.getTargetData();
unsigned Size = TD->getTypeAllocSize(GV->getType()->getElementType());
unsigned AlignLog = TD->getPreferredAlignmentLog(GV);
// 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 (isVerbose()) {
WriteAsOperand(OutStreamer.GetCommentOS(), GV,
/*PrintType=*/false, GV->getParent());
OutStreamer.GetCommentOS() << '\n';
// Handle common symbols.
if (GVKind.isCommon()) {
// .comm _foo, 42, 4
Chris Lattner
committed
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 (MAI->hasLCOMMDirective()) {
// .lcomm _foo, 42
OutStreamer.EmitLocalCommonSymbol(GVSym, Size);
return;
// .local _foo
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Local);
// .comm _foo, 42, 4
OutStreamer.EmitCommonSymbol(GVSym, Size, 1 << AlignLog);
return;
}
const MCSection *TheSection =
getObjFileLowering().SectionForGlobal(GV, GVKind, Mang, TM);
// Handle the zerofill directive on darwin, which is a special form of BSS
// emission.
if (GVKind.isBSSExtern() && MAI->hasMachoZeroFillDirective()) {
// .globl _foo
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global);
// .zerofill __DATA, __common, _foo, 400, 5
OutStreamer.EmitZerofill(TheSection, GVSym, Size, 1 << AlignLog);
return;
}
OutStreamer.SwitchSection(TheSection);
EmitLinkage(GV->getLinkage(), GVSym);
EmitAlignment(AlignLog, GV);
if (isVerbose()) {
WriteAsOperand(OutStreamer.GetCommentOS(), GV,
/*PrintType=*/false, GV->getParent());
OutStreamer.GetCommentOS() << '\n';
OutStreamer.EmitLabel(GVSym);
EmitGlobalConstant(GV->getInitializer());
if (MAI->hasDotTypeDotSizeDirective())
OutStreamer.EmitELFSize(GVSym, MCConstantExpr::Create(Size, OutContext));
OutStreamer.AddBlankLine();
}
/// EmitFunctionHeader - This method emits the header for the current
/// function.
void AsmPrinter::EmitFunctionHeader() {
// Print out constants referenced by the function
EmitConstantPool();
// Print the 'header' of function.
const Function *F = MF->getFunction();
OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
EmitVisibility(CurrentFnSym, F->getVisibility());
EmitLinkage(F->getLinkage(), CurrentFnSym);
EmitAlignment(MF->getAlignment(), F);
if (MAI->hasDotTypeDotSizeDirective())
OutStreamer.EmitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction);
if (isVerbose()) {
WriteAsOperand(OutStreamer.GetCommentOS(), F,
/*PrintType=*/false, F->getParent());
OutStreamer.GetCommentOS() << '\n';
}
// Emit the CurrentFnSym. This is a virtual function to allow targets to
// do their wild and crazy things as required.
EmitFunctionEntryLabel();
// If the function had address-taken blocks that got deleted, then we have
// references to the dangling symbols. Emit them at the start of the function
// so that we don't get references to undefined symbols.
std::vector<MCSymbol*> DeadBlockSyms;
MMI->takeDeletedSymbolsForFunction(F, DeadBlockSyms);
for (unsigned i = 0, e = DeadBlockSyms.size(); i != e; ++i) {
OutStreamer.AddComment("Address taken block that was later removed");
OutStreamer.EmitLabel(DeadBlockSyms[i]);
}
// Add some workaround for linkonce linkage on Cygwin\MinGW.
if (MAI->getLinkOnceDirective() != 0 &&
(F->hasLinkOnceLinkage() || F->hasWeakLinkage())) {
MCSymbol *FakeStub =
OutContext.GetOrCreateSymbol(Twine("Lllvm$workaround$fake$stub$")+
CurrentFnSym->getName());
OutStreamer.EmitLabel(FakeStub);
}
// Emit pre-function debug and/or EH information.
if (DE) {
if (TimePassesIsEnabled) {
NamedRegionTimer T(EHTimerName, DWARFGroupName);
DE->BeginFunction(MF);
} else {
DE->BeginFunction(MF);
}
}
if (DD) {
if (TimePassesIsEnabled) {
NamedRegionTimer T(DbgTimerName, DWARFGroupName);
DD->beginFunction(MF);
} else {
DD->beginFunction(MF);
}
}
}
/// EmitFunctionEntryLabel - Emit the label that is the entrypoint for the
/// function. This can be overridden by targets as required to do custom stuff.
void AsmPrinter::EmitFunctionEntryLabel() {
OutStreamer.EmitLabel(CurrentFnSym);
}
/// EmitComments - Pretty-print comments for instructions.
static void EmitComments(const MachineInstr &MI, raw_ostream &CommentOS) {
const MachineFunction *MF = MI.getParent()->getParent();
const TargetMachine &TM = MF->getTarget();
DebugLoc DL = MI.getDebugLoc();
if (!DL.isUnknown()) { // Print source line info.
DIScope Scope(DL.getScope(MF->getFunction()->getContext()));
// Omit the directory, because it's likely to be long and uninteresting.
CommentOS << Scope.getFilename();
else
CommentOS << "<unknown>";
CommentOS << ':' << DL.getLine();
if (DL.getCol() != 0)
CommentOS << ':' << DL.getCol();
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
CommentOS << '\n';
}
// Check for spills and reloads
int FI;
const MachineFrameInfo *FrameInfo = MF->getFrameInfo();
// We assume a single instruction only has a spill or reload, not
// both.
const MachineMemOperand *MMO;
if (TM.getInstrInfo()->isLoadFromStackSlotPostFE(&MI, FI)) {
if (FrameInfo->isSpillSlotObjectIndex(FI)) {
MMO = *MI.memoperands_begin();
CommentOS << MMO->getSize() << "-byte Reload\n";
}
} else if (TM.getInstrInfo()->hasLoadFromStackSlot(&MI, MMO, FI)) {
if (FrameInfo->isSpillSlotObjectIndex(FI))
CommentOS << MMO->getSize() << "-byte Folded Reload\n";
} else if (TM.getInstrInfo()->isStoreToStackSlotPostFE(&MI, FI)) {
if (FrameInfo->isSpillSlotObjectIndex(FI)) {
MMO = *MI.memoperands_begin();
CommentOS << MMO->getSize() << "-byte Spill\n";
}
} else if (TM.getInstrInfo()->hasStoreToStackSlot(&MI, MMO, FI)) {
if (FrameInfo->isSpillSlotObjectIndex(FI))
CommentOS << MMO->getSize() << "-byte Folded Spill\n";
}
// Check for spill-induced copies
unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
if (TM.getInstrInfo()->isMoveInstr(MI, SrcReg, DstReg,
SrcSubIdx, DstSubIdx)) {
if (MI.getAsmPrinterFlag(MachineInstr::ReloadReuse))
CommentOS << " Reload Reuse\n";
}
}
/// EmitImplicitDef - This method emits the specified machine instruction
/// that is an implicit def.
static void EmitImplicitDef(const MachineInstr *MI, AsmPrinter &AP) {
unsigned RegNo = MI->getOperand(0).getReg();
AP.OutStreamer.AddComment(Twine("implicit-def: ") +
AP.TM.getRegisterInfo()->getName(RegNo));
AP.OutStreamer.AddBlankLine();
}
static void EmitKill(const MachineInstr *MI, AsmPrinter &AP) {
std::string Str = "kill:";
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
const MachineOperand &Op = MI->getOperand(i);
assert(Op.isReg() && "KILL instruction must have only register operands");
Str += ' ';
Str += AP.TM.getRegisterInfo()->getName(Op.getReg());
Str += (Op.isDef() ? "<def>" : "<kill>");
}
AP.OutStreamer.AddComment(Str);
AP.OutStreamer.AddBlankLine();
}
/// EmitDebugValueComment - This method handles the target-independent form
/// of DBG_VALUE, returning true if it was able to do so. A false return
/// means the target will need to handle MI in EmitInstruction.
static bool EmitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) {
// This code handles only the 3-operand target-independent form.
if (MI->getNumOperands() != 3)
return false;
SmallString<128> Str;
raw_svector_ostream OS(Str);
OS << '\t' << AP.MAI->getCommentString() << "DEBUG_VALUE: ";
// cast away const; DIetc do not take const operands for some reason.
DIVariable V(const_cast<MDNode*>(MI->getOperand(2).getMetadata()));
// Register or immediate value. Register 0 means undef.
if (MI->getOperand(0).isFPImm()) {
APFloat APF = APFloat(MI->getOperand(0).getFPImm()->getValueAPF());
if (MI->getOperand(0).getFPImm()->getType()->isFloatTy()) {
} else if (MI->getOperand(0).getFPImm()->getType()->isDoubleTy()) {
} else {
// There is no good way to print long double. Convert a copy to
// double. Ah well, it's only a comment.
bool ignored;
APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven,
&ignored);
}
} else if (MI->getOperand(0).isImm()) {
} else {
assert(MI->getOperand(0).isReg() && "Unknown operand type");
if (MI->getOperand(0).getReg() == 0) {
// Suppress offset, it is not meaningful here.
// NOTE: Want this comment at start of line, don't emit with AddComment.
return true;
}
OS << AP.TM.getRegisterInfo()->getName(MI->getOperand(0).getReg());
// NOTE: Want this comment at start of line, don't emit with AddComment.
return true;
}
/// EmitFunctionBody - This method emits the body and trailer for a
/// function.
void AsmPrinter::EmitFunctionBody() {
Chris Lattner
committed
// Emit target-specific gunk before the function body.
EmitFunctionBodyStart();
bool ShouldPrintDebugScopes = DD && MMI->hasDebugInfo();
// Print out code for the function.
bool HasAnyRealCode = false;
for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
I != E; ++I) {
// Print a label for the basic block.
EmitBasicBlockStart(I);
for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
II != IE; ++II) {
// Print the assembly for the instruction.
if (!II->isLabel())
HasAnyRealCode = true;
++EmittedInsts;
if (ShouldPrintDebugScopes) {
if (TimePassesIsEnabled) {
NamedRegionTimer T(DbgTimerName, DWARFGroupName);
DD->beginScope(II);
} else {
DD->beginScope(II);
}
}
if (isVerbose())
EmitComments(*II, OutStreamer.GetCommentOS());
switch (II->getOpcode()) {
case TargetOpcode::DBG_LABEL:
case TargetOpcode::EH_LABEL:
case TargetOpcode::GC_LABEL:
OutStreamer.EmitLabel(II->getOperand(0).getMCSymbol());
case TargetOpcode::INLINEASM:
EmitInlineAsm(II);
case TargetOpcode::DBG_VALUE:
if (isVerbose()) {
if (!EmitDebugValueComment(II, *this))
EmitInstruction(II);
}
break;
case TargetOpcode::IMPLICIT_DEF:
if (isVerbose()) EmitImplicitDef(II, *this);
case TargetOpcode::KILL:
if (isVerbose()) EmitKill(II, *this);
break;
default:
EmitInstruction(II);
break;
}
if (ShouldPrintDebugScopes) {
if (TimePassesIsEnabled) {
NamedRegionTimer T(DbgTimerName, DWARFGroupName);
DD->endScope(II);
} else {
DD->endScope(II);
}
}
}
}
// If the function is empty and the object file uses .subsections_via_symbols,
// then we need to emit *something* to the function body to prevent the
// labels from collapsing together. Just emit a 0 byte.
if (MAI->hasSubsectionsViaSymbols() && !HasAnyRealCode)
OutStreamer.EmitIntValue(0, 1, 0/*addrspace*/);
Chris Lattner
committed
// Emit target-specific gunk after the function body.
EmitFunctionBodyEnd();
// If the target wants a .size directive for the size of the function, emit
// it.
if (MAI->hasDotTypeDotSizeDirective()) {
// Create a symbol for the end of function, so we can get the size as
// difference between the function label and the temp label.
MCSymbol *FnEndLabel = OutContext.CreateTempSymbol();
OutStreamer.EmitLabel(FnEndLabel);
const MCExpr *SizeExp =
MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(FnEndLabel, OutContext),
MCSymbolRefExpr::Create(CurrentFnSym, OutContext),
OutContext);
OutStreamer.EmitELFSize(CurrentFnSym, SizeExp);
// Emit post-function debug information.
if (DD) {
if (TimePassesIsEnabled) {
NamedRegionTimer T(DbgTimerName, DWARFGroupName);
DD->endFunction(MF);
} else {
DD->endFunction(MF);
}
}
if (DE) {
if (TimePassesIsEnabled) {
NamedRegionTimer T(EHTimerName, DWARFGroupName);
DE->EndFunction();
} else {
DE->EndFunction();
}
}
MMI->EndFunction();
// Print out jump tables referenced by the function.
EmitJumpTableInfo();
OutStreamer.AddBlankLine();
}
bool AsmPrinter::doFinalization(Module &M) {
// Emit global variables.
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I)
EmitGlobalVariable(I);
// Finalize debug and EH information.
if (DE) {
if (TimePassesIsEnabled) {
NamedRegionTimer T(EHTimerName, DWARFGroupName);
DE->EndModule();
} else {
DE->EndModule();
}
delete DE; DE = 0;
}
if (DD) {
if (TimePassesIsEnabled) {
NamedRegionTimer T(DbgTimerName, DWARFGroupName);
DD->endModule();
} else {
DD->endModule();
}
delete DD; DD = 0;
}
// If the target wants to know about weak references, print them all.
if (MAI->getWeakRefDirective()) {
// 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.
// 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()) continue;
OutStreamer.EmitSymbolAttribute(Mang->getSymbol(I), MCSA_WeakReference);
for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) {
if (!I->hasExternalWeakLinkage()) continue;
OutStreamer.EmitSymbolAttribute(Mang->getSymbol(I), MCSA_WeakReference);
if (MAI->hasSetDirective()) {
OutStreamer.AddBlankLine();
for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end();
I != E; ++I) {
MCSymbol *Name = Mang->getSymbol(I);
Anton Korobeynikov
committed
const GlobalValue *GV = cast<GlobalValue>(I->getAliasedGlobal());
MCSymbol *Target = Mang->getSymbol(GV);
if (I->hasExternalLinkage() || !MAI->getWeakRefDirective())
OutStreamer.EmitSymbolAttribute(Name, MCSA_Global);
else if (I->hasWeakLinkage())
OutStreamer.EmitSymbolAttribute(Name, MCSA_WeakReference);
assert(I->hasLocalLinkage() && "Invalid alias linkage");
EmitVisibility(Name, I->getVisibility());
// Emit the directives as assignments aka .set:
OutStreamer.EmitAssignment(Name,
MCSymbolRefExpr::Create(Target, OutContext));
}
}
GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>();
assert(MI && "AsmPrinter didn't require GCModuleInfo?");
for (GCModuleInfo::iterator I = MI->end(), E = MI->begin(); I != E; )
if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*--I))
Gordon Henriksen
committed
// If we don't have any trampolines, then we don't require stack memory
// to be executable. Some targets have a directive to declare this.
Function *InitTrampolineIntrinsic = M.getFunction("llvm.init.trampoline");
if (!InitTrampolineIntrinsic || InitTrampolineIntrinsic->use_empty())
if (MCSection *S = MAI->getNonexecutableStackSection(OutContext))
OutStreamer.SwitchSection(S);
// Allow the target to emit any magic that it wants at the end of the file,
// after everything else has gone out.
EmitEndOfAsmFile(M);
delete Mang; Mang = 0;
Chris Lattner
committed
OutStreamer.Finish();
return false;
}
void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
CurrentFnSym = Mang->getSymbol(MF.getFunction());
if (isVerbose())
Evan Cheng
committed
namespace {
// SectionCPs - Keep track the alignment, constpool entries per Section.
struct SectionCPs {
const MCSection *S;
Evan Cheng
committed
unsigned Alignment;
SmallVector<unsigned, 4> CPEs;
Douglas Gregor
committed
SectionCPs(const MCSection *s, unsigned a) : S(s), Alignment(a) {}
Evan Cheng
committed
};
}
Chris Lattner
committed
/// EmitConstantPool - Print to the current output stream assembly
/// representations of the constants in the constant pool MCP. This is
/// used to print out constants which have been "spilled to memory" by
/// the code generator.
///
void AsmPrinter::EmitConstantPool() {
const MachineConstantPool *MCP = MF->getConstantPool();
const std::vector<MachineConstantPoolEntry> &CP = MCP->getConstants();
Chris Lattner
committed
if (CP.empty()) return;
// Calculate sections for constant pool entries. We collect entries to go into
// the same section together to reduce amount of section switch statements.
Evan Cheng
committed
SmallVector<SectionCPs, 4> CPSections;
for (unsigned i = 0, e = CP.size(); i != e; ++i) {
const MachineConstantPoolEntry &CPE = CP[i];
Evan Cheng
committed
unsigned Align = CPE.getAlignment();
SectionKind Kind;
switch (CPE.getRelocationInfo()) {
default: llvm_unreachable("Unknown section kind");
case 2: Kind = SectionKind::getReadOnlyWithRel(); break;
case 1:
Kind = SectionKind::getReadOnlyWithRelLocal();
break;
switch (TM.getTargetData()->getTypeAllocSize(CPE.getType())) {
case 4: Kind = SectionKind::getMergeableConst4(); break;
case 8: Kind = SectionKind::getMergeableConst8(); break;
case 16: Kind = SectionKind::getMergeableConst16();break;
default: Kind = SectionKind::getMergeableConst(); break;
const MCSection *S = getObjFileLowering().getSectionForConstant(Kind);
Evan Cheng
committed
// The number of sections are small, just do a linear search from the
// last section to the first.
bool Found = false;
unsigned SecIdx = CPSections.size();
while (SecIdx != 0) {
if (CPSections[--SecIdx].S == S) {
Found = true;
break;
}
}
if (!Found) {
SecIdx = CPSections.size();
CPSections.push_back(SectionCPs(S, Align));
}
if (Align > CPSections[SecIdx].Alignment)
CPSections[SecIdx].Alignment = Align;
CPSections[SecIdx].CPEs.push_back(i);
}
// Now print stuff into the calculated sections.
Evan Cheng
committed
for (unsigned i = 0, e = CPSections.size(); i != e; ++i) {
OutStreamer.SwitchSection(CPSections[i].S);
Evan Cheng
committed
EmitAlignment(Log2_32(CPSections[i].Alignment));
Evan Cheng
committed
unsigned Offset = 0;
for (unsigned j = 0, ee = CPSections[i].CPEs.size(); j != ee; ++j) {
unsigned CPI = CPSections[i].CPEs[j];
MachineConstantPoolEntry CPE = CP[CPI];
// Emit inter-object padding for alignment.
unsigned AlignMask = CPE.getAlignment() - 1;
unsigned NewOffset = (Offset + AlignMask) & ~AlignMask;
OutStreamer.EmitFill(NewOffset - Offset, 0/*fillval*/, 0/*addrspace*/);
Evan Cheng
committed
const Type *Ty = CPE.getType();
Offset = NewOffset + TM.getTargetData()->getTypeAllocSize(Ty);
// Emit the label with a comment on it.
if (isVerbose()) {
OutStreamer.GetCommentOS() << "constant pool ";
WriteTypeSymbolic(OutStreamer.GetCommentOS(), CPE.getType(),
MF->getFunction()->getParent());
OutStreamer.GetCommentOS() << '\n';
Evan Cheng
committed
}
OutStreamer.EmitLabel(GetCPISymbol(CPI));
Evan Cheng
committed
if (CPE.isMachineConstantPoolEntry())
EmitMachineConstantPoolValue(CPE.Val.MachineCPVal);
else
Evan Cheng
committed
EmitGlobalConstant(CPE.Val.ConstVal);
Chris Lattner
committed
}
}
/// EmitJumpTableInfo - Print assembly representations of the jump tables used
/// by the current function to the current output stream.
///
void AsmPrinter::EmitJumpTableInfo() {
const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
if (MJTI == 0) return;
if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_Inline) return;
const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
if (JT.empty()) return;
Anton Korobeynikov
committed
// Pick the directive to use to print the jump table entries, and switch to
// the appropriate section.
const Function *F = MF->getFunction();
Evan Cheng
committed
bool JTInDiffSection = false;
if (// In PIC mode, we need to emit the jump table to the same section as the
// function body itself, otherwise the label differences won't make sense.
// FIXME: Need a better predicate for this: what about custom entries?
MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 ||
// We should also do if the section name is NULL or function is declared
// in discardable section
// FIXME: this isn't the right predicate, should be based on the MCSection
// for the function.
F->isWeakForLinker()) {
OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F,Mang,TM));
// Otherwise, drop it in the readonly section.
const MCSection *ReadOnlySection =
getObjFileLowering().getSectionForConstant(SectionKind::getReadOnly());
OutStreamer.SwitchSection(ReadOnlySection);
Evan Cheng
committed
JTInDiffSection = true;
EmitAlignment(Log2_32(MJTI->getEntryAlignment(*TM.getTargetData())));
Chris Lattner
committed
for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) {
const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
// If this jump table was deleted, ignore it.
if (JTBBs.empty()) continue;
// For the EK_LabelDifference32 entry, if the target supports .set, emit a
// .set directive for each unique entry. This reduces the number of
// relocations the assembler will generate for the jump table.
if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 &&
MAI->hasSetDirective()) {
SmallPtrSet<const MachineBasicBlock*, 16> EmittedSets;
const TargetLowering *TLI = TM.getTargetLowering();
const MCExpr *Base = TLI->getPICJumpTableRelocBaseExpr(MF,JTI,OutContext);
for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) {
const MachineBasicBlock *MBB = JTBBs[ii];
if (!EmittedSets.insert(MBB)) continue;
// .set LJTSet, LBB32-base
const MCExpr *LHS =
MCSymbolRefExpr::Create(MBB->getSymbol(), OutContext);
OutStreamer.EmitAssignment(GetJTSetSymbol(JTI, MBB->getNumber()),
MCBinaryExpr::CreateSub(LHS, Base, OutContext));
// On some targets (e.g. Darwin) we want to emit two consequtive labels
Chris Lattner
committed
// before each jump table. The first label is never referenced, but tells
// the assembler and linker the extents of the jump table object. The
// second label is actually referenced by the code.
if (JTInDiffSection && MAI->getLinkerPrivateGlobalPrefix()[0])
// FIXME: This doesn't have to have any specific name, just any randomly
// named and numbered 'l' label would work. Simplify GetJTISymbol.
OutStreamer.EmitLabel(GetJTISymbol(JTI, true));
OutStreamer.EmitLabel(GetJTISymbol(JTI));
for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii)
EmitJumpTableEntry(MJTI, JTBBs[ii], JTI);
}
}
/// EmitJumpTableEntry - Emit a jump table entry for the specified MBB to the
/// current stream.
void AsmPrinter::EmitJumpTableEntry(const MachineJumpTableInfo *MJTI,
const MachineBasicBlock *MBB,
unsigned UID) const {
const MCExpr *Value = 0;
switch (MJTI->getEntryKind()) {
case MachineJumpTableInfo::EK_Inline:
llvm_unreachable("Cannot emit EK_Inline jump table entry"); break;
case MachineJumpTableInfo::EK_Custom32:
Value = TM.getTargetLowering()->LowerCustomJumpTableEntry(MJTI, MBB, UID,
OutContext);
break;
case MachineJumpTableInfo::EK_BlockAddress:
// EK_BlockAddress - Each entry is a plain address of block, e.g.:
// .word LBB123
Value = MCSymbolRefExpr::Create(MBB->getSymbol(), OutContext);
break;
case MachineJumpTableInfo::EK_GPRel32BlockAddress: {
// EK_GPRel32BlockAddress - Each entry is an address of block, encoded
// with a relocation as gp-relative, e.g.:
// .gprel32 LBB123
MCSymbol *MBBSym = MBB->getSymbol();
OutStreamer.EmitGPRel32Value(MCSymbolRefExpr::Create(MBBSym, OutContext));
Anton Korobeynikov
committed
}
case MachineJumpTableInfo::EK_LabelDifference32: {
// EK_LabelDifference32 - Each entry is the address of the block minus
// the address of the jump table. This is used for PIC jump tables where
// gprel32 is not supported. e.g.:
// .word LBB123 - LJTI1_2
// If the .set directive is supported, this is emitted as:
// .set L4_5_set_123, LBB123 - LJTI1_2
// .word L4_5_set_123
// If we have emitted set directives for the jump table entries, print
// them rather than the entries themselves. If we're emitting PIC, then
// emit the table entries as differences between two text section labels.
if (MAI->hasSetDirective()) {
// If we used .set, reference the .set's symbol.
Value = MCSymbolRefExpr::Create(GetJTSetSymbol(UID, MBB->getNumber()),
OutContext);
break;
}
// Otherwise, use the difference as the jump table entry.
Value = MCSymbolRefExpr::Create(MBB->getSymbol(), OutContext);
const MCExpr *JTI = MCSymbolRefExpr::Create(GetJTISymbol(UID), OutContext);
Value = MCBinaryExpr::CreateSub(Value, JTI, OutContext);
break;
}
Anton Korobeynikov
committed
}
assert(Value && "Unknown entry kind!");
unsigned EntrySize = MJTI->getEntrySize(*TM.getTargetData());
OutStreamer.EmitValue(Value, EntrySize, /*addrspace*/0);
Anton Korobeynikov
committed
}
/// EmitSpecialLLVMGlobal - Check to see if the specified global is a
/// special global used by LLVM. If so, emit it and return true, otherwise
/// do nothing and return false.
bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) {
if (MAI->hasNoDeadStrip()) // No need to emit this at all.
EmitLLVMUsedList(GV->getInitializer());
return true;
}
Chris Lattner
committed
// Ignore debug and non-emitted data. This handles llvm.compiler.used.
if (GV->getSection() == "llvm.metadata" ||
GV->hasAvailableExternallyLinkage())
return true;
if (!GV->hasAppendingLinkage()) return false;
assert(GV->hasInitializer() && "Not a special LLVM global!");
Evan Cheng
committed
const TargetData *TD = TM.getTargetData();
unsigned Align = Log2_32(TD->getPointerPrefAlignment());
if (GV->getName() == "llvm.global_ctors") {
OutStreamer.SwitchSection(getObjFileLowering().getStaticCtorSection());
EmitAlignment(Align, 0);
EmitXXStructorList(GV->getInitializer());
if (TM.getRelocationModel() == Reloc::Static &&
MAI->hasStaticCtorDtorReferenceInStaticMode()) {
StringRef Sym(".constructors_used");
OutStreamer.EmitSymbolAttribute(OutContext.GetOrCreateSymbol(Sym),
MCSA_Reference);
return true;