diff options
| -rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 36 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/global-array-destruction.cpp | 33 | 
2 files changed, 48 insertions, 21 deletions
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 2939062c9bb..fd787394d78 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -881,33 +881,49 @@ llvm::Value *CodeGenFunction::emitArrayLength(const ArrayType *origArrayType,    llvm::ConstantInt *zero = Builder.getInt32(0);    gepIndices.push_back(zero); -  // It's more efficient to calculate the count from the LLVM -  // constant-length arrays than to re-evaluate the array bounds.    uint64_t countFromCLAs = 1; +  QualType eltType;    llvm::ArrayType *llvmArrayType = -    cast<llvm::ArrayType>( +    dyn_cast<llvm::ArrayType>(        cast<llvm::PointerType>(addr->getType())->getElementType()); -  while (true) { +  while (llvmArrayType) {      assert(isa<ConstantArrayType>(arrayType));      assert(cast<ConstantArrayType>(arrayType)->getSize().getZExtValue()               == llvmArrayType->getNumElements());      gepIndices.push_back(zero);      countFromCLAs *= llvmArrayType->getNumElements(); +    eltType = arrayType->getElementType();      llvmArrayType =        dyn_cast<llvm::ArrayType>(llvmArrayType->getElementType()); -    if (!llvmArrayType) break; -      arrayType = getContext().getAsArrayType(arrayType->getElementType()); -    assert(arrayType && "LLVM and Clang types are out-of-synch"); +    assert((!llvmArrayType || arrayType) && +           "LLVM and Clang types are out-of-synch");    } -  baseType = arrayType->getElementType(); +  if (arrayType) { +    // From this point onwards, the Clang array type has been emitted +    // as some other type (probably a packed struct). Compute the array +    // size, and just emit the 'begin' expression as a bitcast. +    while (arrayType) { +      countFromCLAs *= +          cast<ConstantArrayType>(arrayType)->getSize().getZExtValue(); +      eltType = arrayType->getElementType(); +      arrayType = getContext().getAsArrayType(eltType); +    } + +    unsigned AddressSpace = +        cast<llvm::PointerType>(addr->getType())->getAddressSpace(); +    llvm::Type *BaseType = ConvertType(eltType)->getPointerTo(AddressSpace); +    addr = Builder.CreateBitCast(addr, BaseType, "array.begin"); +  } else { +    // Create the actual GEP. +    addr = Builder.CreateInBoundsGEP(addr, gepIndices, "array.begin"); +  } -  // Create the actual GEP. -  addr = Builder.CreateInBoundsGEP(addr, gepIndices, "array.begin"); +  baseType = eltType;    llvm::Value *numElements      = llvm::ConstantInt::get(SizeTy, countFromCLAs); diff --git a/clang/test/CodeGenCXX/global-array-destruction.cpp b/clang/test/CodeGenCXX/global-array-destruction.cpp index 5b5dfac0f22..076ef942201 100644 --- a/clang/test/CodeGenCXX/global-array-destruction.cpp +++ b/clang/test/CodeGenCXX/global-array-destruction.cpp @@ -1,6 +1,4 @@ -// REQUIRES: x86-64-registered-target -// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s -// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm %s -o - | FileCheck %s  extern "C" int printf(...); @@ -24,11 +22,24 @@ static S sarr1[4];  S s2;  S arr3[3]; -// CHECK-LP64: callq    ___cxa_atexit -// CHECK-LP64: callq    ___cxa_atexit -// CHECK-LP64: callq    ___cxa_atexit -// CHECK-LP64: callq    ___cxa_atexit -// CHECK-LP64: callq    ___cxa_atexit -// CHECK-LP64: callq    ___cxa_atexit -// CHECK-LP64: callq    ___cxa_atexit -// CHECK-LP64: callq    ___cxa_atexit +// CHECK: call {{.*}} @__cxa_atexit +// CHECK: call {{.*}} @__cxa_atexit +// CHECK: call {{.*}} @__cxa_atexit +// CHECK: call {{.*}} @__cxa_atexit +// CHECK: call {{.*}} @__cxa_atexit +// CHECK: call {{.*}} @__cxa_atexit +// CHECK: call {{.*}} @__cxa_atexit +// CHECK: call {{.*}} @__cxa_atexit + +struct T { +  double d; +  int n; +  ~T(); +}; +T t[2][3] = { 1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10, 11.0, 12 }; + +// CHECK: call {{.*}} @__cxa_atexit +// CHECK: getelementptr inbounds ({{.*}} bitcast {{.*}}* @t to %struct.T*), i64 6 +// CHECK: call void @_ZN1TD1Ev +// CHECK: icmp eq {{.*}} @t +// CHECK: br i1 {{.*}}  | 

