Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: m-labs/clang-lm32
base: 4d9550d
...
head fork: m-labs/clang-lm32
compare: 686ed60
  • 6 commits
  • 14 files changed
  • 0 commit comments
  • 4 contributors
Commits on Jun 24, 2011
Bob Wilson Shorten some ARM builtin names by removing unnecessary "neon" prefix.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133826 91177308-0d34-0410-b5e6-96231b3b80d8
89f19e4
@jpbonn jpbonn Merge github.com:milkymist/clang-lm32 57d3dac
@rjmccall rjmccall Change the IR-generation of VLAs so that we capture bounds,
not sizes;  so that we use well-typed allocas;  and so that we
properly recurse through the full set of variably-modified types.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133827 91177308-0d34-0410-b5e6-96231b3b80d8
bc8d40d
Devang Patel Fix struct member's scope. Patch by Xi Wang.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133829 91177308-0d34-0410-b5e6-96231b3b80d8
1d323e0
Bob Wilson Revert "Shorten some ARM builtin names by removing unnecessary "neon"…
… prefix."

Sorry, this was a bad idea.  Within clang these builtins are in a separate
"ARM" namespace, but the actual builtin names should clearly distinguish tha
they are target specific.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133833 91177308-0d34-0410-b5e6-96231b3b80d8
537c346
@jpbonn jpbonn Merge branch 'master' of http://llvm.org/git/clang 686ed60
View
47 lib/CodeGen/CGDebugInfo.cpp
@@ -314,8 +314,9 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
llvm::SmallVector<llvm::Value *, 16> EltTys;
llvm::DIType FieldTy =
- DBuilder.createMemberType("isa", getOrCreateMainFile(),
- 0,Size, 0, 0, 0, ISATy);
+ DBuilder.createMemberType(getOrCreateMainFile(), "isa",
+ getOrCreateMainFile(), 0, Size,
+ 0, 0, 0, ISATy);
EltTys.push_back(FieldTy);
llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
@@ -529,7 +530,7 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
FieldTy = DescTy;
FieldSize = CGM.getContext().getTypeSize(Ty);
FieldAlign = CGM.getContext().getTypeAlign(Ty);
- FieldTy = DBuilder.createMemberType("__descriptor", Unit,
+ FieldTy = DBuilder.createMemberType(Unit, "__descriptor", Unit,
LineNo, FieldSize, FieldAlign,
FieldOffset, 0, FieldTy);
EltTys.push_back(FieldTy);
@@ -592,7 +593,8 @@ llvm::DIType CGDebugInfo::createFieldType(llvm::StringRef name,
SourceLocation loc,
AccessSpecifier AS,
uint64_t offsetInBits,
- llvm::DIFile tunit) {
+ llvm::DIFile tunit,
+ llvm::DIDescriptor scope) {
llvm::DIType debugType = getOrCreateType(type, tunit);
// Get the location for the field.
@@ -614,15 +616,16 @@ llvm::DIType CGDebugInfo::createFieldType(llvm::StringRef name,
else if (AS == clang::AS_protected)
flags |= llvm::DIDescriptor::FlagProtected;
- return DBuilder.createMemberType(name, file, line, sizeInBits, alignInBits,
- offsetInBits, flags, debugType);
+ return DBuilder.createMemberType(scope, name, file, line, sizeInBits,
+ alignInBits, offsetInBits, flags, debugType);
}
/// CollectRecordFields - A helper function to collect debug info for
/// record fields. This is used while creating debug info entry for a Record.
void CGDebugInfo::
CollectRecordFields(const RecordDecl *record, llvm::DIFile tunit,
- llvm::SmallVectorImpl<llvm::Value *> &elements) {
+ llvm::SmallVectorImpl<llvm::Value *> &elements,
+ llvm::DIType RecordTy) {
unsigned fieldNo = 0;
const FieldDecl *LastFD = 0;
bool IsMsStruct = record->hasAttr<MsStructAttr>();
@@ -653,7 +656,7 @@ CollectRecordFields(const RecordDecl *record, llvm::DIFile tunit,
llvm::DIType fieldType
= createFieldType(name, type, field->getBitWidth(),
field->getLocation(), field->getAccess(),
- layout.getFieldOffset(fieldNo), tunit);
+ layout.getFieldOffset(fieldNo), tunit, RecordTy);
elements.push_back(fieldType);
}
@@ -961,7 +964,7 @@ CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile Unit,
unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
llvm::DIType VPTR
- = DBuilder.createMemberType(getVTableName(RD), Unit,
+ = DBuilder.createMemberType(Unit, getVTableName(RD), Unit,
0, Size, 0, 0, 0,
getOrCreateVTablePtrType(Unit));
EltTys.push_back(VPTR);
@@ -1049,7 +1052,7 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
}
}
- CollectRecordFields(RD, Unit, EltTys);
+ CollectRecordFields(RD, Unit, EltTys, FwdDecl);
llvm::DIArray TParamsArray;
if (CXXDecl) {
CollectCXXMemberFunctions(CXXDecl, Unit, EltTys, FwdDecl);
@@ -1380,13 +1383,13 @@ llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty,
// FIXME: This should probably be a function type instead.
ElementTypes[0] =
- DBuilder.createMemberType("ptr", U, 0,
+ DBuilder.createMemberType(U, "ptr", U, 0,
Info.first, Info.second, FieldOffset, 0,
PointerDiffDITy);
FieldOffset += Info.first;
ElementTypes[1] =
- DBuilder.createMemberType("ptr", U, 0,
+ DBuilder.createMemberType(U, "ptr", U, 0,
Info.first, Info.second, FieldOffset, 0,
PointerDiffDITy);
@@ -1587,7 +1590,7 @@ llvm::DIType CGDebugInfo::CreateMemberType(llvm::DIFile Unit, QualType FType,
llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
uint64_t FieldSize = CGM.getContext().getTypeSize(FType);
unsigned FieldAlign = CGM.getContext().getTypeAlign(FType);
- llvm::DIType Ty = DBuilder.createMemberType(Name, Unit, 0,
+ llvm::DIType Ty = DBuilder.createMemberType(Unit, Name, Unit, 0,
FieldSize, FieldAlign,
*Offset, 0, FieldTy);
*Offset += FieldSize;
@@ -1898,7 +1901,7 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD,
FieldAlign = CGM.getContext().toBits(Align);
*XOffset = FieldOffset;
- FieldTy = DBuilder.createMemberType(VD->getName(), Unit,
+ FieldTy = DBuilder.createMemberType(Unit, VD->getName(), Unit,
0, FieldSize, FieldAlign,
FieldOffset, 0, FieldTy);
EltTys.push_back(FieldTy);
@@ -2134,23 +2137,23 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
llvm::SmallVector<llvm::Value*, 16> fields;
fields.push_back(createFieldType("__isa", C.VoidPtrTy, 0, loc, AS_public,
blockLayout->getElementOffsetInBits(0),
- tunit));
+ tunit, tunit));
fields.push_back(createFieldType("__flags", C.IntTy, 0, loc, AS_public,
blockLayout->getElementOffsetInBits(1),
- tunit));
+ tunit, tunit));
fields.push_back(createFieldType("__reserved", C.IntTy, 0, loc, AS_public,
blockLayout->getElementOffsetInBits(2),
- tunit));
+ tunit, tunit));
fields.push_back(createFieldType("__FuncPtr", C.VoidPtrTy, 0, loc, AS_public,
blockLayout->getElementOffsetInBits(3),
- tunit));
+ tunit, tunit));
fields.push_back(createFieldType("__descriptor",
C.getPointerType(block.NeedsCopyDispose ?
C.getBlockDescriptorExtendedType() :
C.getBlockDescriptorType()),
0, loc, AS_public,
blockLayout->getElementOffsetInBits(4),
- tunit));
+ tunit, tunit));
// We want to sort the captures by offset, not because DWARF
// requires this, but because we're paranoid about debuggers.
@@ -2199,7 +2202,7 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
QualType type = method->getThisType(C);
fields.push_back(createFieldType("this", type, 0, loc, AS_public,
- offsetInBits, tunit));
+ offsetInBits, tunit, tunit));
continue;
}
@@ -2214,12 +2217,12 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
uint64_t xoffset;
fieldType = EmitTypeForVarWithBlocksAttr(variable, &xoffset);
fieldType = DBuilder.createPointerType(fieldType, ptrInfo.first);
- fieldType = DBuilder.createMemberType(name, tunit, line,
+ fieldType = DBuilder.createMemberType(tunit, name, tunit, line,
ptrInfo.first, ptrInfo.second,
offsetInBits, 0, fieldType);
} else {
fieldType = createFieldType(name, variable->getType(), 0,
- loc, AS_public, offsetInBits, tunit);
+ loc, AS_public, offsetInBits, tunit, tunit);
}
fields.push_back(fieldType);
}
View
6 lib/CodeGen/CGDebugInfo.h
@@ -139,9 +139,11 @@ class CGDebugInfo {
llvm::DIType createFieldType(llvm::StringRef name, QualType type,
Expr *bitWidth, SourceLocation loc,
AccessSpecifier AS, uint64_t offsetInBits,
- llvm::DIFile tunit);
+ llvm::DIFile tunit,
+ llvm::DIDescriptor scope);
void CollectRecordFields(const RecordDecl *Decl, llvm::DIFile F,
- llvm::SmallVectorImpl<llvm::Value *> &E);
+ llvm::SmallVectorImpl<llvm::Value *> &E,
+ llvm::DIType RecordTy);
void CollectVTableInfo(const CXXRecordDecl *Decl,
llvm::DIFile F,
View
28 lib/CodeGen/CGDecl.cpp
@@ -98,7 +98,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
QualType Ty = TD.getUnderlyingType();
if (Ty->isVariablyModifiedType())
- EmitVLASize(Ty);
+ EmitVariablyModifiedType(Ty);
}
}
}
@@ -258,7 +258,7 @@ void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D,
// even though that doesn't really make any sense.
// Make sure to evaluate VLA bounds now so that we have them for later.
if (D.getType()->isVariablyModifiedType())
- EmitVLASize(D.getType());
+ EmitVariablyModifiedType(D.getType());
// Local static block variables must be treated as globals as they may be
// referenced in their RHS initializer block-literal expresion.
@@ -699,6 +699,10 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
CharUnits alignment = getContext().getDeclAlign(&D);
emission.Alignment = alignment;
+ // If the type is variably-modified, emit all the VLA sizes for it.
+ if (Ty->isVariablyModifiedType())
+ EmitVariablyModifiedType(Ty);
+
llvm::Value *DeclPtr;
if (Ty->isConstantSizeType()) {
if (!Target.useGlobalsForAutomaticVariables()) {
@@ -778,10 +782,6 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
DeclPtr = CreateStaticVarDecl(D, Class,
llvm::GlobalValue::InternalLinkage);
}
-
- // FIXME: Can this happen?
- if (Ty->isVariablyModifiedType())
- EmitVLASize(Ty);
} else {
EnsureInsertPoint();
@@ -801,19 +801,17 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
EHStack.pushCleanup<CallStackRestore>(NormalCleanup, Stack);
}
- // Get the element type.
- const llvm::Type *LElemTy = ConvertTypeForMem(Ty);
- const llvm::Type *LElemPtrTy =
- LElemTy->getPointerTo(CGM.getContext().getTargetAddressSpace(Ty));
+ llvm::Value *elementCount;
+ QualType elementType;
+ llvm::tie(elementCount, elementType) = getVLASize(Ty);
- llvm::Value *VLASize = EmitVLASize(Ty);
+ const llvm::Type *llvmTy = ConvertTypeForMem(elementType);
// Allocate memory for the array.
- llvm::AllocaInst *VLA =
- Builder.CreateAlloca(llvm::Type::getInt8Ty(getLLVMContext()), VLASize, "vla");
- VLA->setAlignment(alignment.getQuantity());
+ llvm::AllocaInst *vla = Builder.CreateAlloca(llvmTy, elementCount, "vla");
+ vla->setAlignment(alignment.getQuantity());
- DeclPtr = Builder.CreateBitCast(VLA, LElemPtrTy, "tmp");
+ DeclPtr = vla;
}
llvm::Value *&DMEntry = LocalDeclMap[&D];
View
15 lib/CodeGen/CGExpr.cpp
@@ -1579,21 +1579,22 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) {
// size is a VLA or Objective-C interface.
llvm::Value *Address = 0;
unsigned ArrayAlignment = 0;
- if (const VariableArrayType *VAT =
+ if (const VariableArrayType *vla =
getContext().getAsVariableArrayType(E->getType())) {
- llvm::Value *VLASize = GetVLASize(VAT);
+ // The base must be a pointer, which is not an aggregate. Emit
+ // it. It needs to be emitted first in case it's what captures
+ // the VLA bounds.
+ Address = EmitScalarExpr(E->getBase());
- Idx = Builder.CreateMul(Idx, VLASize);
+ // The element count here is the total number of non-VLA elements.
+ llvm::Value *numElements = getVLASize(vla).first;
- // The base must be a pointer, which is not an aggregate. Emit it.
- llvm::Value *Base = EmitScalarExpr(E->getBase());
+ Idx = Builder.CreateMul(Idx, numElements);
- Address = EmitCastToVoidPtr(Base);
if (getContext().getLangOptions().isSignedOverflowDefined())
Address = Builder.CreateGEP(Address, Idx, "arrayidx");
else
Address = Builder.CreateInBoundsGEP(Address, Idx, "arrayidx");
- Address = Builder.CreateBitCast(Address, Base->getType());
} else if (const ObjCObjectType *OIT = E->getType()->getAs<ObjCObjectType>()){
// Indexing over an interface, as in "NSString *P; P[4];"
llvm::Value *InterfaceSize =
View
38 lib/CodeGen/CGExprScalar.cpp
@@ -269,14 +269,12 @@ class ScalarExprEmitter
Value *VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) {
return CGF.CGM.EmitNullConstant(E->getType());
}
- Value *VisitCastExpr(CastExpr *E) {
- // Make sure to evaluate VLA bounds now so that we have them for later.
+ Value *VisitExplicitCastExpr(ExplicitCastExpr *E) {
if (E->getType()->isVariablyModifiedType())
- CGF.EmitVLASize(E->getType());
-
- return EmitCastExpr(E);
+ CGF.EmitVariablyModifiedType(E->getType());
+ return VisitCastExpr(E);
}
- Value *EmitCastExpr(CastExpr *E);
+ Value *VisitCastExpr(CastExpr *E);
Value *VisitCallExpr(const CallExpr *E) {
if (E->getCallReturnType()->isReferenceType())
@@ -1001,7 +999,7 @@ static bool ShouldNullCheckClassCastValue(const CastExpr *CE) {
// VisitCastExpr - Emit code for an explicit or implicit cast. Implicit casts
// have to handle a more broad range of conversions than explicit casts, as they
// handle things like function to ptr-to-function decay etc.
-Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) {
+Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
Expr *E = CE->getSubExpr();
QualType DestTy = CE->getType();
CastKind Kind = CE->getCastKind();
@@ -1298,15 +1296,12 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
// VLA types don't have constant size.
if (type->isVariableArrayType()) {
- llvm::Value *vlaSize =
- CGF.GetVLASize(CGF.getContext().getAsVariableArrayType(type));
- value = CGF.EmitCastToVoidPtr(value);
- if (!isInc) vlaSize = Builder.CreateNSWNeg(vlaSize, "vla.negsize");
+ llvm::Value *numElts = CGF.getVLASize(type).first;
+ if (!isInc) numElts = Builder.CreateNSWNeg(numElts, "vla.negsize");
if (CGF.getContext().getLangOptions().isSignedOverflowDefined())
- value = Builder.CreateGEP(value, vlaSize, "vla.inc");
+ value = Builder.CreateGEP(value, numElts, "vla.inc");
else
- value = Builder.CreateInBoundsGEP(value, vlaSize, "vla.inc");
- value = Builder.CreateBitCast(value, input->getType());
+ value = Builder.CreateInBoundsGEP(value, numElts, "vla.inc");
// Arithmetic on function pointers (!) is just +-1.
} else if (type->isFunctionType()) {
@@ -1526,14 +1521,25 @@ ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
CGF.getContext().getAsVariableArrayType(TypeToSize)) {
if (E->isArgumentType()) {
// sizeof(type) - make sure to emit the VLA size.
- CGF.EmitVLASize(TypeToSize);
+ CGF.EmitVariablyModifiedType(TypeToSize);
} else {
// C99 6.5.3.4p2: If the argument is an expression of type
// VLA, it is evaluated.
CGF.EmitIgnoredExpr(E->getArgumentExpr());
}
- return CGF.GetVLASize(VAT);
+ QualType eltType;
+ llvm::Value *numElts;
+ llvm::tie(numElts, eltType) = CGF.getVLASize(VAT);
+
+ llvm::Value *size = numElts;
+
+ // Scale the number of non-VLA elements by the non-VLA element size.
+ CharUnits eltSize = CGF.getContext().getTypeSizeInChars(eltType);
+ if (!eltSize.isOne())
+ size = CGF.Builder.CreateNUWMul(CGF.CGM.getSize(eltSize), numElts);
+
+ return size;
}
}
View
25 lib/CodeGen/CGObjC.cpp
@@ -1894,9 +1894,10 @@ namespace {
// If it's a VLA, we have to load the stored size. Note that
// this is the size of the VLA in bytes, not its size in elements.
- llvm::Value *vlaSizeInBytes = 0;
+ llvm::Value *numVLAElements = 0;
if (isa<VariableArrayType>(arrayType)) {
- vlaSizeInBytes = CGF.GetVLASize(cast<VariableArrayType>(arrayType));
+ numVLAElements =
+ CGF.getVLASize(cast<VariableArrayType>(arrayType)).first;
// Walk into all VLAs. This doesn't require changes to addr,
// which has type T* where T is the first non-VLA element type.
@@ -1907,7 +1908,7 @@ namespace {
// If we only have VLA components, 'addr' requires no adjustment.
if (!arrayType) {
baseType = elementType;
- return divideVLASizeByBaseType(CGF, vlaSizeInBytes, baseType);
+ return numVLAElements;
}
} while (isa<VariableArrayType>(arrayType));
@@ -1947,22 +1948,20 @@ namespace {
assert(arrayType && "LLVM and Clang types are out-of-synch");
}
+ baseType = arrayType->getElementType();
+
// Create the actual GEP.
addr = CGF.Builder.CreateInBoundsGEP(addr, gepIndices.begin(),
gepIndices.end(), "array.begin");
- baseType = arrayType->getElementType();
-
- // If we had an VLA dimensions, we need to use the captured size.
- if (vlaSizeInBytes)
- return divideVLASizeByBaseType(CGF, vlaSizeInBytes, baseType);
+ llvm::Value *numElements
+ = llvm::ConstantInt::get(CGF.IntPtrTy, countFromCLAs);
- // Otherwise, use countFromCLAs.
- assert(countFromCLAs == (uint64_t)
- (Ctx.getTypeSizeInChars(origArrayType).getQuantity() /
- Ctx.getTypeSizeInChars(baseType).getQuantity()));
+ // If we had any VLA dimensions, factor them in.
+ if (numVLAElements)
+ numElements = CGF.Builder.CreateNUWMul(numVLAElements, numElements);
- return llvm::ConstantInt::get(CGF.IntPtrTy, countFromCLAs);
+ return numElements;
}
static llvm::Value *divideVLASizeByBaseType(CodeGenFunction &CGF,
View
161 lib/CodeGen/CodeGenFunction.cpp
@@ -343,7 +343,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
QualType Ty = (*i)->getType();
if (Ty->isVariablyModifiedType())
- EmitVLASize(Ty);
+ EmitVariablyModifiedType(Ty);
}
}
@@ -709,13 +709,20 @@ CodeGenFunction::EmitNullInitialization(llvm::Value *DestPtr, QualType Ty) {
if (const VariableArrayType *vlaType =
dyn_cast_or_null<VariableArrayType>(
getContext().getAsArrayType(Ty))) {
- SizeVal = GetVLASize(vlaType);
+ QualType eltType;
+ llvm::Value *numElts;
+ llvm::tie(numElts, eltType) = getVLASize(vlaType);
+
+ SizeVal = numElts;
+ CharUnits eltSize = getContext().getTypeSizeInChars(eltType);
+ if (!eltSize.isOne())
+ SizeVal = Builder.CreateNUWMul(SizeVal, CGM.getSize(eltSize));
vla = vlaType;
} else {
return;
}
} else {
- SizeVal = llvm::ConstantInt::get(IntPtrTy, Size.getQuantity());
+ SizeVal = CGM.getSize(Size);
vla = 0;
}
@@ -778,60 +785,120 @@ llvm::BasicBlock *CodeGenFunction::GetIndirectGotoBlock() {
return IndirectBranch->getParent();
}
-llvm::Value *CodeGenFunction::GetVLASize(const VariableArrayType *VAT) {
- llvm::Value *&SizeEntry = VLASizeMap[VAT->getSizeExpr()];
-
- assert(SizeEntry && "Did not emit size for type");
- return SizeEntry;
+std::pair<llvm::Value*, QualType>
+CodeGenFunction::getVLASize(QualType type) {
+ const VariableArrayType *vla = getContext().getAsVariableArrayType(type);
+ assert(vla && "type was not a variable array type!");
+ return getVLASize(vla);
}
-llvm::Value *CodeGenFunction::EmitVLASize(QualType Ty) {
- assert(Ty->isVariablyModifiedType() &&
- "Must pass variably modified type to EmitVLASizes!");
+std::pair<llvm::Value*, QualType>
+CodeGenFunction::getVLASize(const VariableArrayType *type) {
+ // The number of elements so far; always size_t.
+ llvm::Value *numElements = 0;
- EnsureInsertPoint();
+ QualType elementType;
+ do {
+ elementType = type->getElementType();
+ llvm::Value *vlaSize = VLASizeMap[type->getSizeExpr()];
+ assert(vlaSize && "no size for VLA!");
+ assert(vlaSize->getType() == SizeTy);
- if (const VariableArrayType *VAT = getContext().getAsVariableArrayType(Ty)) {
- // unknown size indication requires no size computation.
- if (!VAT->getSizeExpr())
- return 0;
- llvm::Value *&SizeEntry = VLASizeMap[VAT->getSizeExpr()];
+ if (!numElements) {
+ numElements = vlaSize;
+ } else {
+ // It's undefined behavior if this wraps around, so mark it that way.
+ numElements = Builder.CreateNUWMul(numElements, vlaSize);
+ }
+ } while ((type = getContext().getAsVariableArrayType(elementType)));
- if (!SizeEntry) {
- const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
+ return std::pair<llvm::Value*,QualType>(numElements, elementType);
+}
- // Get the element size;
- QualType ElemTy = VAT->getElementType();
- llvm::Value *ElemSize;
- if (ElemTy->isVariableArrayType())
- ElemSize = EmitVLASize(ElemTy);
- else
- ElemSize = llvm::ConstantInt::get(SizeTy,
- getContext().getTypeSizeInChars(ElemTy).getQuantity());
+void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
+ assert(type->isVariablyModifiedType() &&
+ "Must pass variably modified type to EmitVLASizes!");
- llvm::Value *NumElements = EmitScalarExpr(VAT->getSizeExpr());
- NumElements = Builder.CreateIntCast(NumElements, SizeTy, false, "tmp");
+ EnsureInsertPoint();
- SizeEntry = Builder.CreateMul(ElemSize, NumElements);
+ // We're going to walk down into the type and look for VLA
+ // expressions.
+ type = type.getCanonicalType();
+ do {
+ assert(type->isVariablyModifiedType());
+
+ const Type *ty = type.getTypePtr();
+ switch (ty->getTypeClass()) {
+#define TYPE(Class, Base)
+#define ABSTRACT_TYPE(Class, Base)
+#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+ llvm_unreachable("unexpected dependent or non-canonical type!");
+
+ // These types are never variably-modified.
+ case Type::Builtin:
+ case Type::Complex:
+ case Type::Vector:
+ case Type::ExtVector:
+ case Type::Record:
+ case Type::Enum:
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ case Type::ObjCObjectPointer:
+ llvm_unreachable("type class is never variably-modified!");
+
+ case Type::Pointer:
+ type = cast<PointerType>(ty)->getPointeeType();
+ break;
+
+ case Type::BlockPointer:
+ type = cast<BlockPointerType>(ty)->getPointeeType();
+ break;
+
+ case Type::LValueReference:
+ case Type::RValueReference:
+ type = cast<ReferenceType>(ty)->getPointeeType();
+ break;
+
+ case Type::MemberPointer:
+ type = cast<MemberPointerType>(ty)->getPointeeType();
+ break;
+
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ // Losing element qualification here is fine.
+ type = cast<ArrayType>(ty)->getElementType();
+ break;
+
+ case Type::VariableArray: {
+ // Losing element qualification here is fine.
+ const VariableArrayType *vat = cast<VariableArrayType>(ty);
+
+ // Unknown size indication requires no size computation.
+ // Otherwise, evaluate and record it.
+ if (const Expr *size = vat->getSizeExpr()) {
+ // It's possible that we might have emitted this already,
+ // e.g. with a typedef and a pointer to it.
+ llvm::Value *&entry = VLASizeMap[size];
+ if (!entry) {
+ // Always zexting here would be wrong if it weren't
+ // undefined behavior to have a negative bound.
+ entry = Builder.CreateIntCast(EmitScalarExpr(size), SizeTy,
+ /*signed*/ false);
+ }
+ }
+ type = vat->getElementType();
+ break;
}
- return SizeEntry;
- }
-
- if (const ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
- EmitVLASize(AT->getElementType());
- return 0;
- }
-
- if (const ParenType *PT = dyn_cast<ParenType>(Ty)) {
- EmitVLASize(PT->getInnerType());
- return 0;
- }
-
- const PointerType *PT = Ty->getAs<PointerType>();
- assert(PT && "unknown VM type!");
- EmitVLASize(PT->getPointeeType());
- return 0;
+ case Type::FunctionProto:
+ case Type::FunctionNoProto:
+ type = cast<FunctionType>(ty)->getResultType();
+ break;
+ }
+ } while (type->isVariablyModifiedType());
}
llvm::Value* CodeGenFunction::EmitVAListRef(const Expr* E) {
View
18 lib/CodeGen/CodeGenFunction.h
@@ -1526,16 +1526,18 @@ class CodeGenFunction : public CodeGenTypeCache {
// instruction in LLVM instead once it works well enough.
llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty);
- /// EmitVLASize - Generate code for any VLA size expressions that might occur
- /// in a variably modified type. If Ty is a VLA, will return the value that
- /// corresponds to the size in bytes of the VLA type. Will return 0 otherwise.
+ /// EmitVLASize - Capture all the sizes for the VLA expressions in
+ /// the given variably-modified type and store them in the VLASizeMap.
///
/// This function can be called with a null (unreachable) insert point.
- llvm::Value *EmitVLASize(QualType Ty);
-
- // GetVLASize - Returns an LLVM value that corresponds to the size in bytes
- // of a variable length array type.
- llvm::Value *GetVLASize(const VariableArrayType *);
+ void EmitVariablyModifiedType(QualType Ty);
+
+ /// getVLASize - Returns an LLVM value that corresponds to the size,
+ /// in non-variably-sized elements, of a variable length array type,
+ /// plus that largest non-variably-sized element type. Assumes that
+ /// the type has already been emitted with EmitVariablyModifiedType.
+ std::pair<llvm::Value*,QualType> getVLASize(const VariableArrayType *vla);
+ std::pair<llvm::Value*,QualType> getVLASize(QualType vla);
/// LoadCXXThis - Load the value of 'this'. This function is only valid while
/// generating code for an C++ member function.
View
4 lib/CodeGen/CodeGenModule.cpp
@@ -196,6 +196,10 @@ void CodeGenModule::ErrorUnsupported(const Decl *D, const char *Type,
getDiags().Report(Context.getFullLoc(D->getLocation()), DiagID) << Msg;
}
+llvm::ConstantInt *CodeGenModule::getSize(CharUnits size) {
+ return llvm::ConstantInt::get(SizeTy, size.getQuantity());
+}
+
void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV,
const NamedDecl *D) const {
// Internal definitions always have default visibility.
View
4 lib/CodeGen/CodeGenModule.h
@@ -33,6 +33,7 @@
namespace llvm {
class Module;
class Constant;
+ class ConstantInt;
class Function;
class GlobalValue;
class TargetData;
@@ -382,6 +383,9 @@ class CodeGenModule : public CodeGenTypeCache {
static void DecorateInstruction(llvm::Instruction *Inst,
llvm::MDNode *TBAAInfo);
+ /// getSize - Emit the given number of characters as a value of type size_t.
+ llvm::ConstantInt *getSize(CharUnits numChars);
+
/// setGlobalVisibility - Set the visibility for the given LLVM
/// GlobalValue.
void setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D) const;
View
3  test/CodeGen/debug-info-member.c
@@ -0,0 +1,3 @@
+// RUN: %clang_cc1 -emit-llvm -g < %s | grep DW_TAG_member | grep \!3
+
+struct A { int x; } a;
View
20 test/CodeGen/vla.c
@@ -88,13 +88,17 @@ int test2(int n)
// http://llvm.org/PR8567
// CHECK: define double @test_PR8567
double test_PR8567(int n, double (*p)[n][5]) {
- // CHECK: store [[vla_type:.*]] %p,
- // CHECK: load i32*
- // CHECK-NEXT: mul i32 40
- // CHECK-NEXT: [[byte_idx:%.*]] = mul i32 1
- // CHECK-NEXT: [[tmp_1:%.*]] = load [[vla_type]]*
- // CHECK-NEXT: [[tmp_2:%.*]] = bitcast [[vla_type]] [[tmp_1]] to i8*
- // CHECK-NEXT: [[idx:%.*]] = getelementptr inbounds i8* [[tmp_2]], i32 [[byte_idx]]
- // CHECK-NEXT: bitcast i8* [[idx]] to [[vla_type]]
+ // CHECK: [[NV:%.*]] = alloca i32, align 4
+ // CHECK-NEXT: [[PV:%.*]] = alloca [5 x double]*, align 4
+ // CHECK-NEXT: store
+ // CHECK-NEXT: store
+ // CHECK-NEXT: [[N:%.*]] = load i32* [[NV]], align 4
+ // CHECK-NEXT: [[P:%.*]] = load [5 x double]** [[PV]], align 4
+ // CHECK-NEXT: [[T0:%.*]] = mul i32 1, [[N]]
+ // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [5 x double]* [[P]], i32 [[T0]]
+ // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [5 x double]* [[T1]], i32 2
+ // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [5 x double]* [[T2]], i32 0, i32 3
+ // CHECK-NEXT: [[T4:%.*]] = load double* [[T3]]
+ // CHECK-NEXT: ret double [[T4]]
return p[1][2][3];
}
View
43 test/CodeGenCXX/vla.cpp
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -emit-llvm -o - | FileCheck %s
+
+// rdar://problem/9506377
+void test0(void *array, int n) {
+ // CHECK: define void @_Z5test0Pvi(
+ // CHECK: [[ARRAY:%.*]] = alloca i8*, align 8
+ // CHECK-NEXT: [[N:%.*]] = alloca i32, align 4
+ // CHECK-NEXT: [[REF:%.*]] = alloca i16*, align 8
+ // CHECK-NEXT: [[S:%.*]] = alloca i16, align 2
+ // CHECK-NEXT: store i8*
+ // CHECK-NEXT: store i32
+
+ // Capture the bounds.
+ // CHECK-NEXT: [[T0:%.*]] = load i32* [[N]], align 4
+ // CHECK-NEXT: [[DIM0:%.*]] = zext i32 [[T0]] to i64
+ // CHECK-NEXT: [[T0:%.*]] = load i32* [[N]], align 4
+ // CHECK-NEXT: [[T1:%.*]] = add nsw i32 [[T0]], 1
+ // CHECK-NEXT: [[DIM1:%.*]] = zext i32 [[T1]] to i64
+ typedef short array_t[n][n+1];
+
+ // CHECK-NEXT: [[T0:%.*]] = load i8** [[ARRAY]], align 8
+ // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to i16*
+ // CHECK-NEXT: store i16* [[T1]], i16** [[REF]], align 8
+ array_t &ref = *(array_t*) array;
+
+ // CHECK-NEXT: [[T0:%.*]] = load i16** [[REF]]
+ // CHECK-NEXT: [[T1:%.*]] = mul i64 1, [[DIM1]]
+ // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds i16* [[T0]], i64 [[T1]]
+ // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i16* [[T2]], i64 2
+ // CHECK-NEXT: store i16 3, i16* [[T3]]
+ ref[1][2] = 3;
+
+ // CHECK-NEXT: [[T0:%.*]] = load i16** [[REF]]
+ // CHECK-NEXT: [[T1:%.*]] = mul i64 4, [[DIM1]]
+ // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds i16* [[T0]], i64 [[T1]]
+ // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i16* [[T2]], i64 5
+ // CHECK-NEXT: [[T4:%.*]] = load i16* [[T3]]
+ // CHECK-NEXT: store i16 [[T4]], i16* [[S]], align 2
+ short s = ref[4][5];
+
+ // CHECK-NEXT: ret void
+}
+
View
37 test/CodeGenObjC/arc.m
@@ -487,23 +487,23 @@ void test20(unsigned n) {
id x[n];
// Capture the VLA size.
+ // CHECK-NEXT: [[T0:%.*]] = load i32* [[N]], align 4
+ // CHECK-NEXT: [[DIM:%.*]] = zext i32 [[T0]] to i64
+
+ // Save the stack pointer.
// CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.stacksave()
// CHECK-NEXT: store i8* [[T0]], i8** [[SAVED_STACK]]
- // CHECK-NEXT: [[T0:%.*]] = load i32* [[N]], align 4
- // CHECK-NEXT: [[T1:%.*]] = zext i32 [[T0]] to i64
- // CHECK-NEXT: [[VLA_SIZE:%.*]] = mul i64 8, [[T1]]
// Allocate the VLA.
- // CHECK-NEXT: [[T0:%.*]] = alloca i8, i64 [[VLA_SIZE]], align 16
- // CHECK-NEXT: [[VLA:%.*]] = bitcast i8* [[T0]] to i8**
+ // CHECK-NEXT: [[VLA:%.*]] = alloca i8*, i64 [[DIM]], align 16
// Zero-initialize.
// CHECK-NEXT: [[T0:%.*]] = bitcast i8** [[VLA]] to i8*
- // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 [[VLA_SIZE]], i32 8, i1 false)
+ // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[DIM]], 8
+ // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 [[T1]], i32 8, i1 false)
// Destroy.
- // CHECK-NEXT: [[VLA_COUNT:%.*]] = udiv i64 [[VLA_SIZE]], 8
- // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds i8** [[VLA]], i64 [[VLA_COUNT]]
+ // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds i8** [[VLA]], i64 [[DIM]]
// CHECK-NEXT: br label
// CHECK: [[CUR:%.*]] = phi i8**
@@ -529,25 +529,28 @@ void test21(unsigned n) {
id x[2][n][3];
// Capture the VLA size.
+ // CHECK-NEXT: [[T0:%.*]] = load i32* [[N]], align 4
+ // CHECK-NEXT: [[DIM:%.*]] = zext i32 [[T0]] to i64
+
// CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.stacksave()
// CHECK-NEXT: store i8* [[T0]], i8** [[SAVED_STACK]]
- // CHECK-NEXT: [[T0:%.*]] = load i32* [[N]], align 4
- // CHECK-NEXT: [[T1:%.*]] = zext i32 [[T0]] to i64
- // CHECK-NEXT: [[T2:%.*]] = mul i64 24, [[T1]]
- // CHECK-NEXT: [[VLA_SIZE:%.*]] = mul i64 [[T2]], 2
+
// Allocate the VLA.
- // CHECK-NEXT: [[T0:%.*]] = alloca i8, i64 [[VLA_SIZE]], align 16
- // CHECK-NEXT: [[VLA:%.*]] = bitcast i8* [[T0]] to [3 x i8*]*
+ // CHECK-NEXT: [[T0:%.*]] = mul nuw i64 2, [[DIM]]
+ // CHECK-NEXT: [[VLA:%.*]] = alloca [3 x i8*], i64 [[T0]], align 16
// Zero-initialize.
// CHECK-NEXT: [[T0:%.*]] = bitcast [3 x i8*]* [[VLA]] to i8*
- // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 [[VLA_SIZE]], i32 8, i1 false)
+ // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 2, [[DIM]]
+ // CHECK-NEXT: [[T2:%.*]] = mul nuw i64 [[T1]], 24
+ // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 [[T2]], i32 8, i1 false)
// Destroy.
+ // CHECK-NEXT: [[T0:%.*]] = mul nuw i64 2, [[DIM]]
// CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [3 x i8*]* [[VLA]], i32 0, i32 0
- // CHECK-NEXT: [[VLA_COUNT:%.*]] = udiv i64 [[VLA_SIZE]], 8
- // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds i8** [[BEGIN]], i64 [[VLA_COUNT]]
+ // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[T0]], 3
+ // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds i8** [[BEGIN]], i64 [[T1]]
// CHECK-NEXT: br label
// CHECK: [[CUR:%.*]] = phi i8**

No commit comments for this range

Something went wrong with that request. Please try again.