diff options
-rw-r--r-- | clang/CodeGen/CGExpr.cpp | 33 | ||||
-rw-r--r-- | clang/CodeGen/CodeGenFunction.cpp | 1 | ||||
-rw-r--r-- | clang/CodeGen/CodeGenFunction.h | 3 | ||||
-rw-r--r-- | clang/include/clang/AST/Expr.h | 4 | ||||
-rw-r--r-- | clang/include/clang/Basic/TargetInfo.h | 6 |
5 files changed, 46 insertions, 1 deletions
diff --git a/clang/CodeGen/CGExpr.cpp b/clang/CodeGen/CGExpr.cpp index 0af76beff61..3e23c9ad162 100644 --- a/clang/CodeGen/CGExpr.cpp +++ b/clang/CodeGen/CGExpr.cpp @@ -216,6 +216,8 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { case Expr::UnaryOperatorClass: return EmitUnaryOpLValue(cast<UnaryOperator>(E)); + case Expr::ArraySubscriptExprClass: + return EmitArraySubscriptExpr(cast<ArraySubscriptExpr>(E)); } } @@ -291,6 +293,36 @@ LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) { return LValue::getAddr(C); } +LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { + // The base and index must be pointers or integers, neither of which are + // aggregates. Emit them. + QualType BaseTy; + Value *Base =EmitExprWithUsualUnaryConversions(E->getBase(), BaseTy).getVal(); + QualType IdxTy; + Value *Idx = EmitExprWithUsualUnaryConversions(E->getIdx(), IdxTy).getVal(); + + // Usually the base is the pointer type, but sometimes it is the index. + // Canonicalize to have the pointer as the base. + if (isa<llvm::PointerType>(Idx->getType())) { + std::swap(Base, Idx); + std::swap(BaseTy, IdxTy); + } + + // The pointer is now the base. Extend or truncate the index type to 32 or + // 64-bits. + bool IdxSigned = IdxTy->isSignedIntegerType(); + unsigned IdxBitwidth = cast<IntegerType>(Idx->getType())->getBitWidth(); + if (IdxBitwidth != LLVMPointerWidth) + Idx = Builder.CreateIntCast(Idx, IntegerType::get(LLVMPointerWidth), + IdxSigned, "idxprom"); + + // 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"); + return LValue::getAddr(Builder.CreateGEP(Base, Idx, "arrayidx")); +} + //===--------------------------------------------------------------------===// // Expression Emission //===--------------------------------------------------------------------===// @@ -307,6 +339,7 @@ RValue CodeGenFunction::EmitExpr(const Expr *E) { // l-values. case Expr::DeclRefExprClass: // FIXME: EnumConstantDecl's are not lvalues. This is wrong for them. + case Expr::ArraySubscriptExprClass: return EmitLoadOfLValue(E); case Expr::StringLiteralClass: return RValue::get(EmitLValue(E).getAddress()); diff --git a/clang/CodeGen/CodeGenFunction.cpp b/clang/CodeGen/CodeGenFunction.cpp index 4239e1e58e7..817c5fca74e 100644 --- a/clang/CodeGen/CodeGenFunction.cpp +++ b/clang/CodeGen/CodeGenFunction.cpp @@ -139,6 +139,7 @@ const llvm::Type *CodeGenFunction::ConvertType(QualType T, SourceLocation Loc) { void CodeGenFunction::GenerateCode(const FunctionDecl *FD) { LLVMIntTy = ConvertType(getContext().IntTy, FD->getLocation()); + LLVMPointerWidth = Target.getPointerWidth(FD->getLocation()); const llvm::FunctionType *Ty = cast<llvm::FunctionType>(ConvertType(FD->getType(), FD->getLocation())); diff --git a/clang/CodeGen/CodeGenFunction.h b/clang/CodeGen/CodeGenFunction.h index ff6ac655acd..6a21b413ca5 100644 --- a/clang/CodeGen/CodeGenFunction.h +++ b/clang/CodeGen/CodeGenFunction.h @@ -45,6 +45,7 @@ namespace clang { class CastExpr; class UnaryOperator; class BinaryOperator; + class ArraySubscriptExpr; class BlockVarDecl; class EnumConstantDecl; @@ -127,6 +128,7 @@ class CodeGenFunction { llvm::Instruction *AllocaInsertPt; const llvm::Type *LLVMIntTy; + unsigned LLVMPointerWidth; /// LocalDeclMap - This keeps track of the LLVM allocas or globals for local C /// decls. @@ -227,6 +229,7 @@ public: LValue EmitDeclRefLValue(const DeclRefExpr *E); LValue EmitStringLiteralLValue(const StringLiteral *E); LValue EmitUnaryOpLValue(const UnaryOperator *E); + LValue EmitArraySubscriptExpr(const ArraySubscriptExpr *E); //===--------------------------------------------------------------------===// // Expression Emission diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 523d3ff58b7..a210c3ee009 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -324,8 +324,10 @@ public: Expr(ArraySubscriptExprClass, t), Base(base), Idx(idx), Loc(l) {} - Expr *getBase() const { return Base; } + Expr *getBase() { return Base; } + const Expr *getBase() const { return Base; } Expr *getIdx() { return Idx; } + const Expr *getIdx() const { return Idx; } SourceRange getSourceRange() const { return SourceRange(Base->getLocStart(), Loc); } diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 97b5b2f8350..e1394b4f611 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -104,6 +104,12 @@ public: return true; } + /// getPointerWidth - Return the width of pointers on this target, we + /// currently assume one pointer type. + unsigned getPointerWidth(SourceLocation Loc) { + return 32; // FIXME: implement correctly. + } + /// getBoolWidth - Return the size of '_Bool' and C++ 'bool' for this target, /// in bits. unsigned getBoolWidth(SourceLocation Loc) { |