Implement array subscripts for non-vla types.
llvm-svn: 39622
This commit is contained in:
parent
de12ae2fd7
commit
d9d2fb1420
|
@ -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());
|
||||
|
|
|
@ -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()));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue