Change EmitVLASize to take a QualType that must be a variably modified type.

Emit the size even if the declared type is a variably modified type. This lets us handle

void f(int n) {
  int (*a)[n];
  
  printf("size: %d\n", sizeof(*a));
}

llvm-svn: 61285
This commit is contained in:
Anders Carlsson
2008-12-20 20:46:34 +00:00
parent e388a5bf44
commit 8a01b79274
3 changed files with 40 additions and 27 deletions

View File

@@ -160,9 +160,10 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
D.getStorageClass() == VarDecl::Register ? ".reg." : ".auto.";
DeclPtr = GenerateStaticBlockVarDecl(D, true, Class);
}
if (Ty->isVariablyModifiedType())
EmitVLASize(Ty);
} else {
const VariableArrayType *VAT = getContext().getAsVariableArrayType(Ty);
if (!StackSaveValues.back()) {
// Save the stack.
const llvm::Type *LTy = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
@@ -180,7 +181,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
const llvm::Type *LElemPtrTy =
llvm::PointerType::get(LElemTy, D.getType().getAddressSpace());
llvm::Value *VLASize = EmitVLASize(VAT);
llvm::Value *VLASize = EmitVLASize(Ty);
// Allocate memory for the array.
llvm::Value *VLA = Builder.CreateAlloca(llvm::Type::Int8Ty, VLASize, "vla");

View File

@@ -410,29 +410,40 @@ llvm::Value *CodeGenFunction::GetVLASize(const VariableArrayType *VAT)
return SizeEntry;
}
llvm::Value *CodeGenFunction::EmitVLASize(const VariableArrayType *VAT)
llvm::Value *CodeGenFunction::EmitVLASize(QualType Ty)
{
llvm::Value *&SizeEntry = VLASizeMap[VAT];
assert(!SizeEntry && "Must not emit the same VLA size more than once!");
// Get the element size;
llvm::Value *ElemSize;
assert(Ty->isVariablyModifiedType() &&
"Must pass variably modified type to EmitVLASizes!");
QualType ElemTy = VAT->getElementType();
if (const VariableArrayType *ElemVAT =
getContext().getAsVariableArrayType(ElemTy))
ElemSize = EmitVLASize(ElemVAT);
if (const VariableArrayType *VAT = getContext().getAsVariableArrayType(Ty)) {
llvm::Value *&SizeEntry = VLASizeMap[VAT];
assert(!SizeEntry && "Must not emit the same VLA size more than once!");
// Get the element size;
llvm::Value *ElemSize;
QualType ElemTy = VAT->getElementType();
if (ElemTy->isVariableArrayType())
ElemSize = EmitVLASize(ElemTy);
else {
// FIXME: We use Int32Ty here because the alloca instruction takes a
// 32-bit integer. What should we do about overflow?
ElemSize = llvm::ConstantInt::get(llvm::Type::Int32Ty,
getContext().getTypeSize(ElemTy) / 8);
}
llvm::Value *NumElements = EmitScalarExpr(VAT->getSizeExpr());
SizeEntry = Builder.CreateMul(ElemSize, NumElements);
return SizeEntry;
} else if (const PointerType *PT = Ty->getAsPointerType())
EmitVLASize(PT->getPointeeType());
else {
// FIXME: We use Int32Ty here because the alloca instruction takes a
// 32-bit integer. What should we do about overflow?
ElemSize = llvm::ConstantInt::get(llvm::Type::Int32Ty,
getContext().getTypeSize(ElemTy) / 8);
assert(0 && "unknown VM type!");
}
llvm::Value *NumElements = EmitScalarExpr(VAT->getSizeExpr());
SizeEntry = Builder.CreateMul(ElemSize, NumElements);
return SizeEntry;
return 0;
}

View File

@@ -350,9 +350,10 @@ public:
// instruction in LLVM instead once it works well enough.
llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty);
// EmitVLASize - Generate code for the VLA type. Returns an
// lLVM value that corresponds to the size in bytes of the
llvm::Value *EmitVLASize(const VariableArrayType *);
// 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.
llvm::Value *EmitVLASize(QualType Ty);
// GetVLASize - Returns an LLVM value that corresponds to the size in bytes
// of a variable length array type.