mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[MS][ARM64] Hoist __ImageBase handling into TargetLoweringObjectFileCOFF
All COFF targets should use @IMGREL32 relocations for symbol differences against __ImageBase. Do the same for getSectionForConstant, so that immediates lowered to globals get merged across TUs. Patch by Chris January Differential Revision: https://reviews.llvm.org/D47783 llvm-svn: 334523
This commit is contained in:
parent
fb41a59565
commit
aeb232db7c
@ -163,6 +163,16 @@ public:
|
||||
|
||||
void emitLinkerFlagsForUsed(raw_ostream &OS,
|
||||
const GlobalValue *GV) const override;
|
||||
|
||||
const MCExpr *lowerRelativeReference(const GlobalValue *LHS,
|
||||
const GlobalValue *RHS,
|
||||
const TargetMachine &TM) const override;
|
||||
|
||||
/// Given a mergeable constant with the specified size and relocation
|
||||
/// information, return a section that it should be placed in.
|
||||
MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind,
|
||||
const Constant *C,
|
||||
unsigned &Align) const override;
|
||||
};
|
||||
|
||||
class TargetLoweringObjectFileWasm : public TargetLoweringObjectFile {
|
||||
|
@ -1274,6 +1274,111 @@ void TargetLoweringObjectFileCOFF::emitLinkerFlagsForUsed(
|
||||
emitLinkerFlagsForUsedCOFF(OS, GV, getTargetTriple(), getMangler());
|
||||
}
|
||||
|
||||
const MCExpr *TargetLoweringObjectFileCOFF::lowerRelativeReference(
|
||||
const GlobalValue *LHS, const GlobalValue *RHS,
|
||||
const TargetMachine &TM) const {
|
||||
const Triple &T = TM.getTargetTriple();
|
||||
if (!T.isKnownWindowsMSVCEnvironment() &&
|
||||
!T.isWindowsItaniumEnvironment() &&
|
||||
!T.isWindowsCoreCLREnvironment())
|
||||
return nullptr;
|
||||
|
||||
// Our symbols should exist in address space zero, cowardly no-op if
|
||||
// otherwise.
|
||||
if (LHS->getType()->getPointerAddressSpace() != 0 ||
|
||||
RHS->getType()->getPointerAddressSpace() != 0)
|
||||
return nullptr;
|
||||
|
||||
// Both ptrtoint instructions must wrap global objects:
|
||||
// - Only global variables are eligible for image relative relocations.
|
||||
// - The subtrahend refers to the special symbol __ImageBase, a GlobalVariable.
|
||||
// We expect __ImageBase to be a global variable without a section, externally
|
||||
// defined.
|
||||
//
|
||||
// It should look something like this: @__ImageBase = external constant i8
|
||||
if (!isa<GlobalObject>(LHS) || !isa<GlobalVariable>(RHS) ||
|
||||
LHS->isThreadLocal() || RHS->isThreadLocal() ||
|
||||
RHS->getName() != "__ImageBase" || !RHS->hasExternalLinkage() ||
|
||||
cast<GlobalVariable>(RHS)->hasInitializer() || RHS->hasSection())
|
||||
return nullptr;
|
||||
|
||||
return MCSymbolRefExpr::create(TM.getSymbol(LHS),
|
||||
MCSymbolRefExpr::VK_COFF_IMGREL32,
|
||||
getContext());
|
||||
}
|
||||
|
||||
static std::string APIntToHexString(const APInt &AI) {
|
||||
unsigned Width = (AI.getBitWidth() / 8) * 2;
|
||||
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 (isa<UndefValue>(C)) {
|
||||
return APIntToHexString(APInt::getNullValue(Ty->getPrimitiveSizeInBits()));
|
||||
} else if (const auto *CFP = dyn_cast<ConstantFP>(C)) {
|
||||
return APIntToHexString(CFP->getValueAPF().bitcastToAPInt());
|
||||
} else if (const auto *CI = dyn_cast<ConstantInt>(C)) {
|
||||
return APIntToHexString(CI->getValue());
|
||||
} else {
|
||||
unsigned NumElements;
|
||||
if (isa<VectorType>(Ty))
|
||||
NumElements = Ty->getVectorNumElements();
|
||||
else
|
||||
NumElements = Ty->getArrayNumElements();
|
||||
std::string HexString;
|
||||
for (int I = NumElements - 1, E = -1; I != E; --I)
|
||||
HexString += scalarConstantToHexString(C->getAggregateElement(I));
|
||||
return HexString;
|
||||
}
|
||||
}
|
||||
|
||||
MCSection *TargetLoweringObjectFileCOFF::getSectionForConstant(
|
||||
const DataLayout &DL, SectionKind Kind, const Constant *C,
|
||||
unsigned &Align) const {
|
||||
if (Kind.isMergeableConst() && C) {
|
||||
const unsigned Characteristics = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
|
||||
COFF::IMAGE_SCN_MEM_READ |
|
||||
COFF::IMAGE_SCN_LNK_COMDAT;
|
||||
std::string COMDATSymName;
|
||||
if (Kind.isMergeableConst4()) {
|
||||
if (Align <= 4) {
|
||||
COMDATSymName = "__real@" + scalarConstantToHexString(C);
|
||||
Align = 4;
|
||||
}
|
||||
} else if (Kind.isMergeableConst8()) {
|
||||
if (Align <= 8) {
|
||||
COMDATSymName = "__real@" + scalarConstantToHexString(C);
|
||||
Align = 8;
|
||||
}
|
||||
} else if (Kind.isMergeableConst16()) {
|
||||
// FIXME: These may not be appropriate for non-x86 architectures.
|
||||
if (Align <= 16) {
|
||||
COMDATSymName = "__xmm@" + scalarConstantToHexString(C);
|
||||
Align = 16;
|
||||
}
|
||||
} else if (Kind.isMergeableConst32()) {
|
||||
if (Align <= 32) {
|
||||
COMDATSymName = "__ymm@" + scalarConstantToHexString(C);
|
||||
Align = 32;
|
||||
}
|
||||
}
|
||||
|
||||
if (!COMDATSymName.empty())
|
||||
return getContext().getCOFFSection(".rdata", Characteristics, Kind,
|
||||
COMDATSymName,
|
||||
COFF::IMAGE_COMDAT_SELECT_ANY);
|
||||
}
|
||||
|
||||
return TargetLoweringObjectFile::getSectionForConstant(DL, Kind, C, Align);
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Wasm
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -105,8 +105,6 @@ static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {
|
||||
return llvm::make_unique<X86FuchsiaTargetObjectFile>();
|
||||
if (TT.isOSBinFormatELF())
|
||||
return llvm::make_unique<X86ELFTargetObjectFile>();
|
||||
if (TT.isKnownWindowsMSVCEnvironment() || TT.isWindowsCoreCLREnvironment())
|
||||
return llvm::make_unique<X86WindowsTargetObjectFile>();
|
||||
if (TT.isOSBinFormatCOFF())
|
||||
return llvm::make_unique<TargetLoweringObjectFileCOFF>();
|
||||
llvm_unreachable("unknown subtarget type");
|
||||
|
@ -91,100 +91,3 @@ void X86SolarisTargetObjectFile::Initialize(MCContext &Ctx,
|
||||
TargetLoweringObjectFileELF::Initialize(Ctx, TM);
|
||||
InitializeELF(TM.Options.UseInitArray);
|
||||
}
|
||||
|
||||
const MCExpr *X86WindowsTargetObjectFile::lowerRelativeReference(
|
||||
const GlobalValue *LHS, const GlobalValue *RHS,
|
||||
const TargetMachine &TM) const {
|
||||
// Our symbols should exist in address space zero, cowardly no-op if
|
||||
// otherwise.
|
||||
if (LHS->getType()->getPointerAddressSpace() != 0 ||
|
||||
RHS->getType()->getPointerAddressSpace() != 0)
|
||||
return nullptr;
|
||||
|
||||
// Both ptrtoint instructions must wrap global objects:
|
||||
// - Only global variables are eligible for image relative relocations.
|
||||
// - The subtrahend refers to the special symbol __ImageBase, a GlobalVariable.
|
||||
// We expect __ImageBase to be a global variable without a section, externally
|
||||
// defined.
|
||||
//
|
||||
// It should look something like this: @__ImageBase = external constant i8
|
||||
if (!isa<GlobalObject>(LHS) || !isa<GlobalVariable>(RHS) ||
|
||||
LHS->isThreadLocal() || RHS->isThreadLocal() ||
|
||||
RHS->getName() != "__ImageBase" || !RHS->hasExternalLinkage() ||
|
||||
cast<GlobalVariable>(RHS)->hasInitializer() || RHS->hasSection())
|
||||
return nullptr;
|
||||
|
||||
return MCSymbolRefExpr::create(TM.getSymbol(LHS),
|
||||
MCSymbolRefExpr::VK_COFF_IMGREL32,
|
||||
getContext());
|
||||
}
|
||||
|
||||
static std::string APIntToHexString(const APInt &AI) {
|
||||
unsigned Width = (AI.getBitWidth() / 8) * 2;
|
||||
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 (isa<UndefValue>(C)) {
|
||||
return APIntToHexString(APInt::getNullValue(Ty->getPrimitiveSizeInBits()));
|
||||
} else if (const auto *CFP = dyn_cast<ConstantFP>(C)) {
|
||||
return APIntToHexString(CFP->getValueAPF().bitcastToAPInt());
|
||||
} else if (const auto *CI = dyn_cast<ConstantInt>(C)) {
|
||||
return APIntToHexString(CI->getValue());
|
||||
} else {
|
||||
unsigned NumElements;
|
||||
if (isa<VectorType>(Ty))
|
||||
NumElements = Ty->getVectorNumElements();
|
||||
else
|
||||
NumElements = Ty->getArrayNumElements();
|
||||
std::string HexString;
|
||||
for (int I = NumElements - 1, E = -1; I != E; --I)
|
||||
HexString += scalarConstantToHexString(C->getAggregateElement(I));
|
||||
return HexString;
|
||||
}
|
||||
}
|
||||
|
||||
MCSection *X86WindowsTargetObjectFile::getSectionForConstant(
|
||||
const DataLayout &DL, SectionKind Kind, const Constant *C,
|
||||
unsigned &Align) const {
|
||||
if (Kind.isMergeableConst() && C) {
|
||||
const unsigned Characteristics = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
|
||||
COFF::IMAGE_SCN_MEM_READ |
|
||||
COFF::IMAGE_SCN_LNK_COMDAT;
|
||||
std::string COMDATSymName;
|
||||
if (Kind.isMergeableConst4()) {
|
||||
if (Align <= 4) {
|
||||
COMDATSymName = "__real@" + scalarConstantToHexString(C);
|
||||
Align = 4;
|
||||
}
|
||||
} else if (Kind.isMergeableConst8()) {
|
||||
if (Align <= 8) {
|
||||
COMDATSymName = "__real@" + scalarConstantToHexString(C);
|
||||
Align = 8;
|
||||
}
|
||||
} else if (Kind.isMergeableConst16()) {
|
||||
if (Align <= 16) {
|
||||
COMDATSymName = "__xmm@" + scalarConstantToHexString(C);
|
||||
Align = 16;
|
||||
}
|
||||
} else if (Kind.isMergeableConst32()) {
|
||||
if (Align <= 32) {
|
||||
COMDATSymName = "__ymm@" + scalarConstantToHexString(C);
|
||||
Align = 32;
|
||||
}
|
||||
}
|
||||
|
||||
if (!COMDATSymName.empty())
|
||||
return getContext().getCOFFSection(".rdata", Characteristics, Kind,
|
||||
COMDATSymName,
|
||||
COFF::IMAGE_COMDAT_SELECT_ANY);
|
||||
}
|
||||
|
||||
return TargetLoweringObjectFile::getSectionForConstant(DL, Kind, C, Align);
|
||||
}
|
||||
|
@ -71,19 +71,6 @@ namespace llvm {
|
||||
void Initialize(MCContext &Ctx, const TargetMachine &TM) override;
|
||||
};
|
||||
|
||||
/// This implementation is used for Windows targets on x86 and x86-64.
|
||||
class X86WindowsTargetObjectFile : public TargetLoweringObjectFileCOFF {
|
||||
const MCExpr *
|
||||
lowerRelativeReference(const GlobalValue *LHS, const GlobalValue *RHS,
|
||||
const TargetMachine &TM) const override;
|
||||
|
||||
/// Given a mergeable constant with the specified size and relocation
|
||||
/// information, return a section that it should be placed in.
|
||||
MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind,
|
||||
const Constant *C,
|
||||
unsigned &Align) const override;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
11
test/MC/AArch64/ir-to-imgrel.ll
Normal file
11
test/MC/AArch64/ir-to-imgrel.ll
Normal file
@ -0,0 +1,11 @@
|
||||
; RUN: llc -mtriple=aarch64-pc-win32 %s -o - | FileCheck %s --check-prefix=AARCH64
|
||||
|
||||
@__ImageBase = external global i8
|
||||
|
||||
; AARCH64: .xword "?x@@3HA"@IMGREL
|
||||
@"\01?x@@3HA" = global i64 sub nsw (i64 ptrtoint (i64* @"\01?x@@3HA" to i64), i64 ptrtoint (i8* @__ImageBase to i64)), align 8
|
||||
|
||||
declare void @f()
|
||||
|
||||
; AARCH64: .xword f@IMGREL
|
||||
@fp = global i64 sub nsw (i64 ptrtoint (void ()* @f to i64), i64 ptrtoint (i8* @__ImageBase to i64)), align 8
|
Loading…
x
Reference in New Issue
Block a user