From d3abd0b648dd795dc481cc06169714738eb9bbdc Mon Sep 17 00:00:00 2001 From: Robert Lytton Date: Tue, 11 Feb 2014 10:36:26 +0000 Subject: [PATCH] XCore target: fix const section handling Xcore target ABI requires const data that is externally visible to be handled differently if it has C-language linkage rather than C++ language linkage. Clang now emits ".cp.rodata" section information. All other externally visible constant data will be placed in the DP section. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@201144 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/XCore/XCoreISelLowering.cpp | 5 +- lib/Target/XCore/XCoreTargetObjectFile.cpp | 62 ++++++++++++---------- lib/Target/XCore/XCoreTargetObjectFile.h | 1 + test/CodeGen/XCore/codemodel.ll | 24 +++++++-- test/CodeGen/XCore/exception.ll | 3 +- test/CodeGen/XCore/globals.ll | 53 ++++++++++++++---- test/CodeGen/XCore/llvm-intrinsics.ll | 5 +- test/CodeGen/XCore/load.ll | 2 +- 8 files changed, 107 insertions(+), 48 deletions(-) diff --git a/lib/Target/XCore/XCoreISelLowering.cpp b/lib/Target/XCore/XCoreISelLowering.cpp index 82ad0d069a3..842531c455d 100644 --- a/lib/Target/XCore/XCoreISelLowering.cpp +++ b/lib/Target/XCore/XCoreISelLowering.cpp @@ -275,7 +275,10 @@ getGlobalAddressWrapper(SDValue GA, const GlobalValue *GV, if (const GlobalAlias *GA = dyn_cast(GV)) UnderlyingGV = GA->resolveAliasedGlobal(); if (const GlobalVariable *GVar = dyn_cast(UnderlyingGV)) { - if (GVar->isConstant()) + if ( ( GVar->isConstant() && + UnderlyingGV->isLocalLinkage(GV->getLinkage()) ) + || ( GVar->hasSection() && + StringRef(GVar->getSection()).startswith(".cp.") ) ) return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, GA); return DAG.getNode(XCoreISD::DPRelativeWrapper, dl, MVT::i32, GA); } diff --git a/lib/Target/XCore/XCoreTargetObjectFile.cpp b/lib/Target/XCore/XCoreTargetObjectFile.cpp index cf565e7a1e7..33b719b34d2 100644 --- a/lib/Target/XCore/XCoreTargetObjectFile.cpp +++ b/lib/Target/XCore/XCoreTargetObjectFile.cpp @@ -41,10 +41,16 @@ void XCoreTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){ ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::XCORE_SHF_DP_SECTION, SectionKind::getDataRel()); - // This is the wrong place to decide if const data should be placed - // in the .cp or .dp section. - // Ideally we should set up DataRelROSection to use the '.dp.'' and use this - // for const data, unless the front end explicitly states a '.cp.'' section. + DataRelROSection = + Ctx.getELFSection(".dp.rodata", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | ELF::SHF_WRITE | + ELF::XCORE_SHF_DP_SECTION, + SectionKind::getReadOnlyWithRel()); + DataRelROSectionLarge = + Ctx.getELFSection(".dp.rodata.large", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | ELF::SHF_WRITE | + ELF::XCORE_SHF_DP_SECTION, + SectionKind::getReadOnlyWithRel()); ReadOnlySection = Ctx.getELFSection(".cp.rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | @@ -80,19 +86,13 @@ void XCoreTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){ // StaticDtorSection - see MObjectFileInfo.cpp } -static SectionKind getXCoreKindForNamedSection(StringRef Name, SectionKind K) { - if (Name.startswith(".cp.")) - return SectionKind::getReadOnly(); - return K; -} - static unsigned getXCoreSectionType(SectionKind K) { if (K.isBSS()) return ELF::SHT_NOBITS; return ELF::SHT_PROGBITS; } -static unsigned getXCoreSectionFlags(SectionKind K) { +static unsigned getXCoreSectionFlags(SectionKind K, bool IsCPRel) { unsigned Flags = 0; if (!K.isMetadata()) @@ -100,7 +100,7 @@ static unsigned getXCoreSectionFlags(SectionKind K) { if (K.isText()) Flags |= ELF::SHF_EXECINSTR; - else if (K.isReadOnly()) + else if (IsCPRel) Flags |= ELF::XCORE_SHF_CP_SECTION; else Flags |= ELF::XCORE_SHF_DP_SECTION; @@ -123,33 +123,41 @@ getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, Mangler &Mang, const TargetMachine &TM) const { StringRef SectionName = GV->getSection(); // Infer section flags from the section name if we can. - Kind = getXCoreKindForNamedSection(SectionName, Kind); + bool IsCPRel = SectionName.startswith(".cp."); + if (IsCPRel && !Kind.isReadOnly()) + report_fatal_error("Using .cp. section for writeable object."); return getContext().getELFSection(SectionName, getXCoreSectionType(Kind), - getXCoreSectionFlags(Kind), Kind); + getXCoreSectionFlags(Kind, IsCPRel), Kind); } const MCSection *XCoreTargetObjectFile:: SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler &Mang, const TargetMachine &TM) const{ - if (Kind.isText()) return TextSection; - if (Kind.isMergeable1ByteCString()) return CStringSection; - if (Kind.isMergeableConst4()) return MergeableConst4Section; - if (Kind.isMergeableConst8()) return MergeableConst8Section; - if (Kind.isMergeableConst16()) return MergeableConst16Section; + bool UseCPRel = GV->isLocalLinkage(GV->getLinkage()); + + if (Kind.isText()) return TextSection; + if (UseCPRel) { + if (Kind.isMergeable1ByteCString()) return CStringSection; + if (Kind.isMergeableConst4()) return MergeableConst4Section; + if (Kind.isMergeableConst8()) return MergeableConst8Section; + if (Kind.isMergeableConst16()) return MergeableConst16Section; + } Type *ObjType = GV->getType()->getPointerElementType(); if (TM.getCodeModel() == CodeModel::Small || !ObjType->isSized() || TM.getDataLayout()->getTypeAllocSize(ObjType) < CodeModelLargeSize) { - if (Kind.isReadOnly()) return ReadOnlySection; - if (Kind.isBSS()) return BSSSection; - if (Kind.isDataRel()) return DataSection; - if (Kind.isReadOnlyWithRel()) return ReadOnlySection; + if (Kind.isReadOnly()) return UseCPRel? ReadOnlySection + : DataRelROSection; + if (Kind.isBSS()) return BSSSection; + if (Kind.isDataRel()) return DataSection; + if (Kind.isReadOnlyWithRel()) return DataRelROSection; } else { - if (Kind.isReadOnly()) return ReadOnlySectionLarge; - if (Kind.isBSS()) return BSSSectionLarge; - if (Kind.isDataRel()) return DataSectionLarge; - if (Kind.isReadOnlyWithRel()) return ReadOnlySectionLarge; + if (Kind.isReadOnly()) return UseCPRel? ReadOnlySectionLarge + : DataRelROSectionLarge; + if (Kind.isBSS()) return BSSSectionLarge; + if (Kind.isDataRel()) return DataSectionLarge; + if (Kind.isReadOnlyWithRel()) return DataRelROSectionLarge; } assert((Kind.isThreadLocal() || Kind.isCommon()) && "Unknown section kind"); diff --git a/lib/Target/XCore/XCoreTargetObjectFile.h b/lib/Target/XCore/XCoreTargetObjectFile.h index 47d7fad8eea..aa345043c0e 100644 --- a/lib/Target/XCore/XCoreTargetObjectFile.h +++ b/lib/Target/XCore/XCoreTargetObjectFile.h @@ -20,6 +20,7 @@ static const unsigned CodeModelLargeSize = 256; const MCSection *BSSSectionLarge; const MCSection *DataSectionLarge; const MCSection *ReadOnlySectionLarge; + const MCSection *DataRelROSectionLarge; public: void Initialize(MCContext &Ctx, const TargetMachine &TM); diff --git a/test/CodeGen/XCore/codemodel.ll b/test/CodeGen/XCore/codemodel.ll index cc532ea7def..0245893c478 100644 --- a/test/CodeGen/XCore/codemodel.ll +++ b/test/CodeGen/XCore/codemodel.ll @@ -171,27 +171,43 @@ entry: ; LARGE: .space 40 @s = global [10 x i32] zeroinitializer -; CHECK: .section .cp.rodata,"ac",@progbits +; CHECK: .section .dp.rodata,"awd",@progbits ; CHECK-LABEL: cl: ; CHECK: .space 400 -; LARGE: .section .cp.rodata.large,"ac",@progbits +; LARGE: .section .dp.rodata.large,"awd",@progbits ; LARGE-LABEL: cl: ; LARGE: .space 400 @cl = constant [100 x i32] zeroinitializer ; CHECK-LABEL: cs: ; CHECK: .space 40 -; LARGE: .section .cp.rodata,"ac",@progbits +; LARGE: .section .dp.rodata,"awd",@progbits ; LARGE-LABEL: cs: ; LARGE: .space 40 @cs = constant [10 x i32] zeroinitializer +; CHECK: .section .cp.rodata,"ac",@progbits +; CHECK-LABEL: icl: +; CHECK: .space 400 +; LARGE: .section .cp.rodata.large,"ac",@progbits +; LARGE-LABEL: icl: +; LARGE: .space 400 +@icl = internal constant [100 x i32] zeroinitializer + +; CHECK-LABEL: cs: +; CHECK: .space 40 +; LARGE: .section .cp.rodata,"ac",@progbits +; LARGE-LABEL: cs: +; LARGE: .space 40 +@ics = internal constant [10 x i32] zeroinitializer + ; CHECK: .section .cp.namedsection,"ac",@progbits ; CHECK-LABEL: cpsec: ; CHECK: .long 0 -@cpsec = global i32 0, section ".cp.namedsection" +@cpsec = constant i32 0, section ".cp.namedsection" ; CHECK: .section .dp.namedsection,"awd",@progbits ; CHECK-LABEL: dpsec: ; CHECK: .long 0 @dpsec = global i32 0, section ".dp.namedsection" + diff --git a/test/CodeGen/XCore/exception.ll b/test/CodeGen/XCore/exception.ll index 8018cdcada7..3179fcdfcf5 100644 --- a/test/CodeGen/XCore/exception.ll +++ b/test/CodeGen/XCore/exception.ll @@ -29,9 +29,8 @@ entry: ; CHECK: .cfi_offset 15, 0 ; CHECK: ldc r0, 4 ; CHECK: bl __cxa_allocate_exception -; CHECK: ldaw r11, cp[_ZTIi] +; CHECK: ldaw r1, dp[_ZTIi] ; CHECK: ldc r2, 0 -; CHECK: mov r1, r11 ; CHECK: bl __cxa_throw define void @fn_throw() { entry: diff --git a/test/CodeGen/XCore/globals.ll b/test/CodeGen/XCore/globals.ll index b3a872bb689..04e135c25ca 100644 --- a/test/CodeGen/XCore/globals.ll +++ b/test/CodeGen/XCore/globals.ll @@ -17,11 +17,18 @@ entry: define i32 *@addr_G3() { entry: ; CHECK-LABEL: addr_G3: -; CHECK: ldaw r11, cp[G3] -; CHECK: mov r0, r11 +; CHECK: ldaw r0, dp[G3] ret i32* @G3 } +define i32 *@addr_iG3() { +entry: +; CHECK-LABEL: addr_iG3: +; CHECK: ldaw r11, cp[iG3] +; CHECK: mov r0, r11 + ret i32* @iG3 +} + define i32 **@addr_G4() { entry: ; CHECK-LABEL: addr_G4: @@ -32,11 +39,18 @@ entry: define i32 **@addr_G5() { entry: ; CHECK-LABEL: addr_G5: -; CHECK: ldaw r11, cp[G5] -; CHECK: mov r0, r11 +; CHECK: ldaw r0, dp[G5] ret i32** @G5 } +define i32 **@addr_iG5() { +entry: +; CHECK-LABEL: addr_iG5: +; CHECK: ldaw r11, cp[iG5] +; CHECK: mov r0, r11 + ret i32** @iG5 +} + define i32 **@addr_G6() { entry: ; CHECK-LABEL: addr_G6: @@ -47,11 +61,18 @@ entry: define i32 **@addr_G7() { entry: ; CHECK-LABEL: addr_G7: -; CHECK: ldaw r11, cp[G7] -; CHECK: mov r0, r11 +; CHECK: ldaw r0, dp[G7] ret i32** @G7 } +define i32 **@addr_iG7() { +entry: +; CHECK-LABEL: addr_iG7: +; CHECK: ldaw r11, cp[iG7] +; CHECK: mov r0, r11 + ret i32** @iG7 +} + define i32 *@addr_G8() { entry: ; CHECK-LABEL: addr_G8: @@ -68,26 +89,38 @@ entry: ; CHECK: G2: @G3 = unnamed_addr constant i32 9401 -; CHECK: .section .cp.rodata.cst4,"aMc",@progbits,4 +; CHECK: .section .dp.rodata,"awd",@progbits ; CHECK: G3: +@iG3 = internal constant i32 9401 +; CHECK: .section .cp.rodata,"ac",@progbits +; CHECK: iG3: + @G4 = global i32* @G1 ; CHECK: .section .dp.data,"awd",@progbits ; CHECK: G4: @G5 = unnamed_addr constant i32* @G1 -; CHECK: .section .cp.rodata,"ac",@progbits +; CHECK: .section .dp.rodata,"awd",@progbits ; CHECK: G5: +@iG5 = internal unnamed_addr constant i32* @G1 +; CHECK: .section .cp.rodata,"ac",@progbits +; CHECK: iG5: + @G6 = global i32* @G8 ; CHECK: .section .dp.data,"awd",@progbits ; CHECK: G6: @G7 = unnamed_addr constant i32* @G8 -; CHECK: .section .cp.rodata,"ac",@progbits +; CHECK: .section .dp.rodata,"awd",@progbits ; CHECK: G7: -@G8 = internal global i32 9312 +@iG7 = internal unnamed_addr constant i32* @G8 +; CHECK: .section .cp.rodata,"ac",@progbits +; CHECK: iG7: + +@G8 = global i32 9312 ; CHECK: .section .dp.data,"awd",@progbits ; CHECK: G8: diff --git a/test/CodeGen/XCore/llvm-intrinsics.ll b/test/CodeGen/XCore/llvm-intrinsics.ll index be5fd78cd21..e7c78af2122 100644 --- a/test/CodeGen/XCore/llvm-intrinsics.ll +++ b/test/CodeGen/XCore/llvm-intrinsics.ll @@ -119,13 +119,12 @@ entry: ; CHECK-LABEL: EH2 ; CHECK: entsp 1 ; CHECK: bl foo -; CHECK-NEXT: ldw r0, cp[offset] +; CHECK-NEXT: ldw r0, dp[offset] ; CHECK-NEXT: ldc r1, 4 ; CHECK-NEXT: ldaw r2, sp[0] ; CHECK-NEXT: add r1, r2, r1 ; CHECK-NEXT: add r2, r1, r0 -; CHECK-NEXT: ldaw r11, cp[handler] -; CHECK-NEXT: mov r3, r11 +; CHECK-NEXT: ldaw r3, dp[handler] ; CHECK-NEXT: set sp, r2 ; CHECK-NEXT: bau r3 call void (...)* @foo() diff --git a/test/CodeGen/XCore/load.ll b/test/CodeGen/XCore/load.ll index 0622f1cd135..c7fc2a33db1 100644 --- a/test/CodeGen/XCore/load.ll +++ b/test/CodeGen/XCore/load.ll @@ -40,7 +40,7 @@ entry: ret i32 %2 } -@GConst = external constant i32 +@GConst = internal constant i32 42 define i32 @load_cp() nounwind { entry: ; CHECK-LABEL: load_cp: