From 0c2312ff9f30ef716fd3198d7f8d84b486385470 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool <compnerd@compnerd.org> Date: Mon, 30 May 2016 16:23:07 +0000 Subject: [PATCH] CodeGen: tweak CFConstantStrings for COFF and ELF Adjust the constant CFString emission to emit into more appropriate sections on ELF and COFF targets. It would previously try to use MachO section names irrespective of the file format. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@271211 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenModule.cpp | 51 +++++++++++++++++++++-------------- test/CodeGen/CFStrings.c | 49 +++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 20 deletions(-) create mode 100644 test/CodeGen/CFStrings.c diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 0c75cf111b1..cd278e65c15 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -3092,19 +3092,19 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { llvm::Constant *Zero = llvm::Constant::getNullValue(Int32Ty); llvm::Constant *Zeros[] = { Zero, Zero }; llvm::Value *V; - + // If we don't already have it, get __CFConstantStringClassReference. if (!CFConstantStringClassRef) { llvm::Type *Ty = getTypes().ConvertType(getContext().IntTy); Ty = llvm::ArrayType::get(Ty, 0); - llvm::Constant *GV = CreateRuntimeVariable(Ty, - "__CFConstantStringClassReference"); + llvm::Constant *GV = + CreateRuntimeVariable(Ty, "__CFConstantStringClassReference"); // Decay array -> ptr V = llvm::ConstantExpr::getGetElementPtr(Ty, GV, Zeros); CFConstantStringClassRef = V; - } - else + } else { V = CFConstantStringClassRef; + } QualType CFTy = getContext().getCFConstantStringType(); @@ -3117,8 +3117,8 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { // Flags. llvm::Type *Ty = getTypes().ConvertType(getContext().UnsignedIntTy); - Fields[1] = isUTF16 ? llvm::ConstantInt::get(Ty, 0x07d0) : - llvm::ConstantInt::get(Ty, 0x07C8); + Fields[1] = isUTF16 ? llvm::ConstantInt::get(Ty, 0x07d0) + : llvm::ConstantInt::get(Ty, 0x07C8); // String pointer. llvm::Constant *C = nullptr; @@ -3139,18 +3139,17 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { GV->setUnnamedAddr(true); // Don't enforce the target's minimum global alignment, since the only use // of the string is via this class initializer. - // FIXME: We set the section explicitly to avoid a bug in ld64 224.1. Without - // it LLVM can merge the string with a non unnamed_addr one during LTO. Doing - // that changes the section it ends in, which surprises ld64. - if (isUTF16) { - CharUnits Align = getContext().getTypeAlignInChars(getContext().ShortTy); - GV->setAlignment(Align.getQuantity()); - GV->setSection("__TEXT,__ustring"); - } else { - CharUnits Align = getContext().getTypeAlignInChars(getContext().CharTy); - GV->setAlignment(Align.getQuantity()); - GV->setSection("__TEXT,__cstring,cstring_literals"); - } + CharUnits Align = isUTF16 + ? getContext().getTypeAlignInChars(getContext().ShortTy) + : getContext().getTypeAlignInChars(getContext().CharTy); + GV->setAlignment(Align.getQuantity()); + + // FIXME: We set the section explicitly to avoid a bug in ld64 224.1. + // Without it LLVM can merge the string with a non unnamed_addr one during + // LTO. Doing that changes the section it ends in, which surprises ld64. + if (getTarget().getTriple().getObjectFormat() == llvm::Triple::MachO) + GV->setSection(isUTF16 ? "__TEXT,__ustring" + : "__TEXT,__cstring,cstring_literals"); // String. Fields[2] = @@ -3171,8 +3170,20 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { GV = new llvm::GlobalVariable(getModule(), C->getType(), true, llvm::GlobalVariable::PrivateLinkage, C, "_unnamed_cfstring_"); - GV->setSection("__DATA,__cfstring"); GV->setAlignment(Alignment.getQuantity()); + switch (getTarget().getTriple().getObjectFormat()) { + case llvm::Triple::UnknownObjectFormat: + llvm_unreachable("unknown file format"); + case llvm::Triple::COFF: + GV->setSection(".rdata.cfstring"); + break; + case llvm::Triple::ELF: + GV->setSection(".rodata.cfstring"); + break; + case llvm::Triple::MachO: + GV->setSection("__DATA,__cfstring"); + break; + } Entry.second = GV; return ConstantAddress(GV, Alignment); diff --git a/test/CodeGen/CFStrings.c b/test/CodeGen/CFStrings.c new file mode 100644 index 00000000000..7d8959328ce --- /dev/null +++ b/test/CodeGen/CFStrings.c @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -triple thumbv7-windows -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-COFF +// RUN: %clang_cc1 -triple i686-windows -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-COFF +// RUN: %clang_cc1 -triple x86_64-windows -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-COFF + +// RUN: %clang_cc1 -triple armv7-elf -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-ELF -check-prefix CHECK-ELF32 +// RUN: %clang_cc1 -triple i686-elf -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-ELF -check-prefix CHECK-ELF32 +// RUN: %clang_cc1 -triple x86_64-elf -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-ELF -check-prefix CHECK-ELF64 +// RUN: %clang_cc1 -triple armv7-elf -S %s -o - | FileCheck %s -check-prefix CHECK-ELF-DATA-SECTION + +// RUN: %clang_cc1 -triple armv7-macho -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACHO -check-prefix CHECK-MACHO32 +// RUN: %clang_cc1 -triple i386-apple-macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACHO -check-prefix CHECK-MACHO32 +// RUN: %clang_cc1 -triple x86_64-macho -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACHO -check-prefix CHECK-MACHO64 + +typedef struct __CFString *CFStringRef; +const CFStringRef one = (CFStringRef)__builtin___CFStringMakeConstantString("one"); +const CFStringRef two = (CFStringRef)__builtin___CFStringMakeConstantString("\xef\xbf\xbd\x74\xef\xbf\xbd\x77\xef\xbf\xbd\x6f"); + +// CHECK-COFF: @.str = private unnamed_addr constant [4 x i8] c"one\00", align 1 +// CHECK-ELF: @.str = private unnamed_addr constant [4 x i8] c"one\00", align 1 +// CHECK-MACHO: @.str = private unnamed_addr constant [4 x i8] c"one\00", section "__TEXT,__cstring,cstring_literals", align 1 + +// CHECK-COFF: @_unnamed_cfstring_ = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 3 }, section ".rdata.cfstring", align {{[48]}} +// CHECK-ELF32: @_unnamed_cfstring_ = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 3 }, section ".rodata.cfstring", align 4 +// CHECK-ELF64: @_unnamed_cfstring_ = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i64 3 }, section ".rodata.cfstring", align 8 +// CHECK-MACHO32: @_unnamed_cfstring_ = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 3 }, section "__DATA,__cfstring", align 4 +// CHECK-MACHO64: @_unnamed_cfstring_ = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i64 3 }, section "__DATA,__cfstring", align 8 + +// CHECK-COFF: @.str.1 = private unnamed_addr constant [7 x i16] [i16 -3, i16 116, i16 -3, i16 119, i16 -3, i16 111, i16 0], align 2 +// CHECK-ELF: @.str.1 = private unnamed_addr constant [7 x i16] [i16 -3, i16 116, i16 -3, i16 119, i16 -3, i16 111, i16 0], align 2 +// CHECK-MACHO: @.str.1 = private unnamed_addr constant [7 x i16] [i16 -3, i16 116, i16 -3, i16 119, i16 -3, i16 111, i16 0], section "__TEXT,__ustring", align 2 + +// CHECK-COFF: @_unnamed_cfstring_.2 = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 2000, i8* bitcast ([7 x i16]* @.str.1 to i8*), i32 6 }, section ".rdata.cfstring", align {{[48]}} +// CHECK-ELF32: @_unnamed_cfstring_.2 = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 2000, i8* bitcast ([7 x i16]* @.str.1 to i8*), i32 6 }, section ".rodata.cfstring", align 4 +// CHECK-ELF64: @_unnamed_cfstring_.2 = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 2000, i8* bitcast ([7 x i16]* @.str.1 to i8*), i64 6 }, section ".rodata.cfstring", align 8 +// CHECK-MACHO32: @_unnamed_cfstring_.2 = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 2000, i8* bitcast ([7 x i16]* @.str.1 to i8*), i32 6 }, section "__DATA,__cfstring", align 4 +// CHECK-MACHO64: @_unnamed_cfstring_.2 = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 2000, i8* bitcast ([7 x i16]* @.str.1 to i8*), i64 6 }, section "__DATA,__cfstring", align 8 + +// CHECK-ELF-DATA-SECTION: .section .rodata.str1.1 +// CHECK-ELF-DATA-SECTION: .asciz "one" + +// CHECK-ELF-DATA-SECTION: .section .rodata.str2.2 +// CHECK-ELF-DATA-SECTION: .short 65533 +// CHECK-ELF-DATA-SECTION: .short 116 +// CHECK-ELF-DATA-SECTION: .short 65533 +// CHECK-ELF-DATA-SECTION: .short 119 +// CHECK-ELF-DATA-SECTION: .short 65533 +// CHECK-ELF-DATA-SECTION: .short 111 +// CHECK-ELF-DATA-SECTION: .short 0 + -- GitLab