Index: CodeGen/CodeGenFunction.cpp =================================================================== --- CodeGen/CodeGenFunction.cpp (revision 47175) +++ CodeGen/CodeGenFunction.cpp (working copy) @@ -42,6 +42,7 @@ const llvm::Type *CodeGenFunction::ConvertType(QualType T) { + EmitType(T); return CGM.getTypes().ConvertType(T); } Index: CodeGen/CGExprScalar.cpp =================================================================== --- CodeGen/CGExprScalar.cpp (revision 47175) +++ CodeGen/CGExprScalar.cpp (working copy) @@ -473,15 +473,15 @@ // will not true when we add support for VLAs. Value *V = EmitLValue(Op).getAddress(); // Bitfields can't be arrays. - assert(isa(V->getType()) && - isa(cast(V->getType()) - ->getElementType()) && - "Doesn't support VLAs yet!"); - llvm::Constant *Idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0); - - llvm::Value *Ops[] = {Idx0, Idx0}; - V = Builder.CreateGEP(V, Ops, Ops+2, "arraydecay"); - + if (!Op->getType()->isVariablyModifiedType()) { + // Note that we don't have to do anything here for variable + // array types; the LLVM type is already correct. + llvm::Constant *Idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0); + + llvm::Value *Ops[] = {Idx0, Idx0}; + V = Builder.CreateGEP(V, Ops, Ops+2, "arraydecay"); + } + // The resultant pointer type can be implicitly casted to other pointer // types as well, for example void*. const llvm::Type *DestPTy = ConvertType(E->getType()); @@ -599,6 +599,14 @@ /// an integer (RetType). Value *ScalarExprEmitter::EmitSizeAlignOf(QualType TypeToSize, QualType RetType,bool isSizeOf){ + if (isSizeOf && !TypeToSize->isConstantSizeType()) { + llvm::Value* Size = CGF.EmitType(TypeToSize); + QualType BaseType = TypeToSize->getAsVariableArrayType()->getBaseType(); + uint64_t baseSize = CGF.getContext().getTypeSize(BaseType, SourceLocation()); + Size = Builder.CreateMul(Size, llvm::ConstantInt::get(llvm::Type::Int32Ty, baseSize/8)); + return Size; + } + /// FIXME: This doesn't handle VLAs yet! std::pair Info = CGF.getContext().getTypeInfo(TypeToSize, SourceLocation()); Index: CodeGen/CodeGenFunction.h =================================================================== --- CodeGen/CodeGenFunction.h (revision 47175) +++ CodeGen/CodeGenFunction.h (working copy) @@ -261,6 +261,9 @@ /// LabelMap - This keeps track of the LLVM basic block for each C label. llvm::DenseMap LabelMap; + + // VLASizeMap - This keeps track of the associated size for each VLA type + llvm::DenseMap VLASizeMap; // BreakContinueStack - This keeps track of where break and continue // statements should jump to. @@ -476,6 +479,10 @@ bool DestIsVolatile); /// LoadComplexFromAddr - Load a complex number from the specified address. ComplexPairTy LoadComplexFromAddr(llvm::Value *SrcAddr, bool SrcIsVolatile); + + // Emit a type; this causes the sizes of variably modified types to be + // calculated in places like declarations and typedefs. + llvm::Value* EmitType(QualType Ty); }; } // end namespace CodeGen } // end namespace clang Index: CodeGen/CGDecl.cpp =================================================================== --- CodeGen/CGDecl.cpp (revision 47175) +++ CodeGen/CGDecl.cpp (working copy) @@ -34,6 +34,7 @@ case Decl::Class: // class X; case Decl::Enum: // enum X; // None of these decls require codegen support. + // FIXME: Except typedefs containing a VLA type! return; case Decl::BlockVar: @@ -95,7 +96,34 @@ Ty.getAddressSpace()); } - + +llvm::Value* CodeGenFunction::EmitType(QualType Ty) { + if (const PointerType* PT = Ty->getAsPointerType()) { + EmitType(PT->getPointeeType()); + } else if (const VariableArrayType* VAT = Ty->getAsVariableArrayType()) { + if (llvm::Value* SizeLocation = VLASizeMap[VAT->getSizeExpr()]) { + return Builder.CreateLoad(SizeLocation); + } else { + // FIXME: We need to sext (or zext?) smaller stuff + // FIXME: What to do about larger stuff? We can't alloca more than i32; + // also, we cause an implicit buffer overflow for large allocations! + llvm::Value* CurSize = EmitScalarExpr(VAT->getSizeExpr()); + if (llvm::Value* SubArraySize = EmitType(VAT->getElementType())) { + // We multiply here to figure out the total size; all the places + // that need this info want the total size anyway, and this + // prevents quadratic behavior for many-dimensional arrays. + CurSize = Builder.CreateMul(SubArraySize, CurSize); + } + llvm::Value *SizeLocation = CreateTempAlloca(llvm::Type::Int32Ty, + ".size"); + Builder.CreateStore(CurSize, SizeLocation, false); + VLASizeMap[VAT->getSizeExpr()] = SizeLocation; + return CurSize; + } + } + return 0; +} + /// EmitLocalBlockVarDecl - Emit code and set up an entry in LocalDeclMap for a /// variable declaration with auto, register, or no storage class specifier. /// These turn into simple stack objects. @@ -109,8 +137,11 @@ // TODO: Alignment DeclPtr = CreateTempAlloca(LTy, D.getName()); } else { - // TODO: Create a dynamic alloca. - assert(0 && "FIXME: Local VLAs not implemented yet"); + const llvm::Type *LTy = ConvertType(Ty); + const VariableArrayType* VAT = Ty->getAsVariableArrayType(); + assert(VAT && "Non-constant size type must be VAT here!"); + llvm::Value *Size = Builder.CreateLoad(VLASizeMap[VAT->getSizeExpr()]); + DeclPtr = Builder.CreateAlloca(LTy, Size, D.getName()); } llvm::Value *&DMEntry = LocalDeclMap[&D]; Index: CodeGen/CGExpr.cpp =================================================================== --- CodeGen/CGExpr.cpp (revision 47175) +++ CodeGen/CGExpr.cpp (working copy) @@ -438,8 +438,9 @@ // We know that the pointer points to a type of the correct size, unless the // size is a VLA. - if (!E->getType()->isConstantSizeType()) - assert(0 && "VLA idx not implemented"); + if (!E->getType()->isConstantSizeType()) { + Idx = Builder.CreateMul(Idx, Builder.CreateLoad(VLASizeMap[E->getType()->getAsVariableArrayType()->getSizeExpr()])); + } return LValue::MakeAddr(Builder.CreateGEP(Base, Idx, "arrayidx")); }