summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/CodeGen/CGExpr.cpp33
-rw-r--r--clang/CodeGen/CodeGenFunction.cpp1
-rw-r--r--clang/CodeGen/CodeGenFunction.h3
-rw-r--r--clang/include/clang/AST/Expr.h4
-rw-r--r--clang/include/clang/Basic/TargetInfo.h6
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) {
OpenPOWER on IntegriCloud