summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/AsmPrinter/AsmPrinter.cpp')
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinter.cpp199
1 files changed, 94 insertions, 105 deletions
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 988381d..07d6731 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -77,11 +77,11 @@ static gcp_map_type &getGCMap(void *&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 DataLayout &TD,
+static unsigned getGVAlignmentLog2(const GlobalValue *GV, const DataLayout &DL,
unsigned InBits = 0) {
unsigned NumBits = 0;
if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV))
- NumBits = TD.getPreferredAlignmentLog(GVar);
+ NumBits = DL.getPreferredAlignmentLog(GVar);
// If InBits is specified, round it to it.
if (InBits > NumBits)
@@ -103,12 +103,14 @@ static unsigned getGVAlignmentLog2(const GlobalValue *GV, const DataLayout &TD,
AsmPrinter::AsmPrinter(TargetMachine &tm, std::unique_ptr<MCStreamer> Streamer)
: MachineFunctionPass(ID), TM(tm), MAI(tm.getMCAsmInfo()),
OutContext(Streamer->getContext()), OutStreamer(*Streamer.release()),
- LastMI(nullptr), LastFn(0), Counter(~0U), SetCounter(0) {
+ LastMI(nullptr), LastFn(0), Counter(~0U) {
DD = nullptr;
MMI = nullptr;
LI = nullptr;
MF = nullptr;
- CurrentFnSym = CurrentFnSymForSize = nullptr;
+ CurExceptionSym = CurrentFnSym = CurrentFnSymForSize = nullptr;
+ CurrentFnBegin = nullptr;
+ CurrentFnEnd = nullptr;
GCMetadataPrinters = nullptr;
VerboseAsm = OutStreamer.isVerboseAsm();
}
@@ -219,9 +221,13 @@ bool AsmPrinter::doInitialization(Module &M) {
// Emit module-level inline asm if it exists.
if (!M.getModuleInlineAsm().empty()) {
+ // We're at the module level. Construct MCSubtarget from the default CPU
+ // and target triple.
+ std::unique_ptr<MCSubtargetInfo> STI(TM.getTarget().createMCSubtargetInfo(
+ TM.getTargetTriple(), TM.getTargetCPU(), TM.getTargetFeatureString()));
OutStreamer.AddComment("Start of file scope inline assembly");
OutStreamer.AddBlankLine();
- EmitInlineAsm(M.getModuleInlineAsm()+"\n");
+ EmitInlineAsm(M.getModuleInlineAsm()+"\n", *STI);
OutStreamer.AddComment("End of file scope inline assembly");
OutStreamer.AddBlankLine();
}
@@ -525,7 +531,8 @@ void AsmPrinter::EmitFunctionHeader() {
EmitVisibility(CurrentFnSym, F->getVisibility());
EmitLinkage(F, CurrentFnSym);
- EmitAlignment(MF->getAlignment(), F);
+ if (MAI->hasFunctionAlignment())
+ EmitAlignment(MF->getAlignment(), F);
if (MAI->hasDotTypeDotSizeDirective())
OutStreamer.EmitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction);
@@ -554,6 +561,17 @@ void AsmPrinter::EmitFunctionHeader() {
OutStreamer.EmitLabel(DeadBlockSyms[i]);
}
+ if (CurrentFnBegin) {
+ if (MAI->useAssignmentForEHBegin()) {
+ MCSymbol *CurPos = OutContext.CreateTempSymbol();
+ OutStreamer.EmitLabel(CurPos);
+ OutStreamer.EmitAssignment(CurrentFnBegin,
+ MCSymbolRefExpr::Create(CurPos, OutContext));
+ } else {
+ OutStreamer.EmitLabel(CurrentFnBegin);
+ }
+ }
+
// Emit pre-function debug and/or EH information.
for (const HandlerInfo &HI : Handlers) {
NamedRegionTimer T(HI.TimerName, HI.TimerGroupName, TimePassesIsEnabled);
@@ -764,6 +782,8 @@ void AsmPrinter::emitFrameAlloc(const MachineInstr &MI) {
/// EmitFunctionBody - This method emits the body and trailer for a
/// function.
void AsmPrinter::EmitFunctionBody() {
+ EmitFunctionHeader();
+
// Emit target-specific gunk before the function body.
EmitFunctionBodyStart();
@@ -867,32 +887,41 @@ void AsmPrinter::EmitFunctionBody() {
// Emit target-specific gunk after the function body.
EmitFunctionBodyEnd();
+ if (!MMI->getLandingPads().empty() || MMI->hasDebugInfo() ||
+ MAI->hasDotTypeDotSizeDirective()) {
+ // Create a symbol for the end of function.
+ CurrentFnEnd = createTempSymbol("func_end");
+ OutStreamer.EmitLabel(CurrentFnEnd);
+ }
+
// 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);
-
+ // We can get the size as difference between the function label and the
+ // temp label.
const MCExpr *SizeExp =
- MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(FnEndLabel, OutContext),
+ MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(CurrentFnEnd, OutContext),
MCSymbolRefExpr::Create(CurrentFnSymForSize,
OutContext),
OutContext);
OutStreamer.EmitELFSize(CurrentFnSym, SizeExp);
}
- // Emit post-function debug and/or EH information.
for (const HandlerInfo &HI : Handlers) {
NamedRegionTimer T(HI.TimerName, HI.TimerGroupName, TimePassesIsEnabled);
- HI.Handler->endFunction(MF);
+ HI.Handler->markFunctionEnd();
}
- MMI->EndFunction();
// Print out jump tables referenced by the function.
EmitJumpTableInfo();
+ // Emit post-function debug and/or EH information.
+ for (const HandlerInfo &HI : Handlers) {
+ NamedRegionTimer T(HI.TimerName, HI.TimerGroupName, TimePassesIsEnabled);
+ HI.Handler->endFunction(MF);
+ }
+ MMI->EndFunction();
+
OutStreamer.AddBlankLine();
}
@@ -928,7 +957,7 @@ static bool isGOTEquivalentCandidate(const GlobalVariable *GV,
// To be a got equivalent, at least one of its users need to be a constant
// expression used by another global variable.
for (auto *U : GV->users())
- NumGOTEquivUsers += getNumGlobalVariableUses(cast<Constant>(U));
+ NumGOTEquivUsers += getNumGlobalVariableUses(dyn_cast<Constant>(U));
return NumGOTEquivUsers > 0;
}
@@ -961,17 +990,25 @@ void AsmPrinter::emitGlobalGOTEquivs() {
if (!getObjFileLowering().supportIndirectSymViaGOTPCRel())
return;
- while (!GlobalGOTEquivs.empty()) {
- DenseMap<const MCSymbol *, GOTEquivUsePair>::iterator I =
- GlobalGOTEquivs.begin();
- const MCSymbol *S = I->first;
- const GlobalVariable *GV = I->second.first;
- GlobalGOTEquivs.erase(S);
- EmitGlobalVariable(GV);
+ SmallVector<const GlobalVariable *, 8> FailedCandidates;
+ for (auto &I : GlobalGOTEquivs) {
+ const GlobalVariable *GV = I.second.first;
+ unsigned Cnt = I.second.second;
+ if (Cnt)
+ FailedCandidates.push_back(GV);
}
+ GlobalGOTEquivs.clear();
+
+ for (auto *GV : FailedCandidates)
+ EmitGlobalVariable(GV);
}
bool AsmPrinter::doFinalization(Module &M) {
+ // Set the MachineFunction to nullptr so that we can catch attempted
+ // accesses to MF specific features at the module level and so that
+ // we can conditionalize accesses based on whether or not it is nullptr.
+ MF = nullptr;
+
// Gather all GOT equivalent globals in the module. We really need two
// passes over the globals: one to compute and another to avoid its emission
// in EmitGlobalVariable, otherwise we would not be able to handle cases
@@ -997,59 +1034,6 @@ bool AsmPrinter::doFinalization(Module &M) {
EmitVisibility(Name, V, false);
}
- // Get information about jump-instruction tables to print.
- JumpInstrTableInfo *JITI = getAnalysisIfAvailable<JumpInstrTableInfo>();
-
- if (JITI && !JITI->getTables().empty()) {
- // Since we're at the module level we can't use a function specific
- // MCSubtargetInfo - instead create one with the module defaults.
- std::unique_ptr<MCSubtargetInfo> STI(TM.getTarget().createMCSubtargetInfo(
- TM.getTargetTriple(), TM.getTargetCPU(), TM.getTargetFeatureString()));
- unsigned Arch = Triple(getTargetTriple()).getArch();
- bool IsThumb = (Arch == Triple::thumb || Arch == Triple::thumbeb);
- const TargetInstrInfo *TII = TM.getSubtargetImpl()->getInstrInfo();
- MCInst TrapInst;
- TII->getTrap(TrapInst);
- unsigned LogAlignment = llvm::Log2_64(JITI->entryByteAlignment());
-
- // Emit the right section for these functions.
- OutStreamer.SwitchSection(OutContext.getObjectFileInfo()->getTextSection());
- for (const auto &KV : JITI->getTables()) {
- uint64_t Count = 0;
- for (const auto &FunPair : KV.second) {
- // Emit the function labels to make this be a function entry point.
- MCSymbol *FunSym =
- OutContext.GetOrCreateSymbol(FunPair.second->getName());
- EmitAlignment(LogAlignment);
- if (IsThumb)
- OutStreamer.EmitThumbFunc(FunSym);
- if (MAI->hasDotTypeDotSizeDirective())
- OutStreamer.EmitSymbolAttribute(FunSym, MCSA_ELF_TypeFunction);
- OutStreamer.EmitLabel(FunSym);
-
- // Emit the jump instruction to transfer control to the original
- // function.
- MCInst JumpToFun;
- MCSymbol *TargetSymbol =
- OutContext.GetOrCreateSymbol(FunPair.first->getName());
- const MCSymbolRefExpr *TargetSymRef =
- MCSymbolRefExpr::Create(TargetSymbol, MCSymbolRefExpr::VK_PLT,
- OutContext);
- TII->getUnconditionalBranch(JumpToFun, TargetSymRef);
- OutStreamer.EmitInstruction(JumpToFun, *STI);
- ++Count;
- }
-
- // Emit enough padding instructions to fill up to the next power of two.
- uint64_t Remaining = NextPowerOf2(Count) - Count;
- for (uint64_t C = 0; C < Remaining; ++C) {
- EmitAlignment(LogAlignment);
- OutStreamer.EmitInstruction(TrapInst, *STI);
- }
-
- }
- }
-
// Emit module flags.
SmallVector<Module::ModuleFlagEntry, 8> ModuleFlags;
M.getModuleFlagsMetadata(ModuleFlags);
@@ -1152,11 +1136,26 @@ bool AsmPrinter::doFinalization(Module &M) {
return false;
}
+MCSymbol *AsmPrinter::getCurExceptionSym() {
+ if (!CurExceptionSym)
+ CurExceptionSym = createTempSymbol("exception");
+ return CurExceptionSym;
+}
+
void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
this->MF = &MF;
// Get the function symbol.
CurrentFnSym = getSymbol(MF.getFunction());
CurrentFnSymForSize = CurrentFnSym;
+ CurrentFnBegin = nullptr;
+ CurExceptionSym = nullptr;
+ bool NeedsLocalForSize = MAI->needsLocalForSize();
+ if (!MMI->getLandingPads().empty() || MMI->hasDebugInfo() ||
+ NeedsLocalForSize) {
+ CurrentFnBegin = createTempSymbol("func_begin");
+ if (NeedsLocalForSize)
+ CurrentFnSymForSize = CurrentFnBegin;
+ }
if (isVerbose())
LI = &getAnalysis<MachineLoopInfo>();
@@ -1273,10 +1272,8 @@ void AsmPrinter::EmitJumpTableInfo() {
bool JTInDiffSection = !TLOF.shouldPutJumpTableInFunctionSection(
MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32,
*F);
- if (!JTInDiffSection) {
- OutStreamer.SwitchSection(TLOF.SectionForGlobal(F, *Mang, TM));
- } else {
- // Otherwise, drop it in the readonly section.
+ if (JTInDiffSection) {
+ // Drop it in the readonly section.
const MCSection *ReadOnlySection =
TLOF.getSectionForJumpTable(*F, *Mang, TM);
OutStreamer.SwitchSection(ReadOnlySection);
@@ -1585,7 +1582,7 @@ void AsmPrinter::EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo,
}
// Otherwise, emit with .set (aka assignment).
- MCSymbol *SetLabel = GetTempSymbol("set", SetCounter++);
+ MCSymbol *SetLabel = createTempSymbol("set");
OutStreamer.EmitAssignment(SetLabel, Diff);
OutStreamer.EmitSymbolValue(SetLabel, Size);
}
@@ -1667,8 +1664,7 @@ const MCExpr *AsmPrinter::lowerConstant(const Constant *CV) {
// If the code isn't optimized, there may be outstanding folding
// opportunities. Attempt to fold the expression using DataLayout as a
// last resort before giving up.
- if (Constant *C = ConstantFoldConstantExpression(
- CE, TM.getDataLayout()))
+ if (Constant *C = ConstantFoldConstantExpression(CE, *TM.getDataLayout()))
if (C != CE)
return lowerConstant(C);
@@ -2112,9 +2108,15 @@ static void handleIndirectSymViaGOTPCRel(AsmPrinter &AP, const MCExpr **ME,
//
// gotpcrelcst := <offset from @foo base> + <cst>
//
+ // If gotpcrelcst is positive it means that we can safely fold the pc rel
+ // displacement into the GOTPCREL. We can also can have an extra offset <cst>
+ // if the target knows how to encode it.
+ //
int64_t GOTPCRelCst = Offset + MV.getConstant();
if (GOTPCRelCst < 0)
return;
+ if (!AP.getObjFileLowering().supportGOTPCRelWithOffset() && GOTPCRelCst != 0)
+ return;
// Emit the GOT PC relative to replace the got equivalent global, i.e.:
//
@@ -2134,18 +2136,16 @@ static void handleIndirectSymViaGOTPCRel(AsmPrinter &AP, const MCExpr **ME,
//
AsmPrinter::GOTEquivUsePair Result = AP.GlobalGOTEquivs[GOTEquivSym];
const GlobalVariable *GV = Result.first;
- unsigned NumUses = Result.second;
+ int NumUses = (int)Result.second;
const GlobalValue *FinalGV = dyn_cast<GlobalValue>(GV->getOperand(0));
const MCSymbol *FinalSym = AP.getSymbol(FinalGV);
- *ME = AP.getObjFileLowering().getIndirectSymViaGOTPCRel(FinalSym,
- GOTPCRelCst);
+ *ME = AP.getObjFileLowering().getIndirectSymViaGOTPCRel(
+ FinalSym, MV, Offset, AP.MMI, AP.OutStreamer);
// Update GOT equivalent usage information
--NumUses;
- if (NumUses)
+ if (NumUses >= 0)
AP.GlobalGOTEquivs[GOTEquivSym] = std::make_pair(GV, NumUses);
- else
- AP.GlobalGOTEquivs.erase(GOTEquivSym);
}
static void emitGlobalConstantImpl(const Constant *CV, AsmPrinter &AP,
@@ -2206,7 +2206,7 @@ static void emitGlobalConstantImpl(const Constant *CV, AsmPrinter &AP,
// If the constant expression's size is greater than 64-bits, then we have
// to emit the value in chunks. Try to constant fold the value and emit it
// that way.
- Constant *New = ConstantFoldConstantExpression(CE, DL);
+ Constant *New = ConstantFoldConstantExpression(CE, *DL);
if (New && New != CE)
return emitGlobalConstantImpl(New, AP);
}
@@ -2257,23 +2257,10 @@ void AsmPrinter::printOffset(int64_t Offset, raw_ostream &OS) const {
// Symbol Lowering Routines.
//===----------------------------------------------------------------------===//
-/// GetTempSymbol - Return the MCSymbol corresponding to the assembler
-/// temporary label with the specified stem and unique ID.
-MCSymbol *AsmPrinter::GetTempSymbol(const Twine &Name, unsigned ID) const {
- const DataLayout *DL = TM.getDataLayout();
- return OutContext.GetOrCreateSymbol(Twine(DL->getPrivateGlobalPrefix()) +
- Name + Twine(ID));
-}
-
-/// GetTempSymbol - Return an assembler temporary label with the specified
-/// stem.
-MCSymbol *AsmPrinter::GetTempSymbol(const Twine &Name) const {
- const DataLayout *DL = TM.getDataLayout();
- return OutContext.GetOrCreateSymbol(Twine(DL->getPrivateGlobalPrefix())+
- Name);
+MCSymbol *AsmPrinter::createTempSymbol(const Twine &Name) const {
+ return OutContext.createTempSymbol(Name, true);
}
-
MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BlockAddress *BA) const {
return MMI->getAddrLabelSymbol(BA->getBasicBlock());
}
@@ -2523,3 +2510,5 @@ GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy &S) {
/// Pin vtable to this file.
AsmPrinterHandler::~AsmPrinterHandler() {}
+
+void AsmPrinterHandler::markFunctionEnd() {}