mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-27 18:46:04 +00:00
[AIX][CodeGen] Storage Locations for Constant Pointers
This patch adds an `llc` option `-mroptr` to specify storage locations for constant pointers on AIX. When the `-mroptr` option is specified, constant pointers, virtual function tables, and virtual type tables are placed in read-only storage. Otherwise, by default, pointers, virtual function tables, and virtual type tables are placed are placed in read/write storage. https://reviews.llvm.org/D144190 enables the `-mroptr` option for `clang`. Reviewed By: hubert.reinterpretcast, stephenpeckham, myhsu, MaskRay, serge-sans-paille Differential Revision: https://reviews.llvm.org/D144189
This commit is contained in:
parent
fd4aeba307
commit
4f9929add5
@ -122,7 +122,11 @@ Changes to the MIPS Backend
|
||||
Changes to the PowerPC Backend
|
||||
------------------------------
|
||||
|
||||
* ...
|
||||
* A new option ``-mroptr`` is added to ``clang`` and ``llc``. When this option
|
||||
is present, constant objects with relocatable address values are put into the
|
||||
RO data section. This option should be used with the ``-fdata-sections``
|
||||
option, and is not supported with ``-fno-data-sections``. The option is
|
||||
only supported on AIX.
|
||||
|
||||
Changes to the RISC-V Backend
|
||||
-----------------------------
|
||||
|
@ -143,6 +143,8 @@ unsigned getAlignLoops();
|
||||
|
||||
bool getJMCInstrument();
|
||||
|
||||
bool getXCOFFReadOnlyPointers();
|
||||
|
||||
/// Create this object with static storage to register codegen-related command
|
||||
/// line options.
|
||||
struct RegisterCodeGenFlags {
|
||||
|
@ -130,13 +130,12 @@ namespace llvm {
|
||||
HonorSignDependentRoundingFPMathOption(false), NoZerosInBSS(false),
|
||||
GuaranteedTailCallOpt(false), StackSymbolOrdering(true),
|
||||
EnableFastISel(false), EnableGlobalISel(false), UseInitArray(false),
|
||||
DisableIntegratedAS(false),
|
||||
RelaxELFRelocations(true), FunctionSections(false),
|
||||
DataSections(false), IgnoreXCOFFVisibility(false),
|
||||
XCOFFTracebackTable(true), UniqueSectionNames(true),
|
||||
UniqueBasicBlockSectionNames(false), TrapUnreachable(false),
|
||||
NoTrapAfterNoreturn(false), TLSSize(0), EmulatedTLS(false),
|
||||
ExplicitEmulatedTLS(false), EnableIPRA(false),
|
||||
DisableIntegratedAS(false), RelaxELFRelocations(true),
|
||||
FunctionSections(false), DataSections(false),
|
||||
IgnoreXCOFFVisibility(false), XCOFFTracebackTable(true),
|
||||
UniqueSectionNames(true), UniqueBasicBlockSectionNames(false),
|
||||
TrapUnreachable(false), NoTrapAfterNoreturn(false), TLSSize(0),
|
||||
EmulatedTLS(false), ExplicitEmulatedTLS(false), EnableIPRA(false),
|
||||
EmitStackSizeSection(false), EnableMachineOutliner(false),
|
||||
EnableMachineFunctionSplitter(false), SupportsDefaultOutlining(false),
|
||||
EmitAddrsig(false), EmitCallSiteInfo(false),
|
||||
@ -144,7 +143,7 @@ namespace llvm {
|
||||
ValueTrackingVariableLocations(false), ForceDwarfFrameSection(false),
|
||||
XRayOmitFunctionIndex(false), DebugStrictDwarf(false),
|
||||
Hotpatch(false), PPCGenScalarMASSEntries(false), JMCInstrument(false),
|
||||
EnableCFIFixup(false), MisExpect(false),
|
||||
EnableCFIFixup(false), MisExpect(false), XCOFFReadOnlyPointers(false),
|
||||
FPDenormalMode(DenormalMode::IEEE, DenormalMode::IEEE) {}
|
||||
|
||||
/// DisableFramePointerElim - This returns true if frame pointer elimination
|
||||
@ -360,6 +359,10 @@ namespace llvm {
|
||||
/// By default, it is set to false
|
||||
unsigned MisExpect : 1;
|
||||
|
||||
/// When set to true, const objects with relocatable address values are put
|
||||
/// into the RO data section.
|
||||
unsigned XCOFFReadOnlyPointers : 1;
|
||||
|
||||
/// Name of the stack usage file (i.e., .su file) if user passes
|
||||
/// -fstack-usage. If empty, it can be implied that -fstack-usage is not
|
||||
/// passed on the command line.
|
||||
|
@ -103,6 +103,7 @@ CGOPT(bool, XRayOmitFunctionIndex)
|
||||
CGOPT(bool, DebugStrictDwarf)
|
||||
CGOPT(unsigned, AlignLoops)
|
||||
CGOPT(bool, JMCInstrument)
|
||||
CGOPT(bool, XCOFFReadOnlyPointers)
|
||||
|
||||
codegen::RegisterCodeGenFlags::RegisterCodeGenFlags() {
|
||||
#define CGBINDOPT(NAME) \
|
||||
@ -478,6 +479,13 @@ codegen::RegisterCodeGenFlags::RegisterCodeGenFlags() {
|
||||
cl::init(false));
|
||||
CGBINDOPT(JMCInstrument);
|
||||
|
||||
static cl::opt<bool> XCOFFReadOnlyPointers(
|
||||
"mroptr",
|
||||
cl::desc("When set to true, const objects with relocatable address "
|
||||
"values are put into the RO data section."),
|
||||
cl::init(false));
|
||||
CGBINDOPT(XCOFFReadOnlyPointers);
|
||||
|
||||
#undef CGBINDOPT
|
||||
|
||||
mc::RegisterMCTargetOptionsFlags();
|
||||
@ -554,6 +562,7 @@ codegen::InitTargetOptionsFromCodeGenFlags(const Triple &TheTriple) {
|
||||
Options.DebugStrictDwarf = getDebugStrictDwarf();
|
||||
Options.LoopAlignment = getAlignLoops();
|
||||
Options.JMCInstrument = getJMCInstrument();
|
||||
Options.XCOFFReadOnlyPointers = getXCOFFReadOnlyPointers();
|
||||
|
||||
Options.MCOptions = mc::InitMCTargetOptionsFromFlags();
|
||||
|
||||
|
@ -2343,8 +2343,11 @@ MCSection *TargetLoweringObjectFileXCOFF::getExplicitSectionGlobal(
|
||||
XCOFF::StorageMappingClass MappingClass;
|
||||
if (Kind.isText())
|
||||
MappingClass = XCOFF::XMC_PR;
|
||||
else if (Kind.isData() || Kind.isReadOnlyWithRel() || Kind.isBSS())
|
||||
else if (Kind.isData() || Kind.isBSS())
|
||||
MappingClass = XCOFF::XMC_RW;
|
||||
else if (Kind.isReadOnlyWithRel())
|
||||
MappingClass =
|
||||
TM.Options.XCOFFReadOnlyPointers ? XCOFF::XMC_RO : XCOFF::XMC_RW;
|
||||
else if (Kind.isReadOnly())
|
||||
MappingClass = XCOFF::XMC_RO;
|
||||
else
|
||||
@ -2429,9 +2432,18 @@ MCSection *TargetLoweringObjectFileXCOFF::SelectSectionForGlobal(
|
||||
return TextSection;
|
||||
}
|
||||
|
||||
// TODO: We may put Kind.isReadOnlyWithRel() under option control, because
|
||||
// user may want to have read-only data with relocations placed into a
|
||||
// read-only section by the compiler.
|
||||
if (TM.Options.XCOFFReadOnlyPointers && Kind.isReadOnlyWithRel()) {
|
||||
if (!TM.getDataSections())
|
||||
report_fatal_error(
|
||||
"ReadOnlyPointers is supported only if data sections is turned on");
|
||||
|
||||
SmallString<128> Name;
|
||||
getNameWithPrefix(Name, GO, TM);
|
||||
return getContext().getXCOFFSection(
|
||||
Name, SectionKind::getReadOnly(),
|
||||
XCOFF::CsectProperties(XCOFF::XMC_RO, XCOFF::XTY_SD));
|
||||
}
|
||||
|
||||
// For BSS kind, zero initialized data must be emitted to the .data section
|
||||
// because external linkage control sections that get mapped to the .bss
|
||||
// section will be linked as tentative defintions, which is only appropriate
|
||||
|
30
llvm/test/CodeGen/PowerPC/aix-xcoff-roptr.ll
Normal file
30
llvm/test/CodeGen/PowerPC/aix-xcoff-roptr.ll
Normal file
@ -0,0 +1,30 @@
|
||||
; RUN: llc -mtriple powerpc-ibm-aix-xcoff -mroptr < %s | FileCheck %s
|
||||
; RUN: llc -mtriple powerpc-ibm-aix-xcoff -mroptr -filetype=obj -o %t.o < %s
|
||||
; RUN: llvm-objdump -t --symbol-description %t.o | FileCheck %s --check-prefix=OBJ
|
||||
|
||||
; RUN: not llc -mtriple powerpc-ibm-aix-xcoff -mroptr -data-sections=false \
|
||||
; RUN: < %s 2>&1 | FileCheck %s --check-prefix=DS_ERR
|
||||
|
||||
; DS_ERR: -mroptr option must be used with -data-sections
|
||||
|
||||
%union.U = type { %"struct.U::A" }
|
||||
%"struct.U::A" = type { ptr }
|
||||
|
||||
@_ZL1p = internal constant i32 ptrtoint (ptr @_ZL1p to i32), align 4
|
||||
; CHECK: .csect _ZL1p[RO],2
|
||||
; CHECK-NEXT: .lglobl _ZL1p[RO]
|
||||
; CHECK-NEXT: .align 2
|
||||
; CHECK-NEXT: .vbyte 4, _ZL1p[RO]
|
||||
; OBJ-DAG: {{([[:xdigit:]]{8})}} l .text {{([[:xdigit:]]{8})}} (idx: [[#]]) _ZL1p[RO]
|
||||
@q = thread_local constant ptr @_ZL1p, align 4
|
||||
; CHECK: .csect q[TL],2
|
||||
; CHECK-NEXT: .globl q[TL]
|
||||
; CHECK-NEXT: .align 2
|
||||
; CHECK-NEXT: .vbyte 4, _ZL1p[RO]
|
||||
; OBJ-DAG: {{([[:xdigit:]]{8})}} g O .tdata {{([[:xdigit:]]{8})}} (idx: [[#]]) q[TL]
|
||||
@u = local_unnamed_addr constant [1 x %union.U] [%union.U { %"struct.U::A" { ptr @_ZL1p } }], align 4
|
||||
; CHECK: .csect u[RO],2
|
||||
; CHECK-NEXT: .globl u[RO]
|
||||
; CHECK-NEXT: .align 2
|
||||
; CHECK-NEXT: .vbyte 4, _ZL1p[RO]
|
||||
; OBJ-DAG: {{([[:xdigit:]]{8})}} g .text {{([[:xdigit:]]{8})}} (idx: [[#]]) u[RO]
|
33
llvm/test/CodeGen/PowerPC/aix64-xcoff-roptr.ll
Normal file
33
llvm/test/CodeGen/PowerPC/aix64-xcoff-roptr.ll
Normal file
@ -0,0 +1,33 @@
|
||||
; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -mroptr < %s | FileCheck %s
|
||||
; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -mroptr -filetype=obj -o %t.o < %s
|
||||
; RUN: llvm-objdump -t --symbol-description %t.o | FileCheck %s --check-prefix=OBJ
|
||||
|
||||
; RUN: not llc -mtriple powerpc64-ibm-aix-xcoff -mroptr -data-sections=false \
|
||||
; RUN: < %s 2>&1 | FileCheck %s --check-prefix=DS_ERR
|
||||
; RUN: not llc -mtriple powerpc64le-unknown-linux-gnu -mroptr \
|
||||
; RUN: < %s 2>&1 | FileCheck %s --check-prefix=OS_ERR
|
||||
|
||||
; DS_ERR: -mroptr option must be used with -data-sections
|
||||
; OS_ERR: -mroptr option is only supported on AIX
|
||||
|
||||
%union.U = type { %"struct.U::A" }
|
||||
%"struct.U::A" = type { ptr }
|
||||
|
||||
@_ZL1p = internal constant i64 ptrtoint (ptr @_ZL1p to i64), align 8
|
||||
; CHECK: .csect _ZL1p[RO],3
|
||||
; CHECK-NEXT: .lglobl _ZL1p[RO]
|
||||
; CHECK-NEXT: .align 3
|
||||
; CHECK-NEXT: .vbyte 8, _ZL1p[RO]
|
||||
; OBJ-DAG: {{([[:xdigit:]]{16})}} l .text {{([[:xdigit:]]{16})}} (idx: [[#]]) _ZL1p[RO]
|
||||
@q = thread_local constant ptr @_ZL1p, align 8
|
||||
; CHECK: .csect q[TL],3
|
||||
; CHECK-NEXT: .globl q[TL]
|
||||
; CHECK-NEXT: .align 3
|
||||
; CHECK-NEXT: .vbyte 8, _ZL1p[RO]
|
||||
; OBJ-DAG: {{([[:xdigit:]]{16})}} g O .tdata {{([[:xdigit:]]{16})}} (idx: [[#]]) q[TL]
|
||||
@u = local_unnamed_addr constant [1 x %union.U] [%union.U { %"struct.U::A" { ptr @_ZL1p } }], align 8
|
||||
; CHECK: .csect u[RO],3
|
||||
; CHECK-NEXT: .globl u[RO]
|
||||
; CHECK-NEXT: .align 3
|
||||
; CHECK-NEXT: .vbyte 8, _ZL1p[RO]
|
||||
; OBJ-DAG: {{([[:xdigit:]]{16})}} g .text {{([[:xdigit:]]{16})}} (idx: [[#]]) u[RO]
|
@ -496,6 +496,24 @@ static int compileModule(char **argv, LLVMContext &Context) {
|
||||
TargetOptions Options;
|
||||
auto InitializeOptions = [&](const Triple &TheTriple) {
|
||||
Options = codegen::InitTargetOptionsFromCodeGenFlags(TheTriple);
|
||||
|
||||
if (Options.XCOFFReadOnlyPointers) {
|
||||
if (!TheTriple.isOSAIX())
|
||||
reportError("-mroptr option is only supported on AIX", InputFilename);
|
||||
|
||||
// Since the storage mapping class is specified per csect,
|
||||
// without using data sections, it is less effective to use read-only
|
||||
// pointers. Using read-only pointers may cause other RO variables in the
|
||||
// same csect to become RW when the linker acts upon `-bforceimprw`;
|
||||
// therefore, we require that separate data sections are used in the
|
||||
// presence of ReadOnlyPointers. We respect the setting of data-sections
|
||||
// since we have not found reasons to do otherwise that overcome the user
|
||||
// surprise of not respecting the setting.
|
||||
if (!Options.DataSections)
|
||||
reportError("-mroptr option must be used with -data-sections",
|
||||
InputFilename);
|
||||
}
|
||||
|
||||
Options.BinutilsVersion =
|
||||
TargetMachine::parseBinutilsVersion(BinutilsVersion);
|
||||
Options.DisableIntegratedAS = NoIntegratedAssembler;
|
||||
|
Loading…
x
Reference in New Issue
Block a user