diff options
-rw-r--r-- | CodeGen/CGExpr.cpp | 31 | ||||
-rw-r--r-- | test/CodeGen/struct.c | 39 |
2 files changed, 70 insertions, 0 deletions
diff --git a/CodeGen/CGExpr.cpp b/CodeGen/CGExpr.cpp index 7fbd1f17aa..c57b38d407 100644 --- a/CodeGen/CGExpr.cpp +++ b/CodeGen/CGExpr.cpp @@ -101,6 +101,7 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { return EmitArraySubscriptExpr(cast<ArraySubscriptExpr>(E)); case Expr::OCUVectorElementExprClass: return EmitOCUVectorElementExpr(cast<OCUVectorElementExpr>(E)); + case Expr::MemberExprClass: return EmitMemberExpr(cast<MemberExpr>(E)); } } @@ -381,6 +382,36 @@ EmitOCUVectorElementExpr(const OCUVectorElementExpr *E) { E->getEncodedElementAccess()); } +LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { + + // FIXME: Handle union members. + if (E->getBase()->getType()->getAsUnionType()) { + fprintf(stderr, "Unimplemented lvalue expr!\n"); + E->dump(getContext().SourceMgr); + llvm::Type *Ty = llvm::PointerType::get(ConvertType(E->getType())); + return LValue::MakeAddr(llvm::UndefValue::get(Ty)); + } + + LValue BaseLV = EmitLValue(E->getBase()); + llvm::Value *BaseValue = BaseLV.getAddress(); + + FieldDecl *Field = E->getMemberDecl(); + unsigned idx = CGM.getTypes().getLLVMFieldNo(Field); + llvm::Value *Idxs[2] = { llvm::Constant::getNullValue(llvm::Type::Int32Ty), + llvm::ConstantInt::get(llvm::Type::Int32Ty, idx) }; + if (E->isArrow()) { + QualType PTy = cast<PointerType>(E->getBase()->getType())->getPointeeType(); + BaseValue = Builder.CreateBitCast(BaseValue, + llvm::PointerType::get(ConvertType(PTy)), + "tmp"); + } + + return LValue::MakeAddr(Builder.CreateGEP(BaseValue,Idxs, Idxs + 2, "tmp")); + + // FIXME: If record field does not have one to one match with llvm::StructType + // field then apply appropriate masks to select only member field bits. +} + //===--------------------------------------------------------------------===// // Expression Emission //===--------------------------------------------------------------------===// diff --git a/test/CodeGen/struct.c b/test/CodeGen/struct.c new file mode 100644 index 0000000000..a3753d314a --- /dev/null +++ b/test/CodeGen/struct.c @@ -0,0 +1,39 @@ +// RUN: clang %s -emit-llvm + +struct { + int x; + int y; +} point; + +void fn1() { + point.x = 42; +} + +/* Nested member */ +struct { + struct { + int a; + int b; + } p1; +} point2; + +void fn2() { + point2.p1.a = 42; +} + +/* Indirect reference */ +typedef struct __sf { + unsigned char *c; + short flags; +} F; + +typedef struct __sf2 { + F *ff; +} F2; + +int fn3(F2 *c) { + if (c->ff->c >= 0) + return 1; + else + return 0; +} |