/// Given a constant with the SectionKind, return a section that it should be
/// placed in.
- const MCSection *getSectionForConstant(SectionKind Kind) const override;
+ const MCSection *getSectionForConstant(SectionKind Kind,
+ const Constant *C) const override;
const MCSection *getExplicitSectionGlobal(const GlobalValue *GV,
SectionKind Kind, Mangler &Mang,
SectionKind Kind, Mangler &Mang,
const TargetMachine &TM) const override;
- const MCSection *getSectionForConstant(SectionKind Kind) const override;
+ const MCSection *getSectionForConstant(SectionKind Kind,
+ const Constant *C) const override;
/// The mach-o version of this method defaults to returning a stub reference.
const MCExpr *
/// The COMDAT symbol of this section. Only valid if this is a COMDAT
/// section. Two COMDAT sections are merged if they have the same
/// COMDAT symbol.
- const MCSymbol *COMDATSymbol;
+ MCSymbol *COMDATSymbol;
/// Selection - This is the Selection field for the section symbol, if
/// it is a COMDAT section (Characteristics & IMAGE_SCN_LNK_COMDAT) != 0
private:
friend class MCContext;
MCSectionCOFF(StringRef Section, unsigned Characteristics,
- const MCSymbol *COMDATSymbol, int Selection, SectionKind K)
+ MCSymbol *COMDATSymbol, int Selection, SectionKind K)
: MCSection(SV_COFF, K), SectionName(Section),
Characteristics(Characteristics), COMDATSymbol(COMDATSymbol),
Selection(Selection) {
return SectionName.str() + "_end";
}
unsigned getCharacteristics() const { return Characteristics; }
- const MCSymbol *getCOMDATSymbol() const { return COMDATSymbol; }
+ MCSymbol *getCOMDATSymbol() const { return COMDATSymbol; }
int getSelection() const { return Selection; }
void setSelection(int Selection) const;
/// Given a constant with the SectionKind, return a section that it should be
/// placed in.
- virtual const MCSection *getSectionForConstant(SectionKind Kind) const;
+ virtual const MCSection *getSectionForConstant(SectionKind Kind,
+ const Constant *C) const;
/// Classify the specified global variable into a set of target independent
/// categories embodied in SectionKind.
SectionKind Kind = CPE.getSectionKind(TM.getDataLayout());
- const MCSection *S = getObjFileLowering().getSectionForConstant(Kind);
+ const Constant *C = nullptr;
+ if (!CPE.isMachineConstantPoolEntry())
+ C = CPE.Val.ConstVal;
+
+ const MCSection *S = getObjFileLowering().getSectionForConstant(Kind, C);
// The number of sections are small, just do a linear search from the
// last section to the first.
}
// Now print stuff into the calculated sections.
+ const MCSection *CurSection = nullptr;
+ unsigned Offset = 0;
for (unsigned i = 0, e = CPSections.size(); i != e; ++i) {
- OutStreamer.SwitchSection(CPSections[i].S);
- EmitAlignment(Log2_32(CPSections[i].Alignment));
-
- unsigned Offset = 0;
for (unsigned j = 0, ee = CPSections[i].CPEs.size(); j != ee; ++j) {
unsigned CPI = CPSections[i].CPEs[j];
+ MCSymbol *Sym = GetCPISymbol(CPI);
+ if (!Sym->isUndefined())
+ continue;
+
+ if (CurSection != CPSections[i].S) {
+ OutStreamer.SwitchSection(CPSections[i].S);
+ EmitAlignment(Log2_32(CPSections[i].Alignment));
+ CurSection = CPSections[i].S;
+ Offset = 0;
+ }
+
MachineConstantPoolEntry CPE = CP[CPI];
// Emit inter-object padding for alignment.
Type *Ty = CPE.getType();
Offset = NewOffset + TM.getDataLayout()->getTypeAllocSize(Ty);
- OutStreamer.EmitLabel(GetCPISymbol(CPI));
+ OutStreamer.EmitLabel(Sym);
if (CPE.isMachineConstantPoolEntry())
EmitMachineConstantPoolValue(CPE.Val.MachineCPVal);
else
} else {
// Otherwise, drop it in the readonly section.
const MCSection *ReadOnlySection =
- getObjFileLowering().getSectionForConstant(SectionKind::getReadOnly());
+ getObjFileLowering().getSectionForConstant(SectionKind::getReadOnly(),
+ /*C=*/nullptr);
OutStreamer.SwitchSection(ReadOnlySection);
JTInDiffSection = true;
}
/// getSectionForConstant - Given a mergeable constant with the
/// specified size and relocation information, return a section that it
/// should be placed in.
-const MCSection *TargetLoweringObjectFileELF::
-getSectionForConstant(SectionKind Kind) const {
+const MCSection *
+TargetLoweringObjectFileELF::getSectionForConstant(SectionKind Kind,
+ const Constant *C) const {
if (Kind.isMergeableConst4() && MergeableConst4Section)
return MergeableConst4Section;
if (Kind.isMergeableConst8() && MergeableConst8Section)
}
const MCSection *
-TargetLoweringObjectFileMachO::getSectionForConstant(SectionKind Kind) const {
+TargetLoweringObjectFileMachO::getSectionForConstant(SectionKind Kind,
+ const Constant *C) const {
// If this constant requires a relocation, we have to put it in the data
// segment, not in the text segment.
if (Kind.isDataRel() || Kind.isReadOnlyWithRel())
if (!IterBool.second)
return Iter->second;
- const MCSymbol *COMDATSymbol = nullptr;
+ MCSymbol *COMDATSymbol = nullptr;
if (!COMDATSymName.empty())
COMDATSymbol = GetOrCreateSymbol(COMDATSymName);
new NVPTXSection(MCSection::SV_ELF, SectionKind::getMetadata());
}
- const MCSection *getSectionForConstant(SectionKind Kind) const override {
+ const MCSection *getSectionForConstant(SectionKind Kind,
+ const Constant *C) const override {
return ReadOnlySection;
}
/// specified size and relocation information, return a section that it
/// should be placed in.
const MCSection *
-TargetLoweringObjectFile::getSectionForConstant(SectionKind Kind) const {
+TargetLoweringObjectFile::getSectionForConstant(SectionKind Kind,
+ const Constant *C) const {
if (Kind.isReadOnly() && ReadOnlySection != nullptr)
return ReadOnlySection;
#include "X86InstrInfo.h"
#include "X86MachineFunctionInfo.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCSectionCOFF.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
4 /*size*/);
}
+MCSymbol *X86AsmPrinter::GetCPISymbol(unsigned CPID) const {
+ if (Subtarget->isTargetKnownWindowsMSVC()) {
+ const MachineConstantPoolEntry &CPE =
+ MF->getConstantPool()->getConstants()[CPID];
+ if (!CPE.isMachineConstantPoolEntry()) {
+ SectionKind Kind = CPE.getSectionKind(TM.getDataLayout());
+ const Constant *C = CPE.Val.ConstVal;
+ const MCSectionCOFF *S = cast<MCSectionCOFF>(
+ getObjFileLowering().getSectionForConstant(Kind, C));
+ if (MCSymbol *Sym = S->getCOMDATSymbol()) {
+ if (Sym->isUndefined())
+ OutStreamer.EmitSymbolAttribute(Sym, MCSA_Global);
+ return Sym;
+ }
+ }
+ }
+
+ return AsmPrinter::GetCPISymbol(CPID);
+}
+
void X86AsmPrinter::GenerateExportDirective(const MCSymbol *Sym, bool IsData) {
SmallString<128> Directive;
raw_svector_ostream OS(Directive);
unsigned AsmVariant, const char *ExtraCode,
raw_ostream &OS) override;
+ /// \brief Return the symbol for the specified constant pool entry.
+ MCSymbol *GetCPISymbol(unsigned CPID) const override;
+
bool runOnMachineFunction(MachineFunction &F) override;
};
//===----------------------------------------------------------------------===//
#include "X86TargetObjectFile.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Operator.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCSectionCOFF.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Target/TargetLowering.h"
MCSymbolRefExpr::VK_COFF_IMGREL32,
getContext());
}
+
+static std::string APIntToHexString(const APInt &AI, unsigned Width) {
+ std::string HexString = utohexstr(AI.getLimitedValue(), /*LowerCase=*/true);
+ unsigned Size = HexString.size();
+ assert(Width >= Size && "hex string is too large!");
+ HexString.insert(HexString.begin(), Width - Size, '0');
+
+ return HexString;
+}
+
+
+static std::string scalarConstantToHexString(const Constant *C) {
+ Type *Ty = C->getType();
+ if (Ty->isFloatTy()) {
+ const auto *CFP = cast<ConstantFP>(C);
+ return APIntToHexString(CFP->getValueAPF().bitcastToAPInt(), /*Width=*/8);
+ } else if (Ty->isDoubleTy()) {
+ const auto *CFP = cast<ConstantFP>(C);
+ return APIntToHexString(CFP->getValueAPF().bitcastToAPInt(), /*Width=*/16);
+ } else if (const auto *ITy = dyn_cast<IntegerType>(Ty)) {
+ const auto *CI = cast<ConstantInt>(C);
+ return APIntToHexString(CI->getValue(), (ITy->getBitWidth() / 8) * 2);
+ }
+ llvm_unreachable("unexpected constant pool element type!");
+}
+
+const MCSection *
+X86WindowsTargetObjectFile::getSectionForConstant(SectionKind Kind,
+ const Constant *C) const {
+ if (Kind.isReadOnly()) {
+ if (C) {
+ Type *Ty = C->getType();
+ SmallString<32> COMDATSymName;
+ if (Ty->isFloatTy() || Ty->isDoubleTy()) {
+ COMDATSymName = "__real@";
+ COMDATSymName += scalarConstantToHexString(C);
+ } else if (const auto *VTy = dyn_cast<VectorType>(Ty)) {
+ uint64_t NumBits = VTy->getBitWidth();
+ if (NumBits == 128 || NumBits == 256) {
+ const auto *CDV = cast<ConstantDataVector>(C);
+ COMDATSymName = NumBits == 128 ? "__xmm@" : "__ymm@";
+ for (int I = CDV->getNumElements() - 1, E = -1; I != E; --I)
+ COMDATSymName +=
+ scalarConstantToHexString(CDV->getElementAsConstant(I));
+ }
+ }
+ if (!COMDATSymName.empty()) {
+ unsigned Characteristics = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+ COFF::IMAGE_SCN_MEM_READ |
+ COFF::IMAGE_SCN_LNK_COMDAT;
+ return getContext().getCOFFSection(".rdata", Characteristics, Kind,
+ COMDATSymName,
+ COFF::IMAGE_COMDAT_SELECT_ANY);
+ }
+ }
+ }
+
+ return TargetLoweringObjectFile::getSectionForConstant(Kind, C);
+}
const MCExpr *
getExecutableRelativeSymbol(const ConstantExpr *CE, Mangler &Mang,
const TargetMachine &TM) const override;
+
+ /// \brief Given a mergeable constant with the specified size and relocation
+ /// information, return a section that it should be placed in.
+ const MCSection *getSectionForConstant(SectionKind Kind,
+ const Constant *C) const override;
};
} // end namespace llvm
report_fatal_error("Target does not support TLS or Common sections");
}
-const MCSection *XCoreTargetObjectFile::
-getSectionForConstant(SectionKind Kind) const {
+const MCSection *
+XCoreTargetObjectFile::getSectionForConstant(SectionKind Kind,
+ const Constant *C) const {
if (Kind.isMergeableConst4()) return MergeableConst4Section;
if (Kind.isMergeableConst8()) return MergeableConst8Section;
if (Kind.isMergeableConst16()) return MergeableConst16Section;
Mangler &Mang,
const TargetMachine &TM) const override;
- const MCSection *getSectionForConstant(SectionKind Kind) const override;
+ const MCSection *getSectionForConstant(SectionKind Kind,
+ const Constant *C) const override;
};
} // end namespace llvm
-; RUN: llc < %s -mtriple=x86_64-linux -mcpu=corei7 | FileCheck %s
-; RUN: llc < %s -mtriple=x86_64-win32 -mcpu=corei7 | FileCheck %s
+; RUN: llc < %s -mtriple=x86_64-linux -mcpu=corei7 | FileCheck %s --check-prefix=COMMON --check-prefix=LINUX
+; RUN: llc < %s -mtriple=x86_64-win32 -mcpu=corei7 | FileCheck %s --check-prefix=COMMON --check-prefix=MSVC
; llc should share constant pool entries between this integer vector
; and this floating-point vector since they have the same encoding.
-; CHECK: LCPI0_0(%rip), %xmm0
-; CHECK: movaps %xmm0, ({{%rdi|%rcx}})
-; CHECK: movaps %xmm0, ({{%rsi|%rdx}})
+; LINUX: LCPI0_0(%rip), %xmm0
+; MSVC: __xmm@40000000400000004000000040000000(%rip), %xmm0
+; COMMON: movaps %xmm0, ({{%rdi|%rcx}})
+; COMMON: movaps %xmm0, ({{%rsi|%rdx}})
define void @foo(<4 x i32>* %p, <4 x float>* %q, i1 %t) nounwind {
entry:
--- /dev/null
+; RUN: llc < %s -mtriple=x86_64-win32 -mcpu=corei7 | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+define double @double() {
+ ret double 0x0000000000800000
+}
+; CHECK: .globl __real@0000000000800000
+; CHECK-NEXT: .section .rdata,"rd",discard,__real@0000000000800000
+; CHECK-NEXT: .align 8
+; CHECK-NEXT: __real@0000000000800000:
+; CHECK-NEXT: .quad 8388608
+; CHECK: double:
+; CHECK: movsd __real@0000000000800000(%rip), %xmm0
+; CHECK-NEXT: ret
+
+define <4 x i32> @vec1() {
+ ret <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+}
+; CHECK: .globl __xmm@00000000000000010000000200000003
+; CHECK-NEXT: .section .rdata,"rd",discard,__xmm@00000000000000010000000200000003
+; CHECK-NEXT: .align 16
+; CHECK-NEXT: __xmm@00000000000000010000000200000003:
+; CHECK-NEXT: .long 3
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long 1
+; CHECK-NEXT: .long 0
+; CHECK: vec1:
+; CHECK: movaps __xmm@00000000000000010000000200000003(%rip), %xmm0
+; CHECK-NEXT: ret
+
+define <8 x i16> @vec2() {
+ ret <8 x i16> <i16 7, i16 6, i16 5, i16 4, i16 3, i16 2, i16 1, i16 0>
+}
+; CHECK: .globl __xmm@00000001000200030004000500060007
+; CHECK-NEXT: .section .rdata,"rd",discard,__xmm@00000001000200030004000500060007
+; CHECK-NEXT: .align 16
+; CHECK-NEXT: __xmm@00000001000200030004000500060007:
+; CHECK-NEXT: .short 7
+; CHECK-NEXT: .short 6
+; CHECK-NEXT: .short 5
+; CHECK-NEXT: .short 4
+; CHECK-NEXT: .short 3
+; CHECK-NEXT: .short 2
+; CHECK-NEXT: .short 1
+; CHECK-NEXT: .short 0
+; CHECK: vec2:
+; CHECK: movaps __xmm@00000001000200030004000500060007(%rip), %xmm0
+; CHECK-NEXT: ret