//===-- llvm/Target/TargetLoweringObjectFile.cpp - Object File Info -------===////// The LLVM Compiler Infrastructure//// This file is distributed under the University of Illinois Open Source// License. See LICENSE.TXT for details.////===----------------------------------------------------------------------===////// This file implements classes used to handle lowerings specific to common// object file formats.////===----------------------------------------------------------------------===//#include"llvm/Target/TargetLoweringObjectFile.h"#include"llvm/IR/Constants.h"#include"llvm/IR/DataLayout.h"#include"llvm/IR/DerivedTypes.h"#include"llvm/IR/Function.h"#include"llvm/IR/GlobalVariable.h"#include"llvm/IR/Mangler.h"#include"llvm/MC/MCAsmInfo.h"#include"llvm/MC/MCContext.h"#include"llvm/MC/MCExpr.h"#include"llvm/MC/MCStreamer.h"#include"llvm/MC/MCSymbol.h"#include"llvm/Support/Dwarf.h"#include"llvm/Support/ErrorHandling.h"#include"llvm/Support/raw_ostream.h"#include"llvm/Target/TargetLowering.h"#include"llvm/Target/TargetMachine.h"#include"llvm/Target/TargetOptions.h"#include"llvm/Target/TargetSubtargetInfo.h"usingnamespacellvm;//===----------------------------------------------------------------------===//// Generic Code//===----------------------------------------------------------------------===///// Initialize - this method must be called before any actual lowering is/// done. This specifies the current context for codegen, and gives the/// lowering implementations a chance to set up their default sections.voidTargetLoweringObjectFile::Initialize(MCContext&ctx,constTargetMachine&TM){Ctx=&ctx;// `Initialize` can be called more than once.if(Mang!=nullptr)deleteMang;Mang=newMangler();InitMCObjectFileInfo(TM.getTargetTriple(),TM.isPositionIndependent(),TM.getCodeModel(),*Ctx);}TargetLoweringObjectFile::~TargetLoweringObjectFile(){deleteMang;}staticboolisSuitableForBSS(constGlobalVariable*GV,boolNoZerosInBSS){constConstant*C=GV->getInitializer();// Must have zero initializer.if(!C->isNullValue())returnfalse;// Leave constant zeros in readonly constant sections, so they can be shared.if(GV->isConstant())returnfalse;// If the global has an explicit section specified, don't put it in BSS.if(GV->hasSection())returnfalse;// If -nozero-initialized-in-bss is specified, don't ever use BSS.if(NoZerosInBSS)returnfalse;// Otherwise, put it in BSS!returntrue;}/// IsNullTerminatedString - Return true if the specified constant (which is/// known to have a type that is an array of 1/2/4 byte elements) ends with a/// nul value and contains no other nuls in it. Note that this is more general/// than ConstantDataSequential::isString because we allow 2 & 4 byte strings.staticboolIsNullTerminatedString(constConstant*C){// First check: is we have constant array terminated with zeroif(constConstantDataSequential*CDS=dyn_cast<ConstantDataSequential>(C)){unsignedNumElts=CDS->getNumElements();assert(NumElts!=0&&"Can't have an empty CDS");if(CDS->getElementAsInteger(NumElts-1)!=0)returnfalse;// Not null terminated.// Verify that the null doesn't occur anywhere else in the string.for(unsignedi=0;i!=NumElts-1;++i)if(CDS->getElementAsInteger(i)==0)returnfalse;returntrue;}// Another possibility: [1 x i8] zeroinitializerif(isa<ConstantAggregateZero>(C))returncast<ArrayType>(C->getType())->getNumElements()==1;returnfalse;}MCSymbol*TargetLoweringObjectFile::getSymbolWithGlobalValueBase(constGlobalValue*GV,StringRefSuffix,constTargetMachine&TM)const{assert(!Suffix.empty());SmallString<60>NameStr;NameStr+=GV->getParent()->getDataLayout().getPrivateGlobalPrefix();TM.getNameWithPrefix(NameStr,GV,*Mang);NameStr.append(Suffix.begin(),Suffix.end());returnCtx->getOrCreateSymbol(NameStr);}MCSymbol*TargetLoweringObjectFile::getCFIPersonalitySymbol(constGlobalValue*GV,constTargetMachine&TM,MachineModuleInfo*MMI)const{returnTM.getSymbol(GV);}voidTargetLoweringObjectFile::emitPersonalityValue(MCStreamer&Streamer,constDataLayout&,constMCSymbol*Sym)const{}/// getKindForGlobal - This is a top-level target-independent classifier for/// a global variable. Given an global variable and information from TM, it/// classifies the global in a variety of ways that make various target/// implementations simpler. The target implementation is free to ignore this/// extra info of course.SectionKindTargetLoweringObjectFile::getKindForGlobal(constGlobalObject*GO,constTargetMachine&TM){assert(!GO->isDeclaration()&&!GO->hasAvailableExternallyLinkage()&&"Can only be used for global definitions");Reloc::ModelReloModel=TM.getRelocationModel();// Early exit - functions should be always in text sections.constauto*GVar=dyn_cast<GlobalVariable>(GO);if(!GVar)returnSectionKind::getText();// Handle thread-local data first.if(GVar->isThreadLocal()){if(isSuitableForBSS(GVar,TM.Options.NoZerosInBSS))returnSectionKind::getThreadBSS();returnSectionKind::getThreadData();}// Variables with common linkage always get classified as common.if(GVar->hasCommonLinkage())returnSectionKind::getCommon();// Variable can be easily put to BSS section.if(isSuitableForBSS(GVar,TM.Options.NoZerosInBSS)){if(GVar->hasLocalLinkage())returnSectionKind::getBSSLocal();elseif(GVar->hasExternalLinkage())returnSectionKind::getBSSExtern();returnSectionKind::getBSS();}constConstant*C=GVar->getInitializer();// If the global is marked constant, we can put it into a mergable section,// a mergable string section, or general .data if it contains relocations.if(GVar->isConstant()){// If the initializer for the global contains something that requires a// relocation, then we may have to drop this into a writable data section// even though it is marked const.if(!C->needsRelocation()){// If the global is required to have a unique address, it can't be put// into a mergable section: just drop it into the general read-only// section instead.if(!GVar->hasGlobalUnnamedAddr())returnSectionKind::getReadOnly();// If initializer is a null-terminated string, put it in a "cstring"// section of the right width.if(ArrayType*ATy=dyn_cast<ArrayType>(C->getType())){if(IntegerType*ITy=dyn_cast<IntegerType>(ATy->getElementType())){if((ITy->getBitWidth()==8||ITy->getBitWidth()==16||ITy->getBitWidth()==32)&&IsNullTerminatedString(C)){if(ITy->getBitWidth()==8)returnSectionKind::getMergeable1ByteCString();if(ITy->getBitWidth()==16)returnSectionKind::getMergeable2ByteCString();assert(ITy->getBitWidth()==32&&"Unknown width");returnSectionKind::getMergeable4ByteCString();}}}// Otherwise, just drop it into a mergable constant section. If we have// a section for this size, use it, otherwise use the arbitrary sized// mergable section.switch(GVar->getParent()->getDataLayout().getTypeAllocSize(C->getType())){case4:returnSectionKind::getMergeableConst4();case8:returnSectionKind::getMergeableConst8();case16:returnSectionKind::getMergeableConst16();case32:returnSectionKind::getMergeableConst32();default:returnSectionKind::getReadOnly();}}else{// In static, ROPI and RWPI relocation models, the linker will resolve// all addresses, so the relocation entries will actually be constants by// the time the app starts up. However, we can't put this into a// mergable section, because the linker doesn't take relocations into// consideration when it tries to merge entries in the section.if(ReloModel==Reloc::Static||ReloModel==Reloc::ROPI||ReloModel==Reloc::RWPI||ReloModel==Reloc::ROPI_RWPI)returnSectionKind::getReadOnly();// Otherwise, the dynamic linker needs to fix it up, put it in the// writable data.rel section.returnSectionKind::getReadOnlyWithRel();}}// Okay, this isn't a constant.returnSectionKind::getData();}/// This method computes the appropriate section to emit the specified global/// variable or function definition. This should not be passed external (or/// available externally) globals.MCSection*TargetLoweringObjectFile::SectionForGlobal(constGlobalObject*GO,SectionKindKind,constTargetMachine&TM)const{// Select section name.if(GO->hasSection())returngetExplicitSectionGlobal(GO,Kind,TM);// Use default section depending on the 'type' of globalreturnSelectSectionForGlobal(GO,Kind,TM);}MCSection*TargetLoweringObjectFile::getSectionForJumpTable(constFunction&F,constTargetMachine&TM)const{unsignedAlign=0;returngetSectionForConstant(F.getParent()->getDataLayout(),SectionKind::getReadOnly(),/*C=*/nullptr,Align);}boolTargetLoweringObjectFile::shouldPutJumpTableInFunctionSection(boolUsesLabelDifference,constFunction&F)const{// 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?if(UsesLabelDifference)returntrue;// 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.if(F.isWeakForLinker())returntrue;returnfalse;}/// Given a mergable constant with the specified size and relocation/// information, return a section that it should be placed in.MCSection*TargetLoweringObjectFile::getSectionForConstant(constDataLayout&DL,SectionKindKind,constConstant*C,unsigned&Align)const{if(Kind.isReadOnly()&&ReadOnlySection!=nullptr)returnReadOnlySection;returnDataSection;}/// getTTypeGlobalReference - Return an MCExpr to use for a/// reference to the specified global variable from exception/// handling information.constMCExpr*TargetLoweringObjectFile::getTTypeGlobalReference(constGlobalValue*GV,unsignedEncoding,constTargetMachine&TM,MachineModuleInfo*MMI,MCStreamer&Streamer)const{constMCSymbolRefExpr*Ref=MCSymbolRefExpr::create(TM.getSymbol(GV),getContext());returngetTTypeReference(Ref,Encoding,Streamer);}constMCExpr*TargetLoweringObjectFile::getTTypeReference(constMCSymbolRefExpr*Sym,unsignedEncoding,MCStreamer&Streamer)const{switch(Encoding&0x70){default:report_fatal_error("We do not support this DWARF encoding yet!");casedwarf::DW_EH_PE_absptr:// Do nothing specialreturnSym;casedwarf::DW_EH_PE_pcrel:{// Emit a label to the streamer for the current position. This gives us// .-foo addressing.MCSymbol*PCSym=getContext().createTempSymbol();Streamer.EmitLabel(PCSym);constMCExpr*PC=MCSymbolRefExpr::create(PCSym,getContext());returnMCBinaryExpr::createSub(Sym,PC,getContext());}}}constMCExpr*TargetLoweringObjectFile::getDebugThreadLocalSymbol(constMCSymbol*Sym)const{// FIXME: It's not clear what, if any, default this should have - perhaps a// null return could mean 'no location' & we should just do that here.returnMCSymbolRefExpr::create(Sym,*Ctx);}voidTargetLoweringObjectFile::getNameWithPrefix(SmallVectorImpl<char>&OutName,constGlobalValue*GV,constTargetMachine&TM)const{Mang->getNameWithPrefix(OutName,GV,/*CannotUsePrivateLabel=*/false);}