diff --git a/expr.cpp b/expr.cpp index 27f45299..7ef2c0d0 100644 --- a/expr.cpp +++ b/expr.cpp @@ -3486,6 +3486,19 @@ FunctionCallExpr::GetValue(FunctionEmitContext *ctx) const { } +llvm::Value * +FunctionCallExpr::GetLValue(FunctionEmitContext *ctx) const { + if (GetLValueType() != NULL) { + return GetValue(ctx); + } + else { + // Only be a valid LValue type if the function + // returns a pointer or reference. + return NULL; + } +} + + const Type * FunctionCallExpr::GetType() const { const FunctionType *ftype = lGetFunctionType(func); @@ -3493,6 +3506,21 @@ FunctionCallExpr::GetType() const { } +const Type * +FunctionCallExpr::GetLValueType() const { + const FunctionType *ftype = lGetFunctionType(func); + if (ftype && (ftype->GetReturnType()->IsPointerType() + || ftype->GetReturnType()->IsReferenceType())) { + return ftype->GetReturnType(); + } + else { + // Only be a valid LValue type if the function + // returns a pointer or reference. + return NULL; + } +} + + Expr * FunctionCallExpr::Optimize() { if (func == NULL || args == NULL) @@ -4030,7 +4058,10 @@ IndexExpr::GetValue(FunctionEmitContext *ctx) const { } else { Symbol *baseSym = GetBaseSymbol(); - AssertPos(pos, baseSym != NULL); + if (dynamic_cast(baseExpr) == NULL) { + // Only check for non-function calls + AssertPos(pos, baseSym != NULL); + } mask = lMaskForSymbol(baseSym, ctx); } @@ -4269,8 +4300,16 @@ IndexExpr::GetLValueType() const { else { const PointerType *pt = CastType(baseExprLValueType->GetBaseType()); - AssertPos(pos, pt != NULL); - elementType = pt->GetBaseType(); + // This assertion seems overly strict. + // Why does it need to be a pointer to a pointer? + // AssertPos(pos, pt != NULL); + + if (pt != NULL) { + elementType = pt->GetBaseType(); + } + else { + elementType = baseExprLValueType->GetBaseType(); + } } // Are we indexing into a varying type, or are we indexing with a @@ -6789,6 +6828,17 @@ TypeCastExpr::GetValue(FunctionEmitContext *ctx) const { } +llvm::Value * +TypeCastExpr::GetLValue(FunctionEmitContext *ctx) const { + if (GetLValueType() != NULL) { + return GetValue(ctx); + } + else { + return NULL; + } +} + + const Type * TypeCastExpr::GetType() const { AssertPos(pos, type->HasUnboundVariability() == false); @@ -6796,6 +6846,18 @@ TypeCastExpr::GetType() const { } +const Type * +TypeCastExpr::GetLValueType() const { + AssertPos(pos, type->HasUnboundVariability() == false); + if (CastType(GetType()) != NULL) { + return type; + } + else { + return NULL; + } +} + + static const Type * lDeconstifyType(const Type *t) { const PointerType *pt = CastType(t); diff --git a/expr.h b/expr.h index 3b1a07e3..1ea44c4b 100644 --- a/expr.h +++ b/expr.h @@ -249,7 +249,9 @@ public: bool isLaunch = false, Expr *launchCountExpr = NULL); llvm::Value *GetValue(FunctionEmitContext *ctx) const; + llvm::Value *GetLValue(FunctionEmitContext *ctx) const; const Type *GetType() const; + const Type *GetLValueType() const; void Print() const; Expr *Optimize(); @@ -505,7 +507,9 @@ public: TypeCastExpr(const Type *t, Expr *e, SourcePos p); llvm::Value *GetValue(FunctionEmitContext *ctx) const; + llvm::Value *GetLValue(FunctionEmitContext *ctx) const; const Type *GetType() const; + const Type *GetLValueType() const; void Print() const; Expr *TypeCheck(); Expr *Optimize();