unsigned Major, Minor, Update;
TT.getOSVersion(Major, Minor, Update);
// If there is a version specified, Major will be non-zero.
- if (Major)
- OutStreamer->EmitVersionMin((TT.isMacOSX() ?
- MCVM_OSXVersionMin : MCVM_IOSVersionMin),
- Major, Minor, Update);
+ if (Major) {
+ MCVersionMinType VersionType;
+ if (TT.isWatchOS())
+ VersionType = MCVM_WatchOSVersionMin;
+ else if (TT.isTvOS())
+ VersionType = MCVM_TvOSVersionMin;
+ else if (TT.isMacOSX())
+ VersionType = MCVM_OSXVersionMin;
+ else
+ VersionType = MCVM_IOSVersionMin;
+ OutStreamer->EmitVersionMin(VersionType, Major, Minor, Update);
+ }
}
// Allow the target to emit any magic that it wants at the start of the file.
TM.getTargetFeatureString()));
OutStreamer->AddComment("Start of file scope inline assembly");
OutStreamer->AddBlankLine();
- EmitInlineAsm(M.getModuleInlineAsm()+"\n", *STI, TM.Options.MCOptions);
+ EmitInlineAsm(M.getModuleInlineAsm()+"\n",
+ OutContext.getSubtargetCopy(*STI), TM.Options.MCOptions);
OutStreamer->AddComment("End of file scope inline assembly");
OutStreamer->AddBlankLine();
}
if (MAI->doesSupportDebugInformation()) {
- bool skip_dwarf = false;
- if (TM.getTargetTriple().isKnownWindowsMSVCEnvironment()) {
+ bool EmitCodeView = MMI->getModule()->getCodeViewFlag();
+ if (EmitCodeView && TM.getTargetTriple().isKnownWindowsMSVCEnvironment()) {
Handlers.push_back(HandlerInfo(new WinCodeViewLineTables(this),
DbgTimerName,
CodeViewLineTablesGroupName));
- // FIXME: Don't emit DWARF debug info if there's at least one function
- // with AddressSanitizer instrumentation.
- // This is a band-aid fix for PR22032.
- for (auto &F : M.functions()) {
- if (F.hasFnAttribute(Attribute::SanitizeAddress)) {
- skip_dwarf = true;
- break;
- }
- }
}
- if (!skip_dwarf) {
+ if (!EmitCodeView || MMI->getModule()->getDwarfVersion()) {
DD = new DwarfDebug(this, &M);
Handlers.push_back(HandlerInfo(DD, DbgTimerName, DWARFGroupName));
}
return TM.getSymbol(GV, *Mang);
}
+static MCSymbol *getOrCreateEmuTLSControlSym(MCSymbol *GVSym, MCContext &C) {
+ return C.getOrCreateSymbol(Twine("__emutls_v.") + GVSym->getName());
+}
+
+static MCSymbol *getOrCreateEmuTLSInitSym(MCSymbol *GVSym, MCContext &C) {
+ return C.getOrCreateSymbol(Twine("__emutls_t.") + GVSym->getName());
+}
+
+/// EmitEmulatedTLSControlVariable - Emit the control variable for an emulated TLS variable.
+void AsmPrinter::EmitEmulatedTLSControlVariable(const GlobalVariable *GV,
+ MCSymbol *EmittedSym,
+ bool AllZeroInitValue) {
+ // If there is init value, use .data.rel.local section;
+ // otherwise use the .data section.
+ MCSection *TLSVarSection =
+ const_cast<MCSection *>((GV->hasInitializer() && !AllZeroInitValue)
+ ? getObjFileLowering().getDataRelSection()
+ : getObjFileLowering().getDataSection());
+ OutStreamer->SwitchSection(TLSVarSection);
+ MCSymbol *GVSym = getSymbol(GV);
+ EmitLinkage(GV, EmittedSym); // same linkage as GV
+ const DataLayout &DL = GV->getParent()->getDataLayout();
+ uint64_t Size = DL.getTypeAllocSize(GV->getType()->getElementType());
+ unsigned AlignLog = getGVAlignmentLog2(GV, DL);
+ unsigned WordSize = DL.getPointerSize();
+ unsigned Alignment = DL.getPointerABIAlignment();
+ EmitAlignment(Log2_32(Alignment));
+ OutStreamer->EmitLabel(EmittedSym);
+ OutStreamer->EmitIntValue(Size, WordSize);
+ OutStreamer->EmitIntValue((1 << AlignLog), WordSize);
+ OutStreamer->EmitIntValue(0, WordSize);
+ if (GV->hasInitializer() && !AllZeroInitValue) {
+ OutStreamer->EmitSymbolValue(
+ getOrCreateEmuTLSInitSym(GVSym, OutContext), WordSize);
+ } else
+ OutStreamer->EmitIntValue(0, WordSize);
+ if (MAI->hasDotTypeDotSizeDirective())
+ OutStreamer->emitELFSize(cast<MCSymbolELF>(EmittedSym),
+ MCConstantExpr::create(4 * WordSize, OutContext));
+ OutStreamer->AddBlankLine(); // End of the __emutls_v.* variable.
+}
+
/// EmitGlobalVariable - Emit the specified global variable to the .s file.
void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
+ bool IsEmuTLSVar =
+ GV->getThreadLocalMode() != llvm::GlobalVariable::NotThreadLocal &&
+ TM.Options.EmulatedTLS;
+ assert(!(IsEmuTLSVar && GV->hasCommonLinkage()) &&
+ "No emulated TLS variables in the common section");
+
if (GV->hasInitializer()) {
// Check to see if this is a special global used by LLVM, if so, emit it.
if (EmitSpecialLLVMGlobal(GV))
if (GlobalGOTEquivs.count(getSymbol(GV)))
return;
- if (isVerbose()) {
+ if (isVerbose() && !IsEmuTLSVar) {
+ // When printing the control variable __emutls_v.*,
+ // we don't need to print the original TLS variable name.
GV->printAsOperand(OutStreamer->GetCommentOS(),
/*PrintType=*/false, GV->getParent());
OutStreamer->GetCommentOS() << '\n';
}
MCSymbol *GVSym = getSymbol(GV);
- EmitVisibility(GVSym, GV->getVisibility(), !GV->isDeclaration());
+ MCSymbol *EmittedSym = IsEmuTLSVar ?
+ getOrCreateEmuTLSControlSym(GVSym, OutContext) : GVSym;
+ // getOrCreateEmuTLSControlSym only creates the symbol with name and default attributes.
+ // GV's or GVSym's attributes will be used for the EmittedSym.
+
+ EmitVisibility(EmittedSym, GV->getVisibility(), !GV->isDeclaration());
if (!GV->hasInitializer()) // External globals require no extra code.
return;
"' is already defined");
if (MAI->hasDotTypeDotSizeDirective())
- OutStreamer->EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject);
+ OutStreamer->EmitSymbolAttribute(EmittedSym, MCSA_ELF_TypeObject);
SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GV, TM);
// sections and expected to be contiguous (e.g. ObjC metadata).
unsigned AlignLog = getGVAlignmentLog2(GV, DL);
+ bool AllZeroInitValue = false;
+ const Constant *InitValue = GV->getInitializer();
+ if (isa<ConstantAggregateZero>(InitValue))
+ AllZeroInitValue = true;
+ else {
+ const ConstantInt *InitIntValue = dyn_cast<ConstantInt>(InitValue);
+ if (InitIntValue && InitIntValue->isZero())
+ AllZeroInitValue = true;
+ }
+ if (IsEmuTLSVar)
+ EmitEmulatedTLSControlVariable(GV, EmittedSym, AllZeroInitValue);
+
for (const HandlerInfo &HI : Handlers) {
NamedRegionTimer T(HI.TimerName, HI.TimerGroupName, TimePassesIsEnabled);
HI.Handler->setSymbolSize(GVSym, Size);
// Handle common and BSS local symbols (.lcomm).
if (GVKind.isCommon() || GVKind.isBSSLocal()) {
+ assert(!(IsEmuTLSVar && GVKind.isCommon()) &&
+ "No emulated TLS variables in the common section");
if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
unsigned Align = 1 << AlignLog;
return;
}
- MCSection *TheSection =
+ if (IsEmuTLSVar && AllZeroInitValue)
+ return; // No need of initialization values.
+
+ MCSymbol *EmittedInitSym = IsEmuTLSVar ?
+ getOrCreateEmuTLSInitSym(GVSym, OutContext) : GVSym;
+ // getOrCreateEmuTLSInitSym only creates the symbol with name and default attributes.
+ // GV's or GVSym's attributes will be used for the EmittedInitSym.
+
+ MCSection *TheSection = IsEmuTLSVar ?
+ getObjFileLowering().getReadOnlySection() :
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()) {
+ if (GVKind.isBSSExtern() && MAI->hasMachoZeroFillDirective() && !IsEmuTLSVar) {
if (Size == 0) Size = 1; // zerofill of 0 bytes is undefined.
// .globl _foo
// TLOF class. This will also make it more obvious that stuff like
// MCStreamer::EmitTBSSSymbol is macho specific and only called from macho
// specific code.
- if (GVKind.isThreadLocal() && MAI->hasMachoTBSSDirective()) {
+ if (GVKind.isThreadLocal() && MAI->hasMachoTBSSDirective() && !IsEmuTLSVar) {
// Emit the .tbss symbol
MCSymbol *MangSym =
OutContext.getOrCreateSymbol(GVSym->getName() + Twine("$tlv$init"));
OutStreamer->SwitchSection(TheSection);
- EmitLinkage(GV, GVSym);
+ // emutls_t.* symbols are only used in the current compilation unit.
+ if (!IsEmuTLSVar)
+ EmitLinkage(GV, EmittedInitSym);
EmitAlignment(AlignLog, GV);
- OutStreamer->EmitLabel(GVSym);
+ OutStreamer->EmitLabel(EmittedInitSym);
EmitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer());
if (MAI->hasDotTypeDotSizeDirective())
// .size foo, 42
- OutStreamer->emitELFSize(cast<MCSymbolELF>(GVSym),
+ OutStreamer->emitELFSize(cast<MCSymbolELF>(EmittedInitSym),
MCConstantExpr::create(Size, OutContext));
OutStreamer->AddBlankLine();
/// that is an implicit def.
void AsmPrinter::emitImplicitDef(const MachineInstr *MI) const {
unsigned RegNo = MI->getOperand(0).getReg();
- OutStreamer->AddComment(Twine("implicit-def: ") +
- MMI->getContext().getRegisterInfo()->getName(RegNo));
+
+ SmallString<128> Str;
+ raw_svector_ostream OS(Str);
+ OS << "implicit-def: "
+ << PrintReg(RegNo, MF->getSubtarget().getRegisterInfo());
+
+ OutStreamer->AddComment(OS.str());
OutStreamer->AddBlankLine();
}
static void emitKill(const MachineInstr *MI, AsmPrinter &AP) {
- std::string Str = "kill:";
+ std::string Str;
+ raw_string_ostream OS(Str);
+ OS << "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.MMI->getContext().getRegisterInfo()->getName(Op.getReg());
- Str += (Op.isDef() ? "<def>" : "<kill>");
+ OS << ' '
+ << PrintReg(Op.getReg(),
+ AP.MF->getSubtarget().getRegisterInfo())
+ << (Op.isDef() ? "<def>" : "<kill>");
}
AP.OutStreamer->AddComment(Str);
AP.OutStreamer->AddBlankLine();
}
if (Deref)
OS << '[';
- OS << AP.MMI->getContext().getRegisterInfo()->getName(Reg);
+ OS << PrintReg(Reg, AP.MF->getSubtarget().getRegisterInfo());
}
if (Deref)
EmitFunctionBodyEnd();
if (!MMI->getLandingPads().empty() || MMI->hasDebugInfo() ||
- MAI->hasDotTypeDotSizeDirective()) {
+ MMI->hasEHFunclets() || MAI->hasDotTypeDotSizeDirective()) {
// Create a symbol for the end of function.
CurrentFnEnd = createTempSymbol("func_end");
OutStreamer->EmitLabel(CurrentFnEnd);
}
}
- // Make sure we wrote out everything we need.
- OutStreamer->Flush();
-
// Finalize debug and EH information.
for (const HandlerInfo &HI : Handlers) {
NamedRegionTimer T(HI.TimerName, HI.TimerGroupName,
// Emit the directives as assignments aka .set:
OutStreamer->EmitAssignment(Name, lowerConstant(Alias.getAliasee()));
- // Set the size of the alias symbol if we can, as otherwise the alias gets
- // the size of the aliasee which may not be correct e.g. if the alias is of
- // a member of a struct.
- if (MAI->hasDotTypeDotSizeDirective() && Alias.getValueType()->isSized()) {
+ // If the aliasee does not correspond to a symbol in the output, i.e. the
+ // alias is not of an object or the aliased object is private, then set the
+ // size of the alias symbol from the type of the alias. We don't do this in
+ // other situations as the alias and aliasee having differing types but same
+ // size may be intentional.
+ const GlobalObject *BaseObject = Alias.getBaseObject();
+ if (MAI->hasDotTypeDotSizeDirective() && Alias.getValueType()->isSized() &&
+ (!BaseObject || BaseObject->hasPrivateLinkage())) {
const DataLayout &DL = M.getDataLayout();
uint64_t Size = DL.getTypeAllocSize(Alias.getValueType());
OutStreamer->emitELFSize(cast<MCSymbolELF>(Name),
CurExceptionSym = nullptr;
bool NeedsLocalForSize = MAI->needsLocalForSize();
if (!MMI->getLandingPads().empty() || MMI->hasDebugInfo() ||
- NeedsLocalForSize) {
+ MMI->hasEHFunclets() || NeedsLocalForSize) {
CurrentFnBegin = createTempSymbol("func_begin");
if (NeedsLocalForSize)
CurrentFnSymForSize = CurrentFnBegin;
/// MachineBasicBlock, an alignment (if present) and a comment describing
/// it if appropriate.
void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) const {
+ // End the previous funclet and start a new one.
+ if (MBB.isEHFuncletEntry()) {
+ for (const HandlerInfo &HI : Handlers) {
+ HI.Handler->endFunclet();
+ HI.Handler->beginFunclet(MBB);
+ }
+ }
+
// Emit an alignment directive for this block, if needed.
if (unsigned Align = MBB.getAlignment())
EmitAlignment(Align);
if (isVerbose())
OutStreamer->AddComment("Block address taken");
- for (MCSymbol *Sym : MMI->getAddrLabelSymbolToEmit(BB))
- OutStreamer->EmitLabel(Sym);
+ // MBBs can have their address taken as part of CodeGen without having
+ // their corresponding BB's address taken in IR
+ if (BB->hasAddressTaken())
+ for (MCSymbol *Sym : MMI->getAddrLabelSymbolToEmit(BB))
+ OutStreamer->EmitLabel(Sym);
}
// Print some verbose block comments.
}
// Print the main label for the block.
- if (MBB.pred_empty() || isBlockOnlyReachableByFallthrough(&MBB)) {
+ if (MBB.pred_empty() ||
+ (isBlockOnlyReachableByFallthrough(&MBB) && !MBB.isEHFuncletEntry())) {
if (isVerbose()) {
// NOTE: Want this comment at start of line, don't emit with AddComment.
OutStreamer->emitRawComment(" BB#" + Twine(MBB.getNumber()) + ":", false);
isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const {
// If this is a landing pad, it isn't a fall through. If it has no preds,
// then nothing falls through to it.
- if (MBB->isLandingPad() || MBB->pred_empty())
+ if (MBB->isEHPad() || MBB->pred_empty())
return false;
// If there isn't exactly one predecessor, it can't be a fall through.