summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CodeGenFunction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CodeGenFunction.cpp')
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp36
1 files changed, 26 insertions, 10 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);
OpenPOWER on IntegriCloud