diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2009-02-27 06:44:11 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2009-02-27 06:44:11 +0000 |
commit | 35183aca180a2b9b2c637cd625a40a7e147d6a32 (patch) | |
tree | 64fb42bccd90eeec474659c00ef7ef9da8791e4a /lib/CodeGen/CGExprScalar.cpp | |
parent | 5de4092946373af0c8caca64a281e8080c9d8a34 (diff) |
Change the AST generated for offsetof a bit so that it looks like a
normal expression, and change Evaluate and IRGen to evaluate it like a
normal expression. This simplifies the code significantly, and fixes
PR3396.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65622 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGExprScalar.cpp')
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 42 |
1 files changed, 2 insertions, 40 deletions
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 020c21f5cb..c65c0816e2 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -755,47 +755,9 @@ Value *ScalarExprEmitter::VisitUnaryImag(const UnaryOperator *E) { Value *ScalarExprEmitter::VisitUnaryOffsetOf(const UnaryOperator *E) { - const Expr* SubExpr = E->getSubExpr(); + Value* ResultAsPtr = EmitLValue(E->getSubExpr()).getAddress(); const llvm::Type* ResultType = ConvertType(E->getType()); - llvm::Value* Result = llvm::Constant::getNullValue(ResultType); - while (!isa<CompoundLiteralExpr>(SubExpr)) { - if (const MemberExpr *ME = dyn_cast<MemberExpr>(SubExpr)) { - SubExpr = ME->getBase(); - QualType Ty = SubExpr->getType(); - - RecordDecl *RD = Ty->getAsRecordType()->getDecl(); - const ASTRecordLayout &RL = CGF.getContext().getASTRecordLayout(RD); - FieldDecl *FD = cast<FieldDecl>(ME->getMemberDecl()); - - // FIXME: This is linear time. And the fact that we're indexing - // into the layout by position in the record means that we're - // either stuck numbering the fields in the AST or we have to keep - // the linear search (yuck and yuck). - unsigned i = 0; - for (RecordDecl::field_iterator Field = RD->field_begin(), - FieldEnd = RD->field_end(); - Field != FieldEnd; (void)++Field, ++i) { - if (*Field == FD) - break; - } - - llvm::Value* Offset = - llvm::ConstantInt::get(ResultType, RL.getFieldOffset(i) / 8); - Result = Builder.CreateAdd(Result, Offset); - } else if (const ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(SubExpr)) { - SubExpr = ASE->getBase(); - int64_t size = CGF.getContext().getTypeSize(ASE->getType()) / 8; - llvm::Value* ElemSize = llvm::ConstantInt::get(ResultType, size); - llvm::Value* ElemIndex = CGF.EmitScalarExpr(ASE->getIdx()); - bool IndexSigned = ASE->getIdx()->getType()->isSignedIntegerType(); - ElemIndex = Builder.CreateIntCast(ElemIndex, ResultType, IndexSigned); - llvm::Value* Offset = Builder.CreateMul(ElemSize, ElemIndex); - Result = Builder.CreateAdd(Result, Offset); - } else { - assert(0 && "This should be impossible!"); - } - } - return Result; + return Builder.CreatePtrToInt(ResultAsPtr, ResultType, "offsetof"); } //===----------------------------------------------------------------------===// |