2007-08-24 10:22:53 +08:00
|
|
|
//===--- CGExprAgg.cpp - Emit LLVM Code from Aggregate Expressions --------===//
|
2007-08-11 04:13:28 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-30 03:59:25 +08:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2007-08-11 04:13:28 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This contains code to emit Aggregate Expr nodes as LLVM code.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "CodeGenFunction.h"
|
2007-08-11 08:04:45 +08:00
|
|
|
#include "CodeGenModule.h"
|
2008-08-11 13:00:27 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
|
|
|
#include "clang/AST/StmtVisitor.h"
|
2007-08-11 08:04:45 +08:00
|
|
|
#include "llvm/Constants.h"
|
|
|
|
#include "llvm/Function.h"
|
2007-10-27 01:44:44 +08:00
|
|
|
#include "llvm/GlobalVariable.h"
|
2007-08-21 12:25:47 +08:00
|
|
|
#include "llvm/Support/Compiler.h"
|
2008-04-05 02:42:16 +08:00
|
|
|
#include "llvm/Intrinsics.h"
|
2007-08-11 04:13:28 +08:00
|
|
|
using namespace clang;
|
|
|
|
using namespace CodeGen;
|
2007-08-11 08:04:45 +08:00
|
|
|
|
2007-08-21 12:25:47 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Aggregate Expression Emitter
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
class VISIBILITY_HIDDEN AggExprEmitter : public StmtVisitor<AggExprEmitter> {
|
|
|
|
CodeGenFunction &CGF;
|
2008-11-01 09:53:16 +08:00
|
|
|
CGBuilderTy &Builder;
|
2007-08-21 12:25:47 +08:00
|
|
|
llvm::Value *DestPtr;
|
|
|
|
bool VolatileDest;
|
|
|
|
public:
|
|
|
|
AggExprEmitter(CodeGenFunction &cgf, llvm::Value *destPtr, bool volatileDest)
|
2007-08-27 07:13:56 +08:00
|
|
|
: CGF(cgf), Builder(CGF.Builder),
|
|
|
|
DestPtr(destPtr), VolatileDest(volatileDest) {
|
2007-08-21 12:25:47 +08:00
|
|
|
}
|
|
|
|
|
2007-08-21 12:59:27 +08:00
|
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
// Utilities
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
|
2007-08-21 12:25:47 +08:00
|
|
|
/// EmitAggLoadOfLValue - Given an expression with aggregate type that
|
|
|
|
/// represents a value lvalue, this method emits the address of the lvalue,
|
|
|
|
/// then loads the result into DestPtr.
|
|
|
|
void EmitAggLoadOfLValue(const Expr *E);
|
|
|
|
|
2008-02-20 06:04:22 +08:00
|
|
|
void EmitNonConstInit(InitListExpr *E);
|
2008-05-20 01:51:16 +08:00
|
|
|
|
2007-08-21 12:59:27 +08:00
|
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
// Visitor Methods
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
|
2007-08-21 12:25:47 +08:00
|
|
|
void VisitStmt(Stmt *S) {
|
2008-08-16 08:56:44 +08:00
|
|
|
CGF.ErrorUnsupported(S, "aggregate expression");
|
2007-08-21 12:25:47 +08:00
|
|
|
}
|
|
|
|
void VisitParenExpr(ParenExpr *PE) { Visit(PE->getSubExpr()); }
|
|
|
|
|
|
|
|
// l-values.
|
2007-12-14 10:04:12 +08:00
|
|
|
void VisitDeclRefExpr(DeclRefExpr *DRE) { EmitAggLoadOfLValue(DRE); }
|
|
|
|
void VisitMemberExpr(MemberExpr *ME) { EmitAggLoadOfLValue(ME); }
|
|
|
|
void VisitUnaryDeref(UnaryOperator *E) { EmitAggLoadOfLValue(E); }
|
2007-12-23 11:11:58 +08:00
|
|
|
void VisitStringLiteral(StringLiteral *E) { EmitAggLoadOfLValue(E); }
|
2008-05-27 23:51:49 +08:00
|
|
|
void VisitCompoundLiteralExpr(CompoundLiteralExpr *E)
|
|
|
|
{ EmitAggLoadOfLValue(E); }
|
2007-12-14 10:04:12 +08:00
|
|
|
|
|
|
|
void VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
|
|
|
|
EmitAggLoadOfLValue(E);
|
|
|
|
}
|
2007-08-21 12:25:47 +08:00
|
|
|
|
|
|
|
// Operators.
|
|
|
|
// case Expr::UnaryOperatorClass:
|
|
|
|
// case Expr::CastExprClass:
|
2008-01-14 14:28:57 +08:00
|
|
|
void VisitImplicitCastExpr(ImplicitCastExpr *E);
|
2007-11-01 06:04:46 +08:00
|
|
|
void VisitCallExpr(const CallExpr *E);
|
2007-09-01 06:54:14 +08:00
|
|
|
void VisitStmtExpr(const StmtExpr *E);
|
2007-08-21 12:25:47 +08:00
|
|
|
void VisitBinaryOperator(const BinaryOperator *BO);
|
2007-08-21 12:43:17 +08:00
|
|
|
void VisitBinAssign(const BinaryOperator *E);
|
2008-01-31 13:38:29 +08:00
|
|
|
void VisitOverloadExpr(const OverloadExpr *E);
|
2008-05-20 15:56:31 +08:00
|
|
|
void VisitBinComma(const BinaryOperator *E);
|
2007-08-21 12:25:47 +08:00
|
|
|
|
2008-06-25 01:04:18 +08:00
|
|
|
void VisitObjCMessageExpr(ObjCMessageExpr *E);
|
2008-08-23 18:51:21 +08:00
|
|
|
void VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
|
|
|
|
EmitAggLoadOfLValue(E);
|
|
|
|
}
|
2008-08-27 14:57:25 +08:00
|
|
|
void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E);
|
2008-11-23 02:39:36 +08:00
|
|
|
void VisitObjCKVCRefExpr(ObjCKVCRefExpr *E);
|
2007-08-21 12:25:47 +08:00
|
|
|
|
|
|
|
void VisitConditionalOperator(const ConditionalOperator *CO);
|
2007-10-27 01:44:44 +08:00
|
|
|
void VisitInitListExpr(InitListExpr *E);
|
2008-04-08 12:40:51 +08:00
|
|
|
void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
|
|
|
|
Visit(DAE->getExpr());
|
|
|
|
}
|
2008-05-27 23:51:49 +08:00
|
|
|
void VisitVAArgExpr(VAArgExpr *E);
|
2008-04-05 02:42:16 +08:00
|
|
|
|
|
|
|
void EmitInitializationToLValue(Expr *E, LValue Address);
|
|
|
|
void EmitNullInitializationToLValue(LValue Address, QualType T);
|
2007-08-21 12:25:47 +08:00
|
|
|
// case Expr::ChooseExprClass:
|
2008-02-19 06:44:02 +08:00
|
|
|
|
2007-08-21 12:25:47 +08:00
|
|
|
};
|
|
|
|
} // end anonymous namespace.
|
|
|
|
|
2007-08-21 12:59:27 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Utilities
|
|
|
|
//===----------------------------------------------------------------------===//
|
2007-08-21 12:25:47 +08:00
|
|
|
|
2007-08-11 08:04:45 +08:00
|
|
|
/// EmitAggLoadOfLValue - Given an expression with aggregate type that
|
|
|
|
/// represents a value lvalue, this method emits the address of the lvalue,
|
|
|
|
/// then loads the result into DestPtr.
|
2007-08-21 12:25:47 +08:00
|
|
|
void AggExprEmitter::EmitAggLoadOfLValue(const Expr *E) {
|
|
|
|
LValue LV = CGF.EmitLValue(E);
|
2007-08-11 08:04:45 +08:00
|
|
|
assert(LV.isSimple() && "Can't have aggregate bitfield, vector, etc");
|
|
|
|
llvm::Value *SrcPtr = LV.getAddress();
|
|
|
|
|
|
|
|
// If the result is ignored, don't copy from the value.
|
|
|
|
if (DestPtr == 0)
|
|
|
|
// FIXME: If the source is volatile, we must read from it.
|
|
|
|
return;
|
|
|
|
|
2008-09-10 04:49:46 +08:00
|
|
|
CGF.EmitAggregateCopy(DestPtr, SrcPtr, E->getType());
|
2007-08-11 08:04:45 +08:00
|
|
|
}
|
|
|
|
|
2007-08-21 12:59:27 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Visitor Methods
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2008-07-27 06:37:01 +08:00
|
|
|
void AggExprEmitter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
|
2008-02-11 09:09:17 +08:00
|
|
|
assert(CGF.getContext().typesAreCompatible(
|
2008-07-27 06:37:01 +08:00
|
|
|
E->getSubExpr()->getType().getUnqualifiedType(),
|
|
|
|
E->getType().getUnqualifiedType()) &&
|
|
|
|
"Implicit cast types must be compatible");
|
2008-01-14 14:28:57 +08:00
|
|
|
Visit(E->getSubExpr());
|
|
|
|
}
|
|
|
|
|
2008-07-27 06:37:01 +08:00
|
|
|
void AggExprEmitter::VisitCallExpr(const CallExpr *E) {
|
2007-11-01 06:04:46 +08:00
|
|
|
RValue RV = CGF.EmitCallExpr(E);
|
|
|
|
assert(RV.isAggregate() && "Return value must be aggregate value!");
|
|
|
|
|
|
|
|
// If the result is ignored, don't copy from the value.
|
|
|
|
if (DestPtr == 0)
|
2008-01-31 13:38:29 +08:00
|
|
|
// FIXME: If the source is volatile, we must read from it.
|
|
|
|
return;
|
|
|
|
|
2008-09-10 04:49:46 +08:00
|
|
|
CGF.EmitAggregateCopy(DestPtr, RV.getAggregateAddr(), E->getType());
|
2008-01-31 13:38:29 +08:00
|
|
|
}
|
2008-07-27 06:37:01 +08:00
|
|
|
|
|
|
|
void AggExprEmitter::VisitObjCMessageExpr(ObjCMessageExpr *E) {
|
2008-08-23 11:46:30 +08:00
|
|
|
RValue RV = CGF.EmitObjCMessageExpr(E);
|
|
|
|
assert(RV.isAggregate() && "Return value must be aggregate value!");
|
2008-06-25 01:04:18 +08:00
|
|
|
|
|
|
|
// If the result is ignored, don't copy from the value.
|
|
|
|
if (DestPtr == 0)
|
2008-08-23 11:46:30 +08:00
|
|
|
// FIXME: If the source is volatile, we must read from it.
|
2008-06-25 01:04:18 +08:00
|
|
|
return;
|
|
|
|
|
2008-09-10 04:49:46 +08:00
|
|
|
CGF.EmitAggregateCopy(DestPtr, RV.getAggregateAddr(), E->getType());
|
2008-06-25 01:04:18 +08:00
|
|
|
}
|
2008-01-31 13:38:29 +08:00
|
|
|
|
2008-08-27 14:57:25 +08:00
|
|
|
void AggExprEmitter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
|
|
|
|
RValue RV = CGF.EmitObjCPropertyGet(E);
|
|
|
|
assert(RV.isAggregate() && "Return value must be aggregate value!");
|
2008-11-23 02:39:36 +08:00
|
|
|
|
|
|
|
// If the result is ignored, don't copy from the value.
|
|
|
|
if (DestPtr == 0)
|
|
|
|
// FIXME: If the source is volatile, we must read from it.
|
|
|
|
return;
|
|
|
|
|
|
|
|
CGF.EmitAggregateCopy(DestPtr, RV.getAggregateAddr(), E->getType());
|
|
|
|
}
|
|
|
|
|
|
|
|
void AggExprEmitter::VisitObjCKVCRefExpr(ObjCKVCRefExpr *E) {
|
|
|
|
RValue RV = CGF.EmitObjCPropertyGet(E);
|
|
|
|
assert(RV.isAggregate() && "Return value must be aggregate value!");
|
2008-08-27 14:57:25 +08:00
|
|
|
|
|
|
|
// If the result is ignored, don't copy from the value.
|
|
|
|
if (DestPtr == 0)
|
|
|
|
// FIXME: If the source is volatile, we must read from it.
|
|
|
|
return;
|
|
|
|
|
2008-09-10 04:49:46 +08:00
|
|
|
CGF.EmitAggregateCopy(DestPtr, RV.getAggregateAddr(), E->getType());
|
2008-08-27 14:57:25 +08:00
|
|
|
}
|
|
|
|
|
2008-07-27 06:37:01 +08:00
|
|
|
void AggExprEmitter::VisitOverloadExpr(const OverloadExpr *E) {
|
2008-01-31 13:38:29 +08:00
|
|
|
RValue RV = CGF.EmitCallExpr(E->getFn(), E->arg_begin(),
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
llvm-svn: 52378
2008-06-17 10:43:46 +08:00
|
|
|
E->arg_end(CGF.getContext()));
|
|
|
|
|
2008-01-31 13:38:29 +08:00
|
|
|
assert(RV.isAggregate() && "Return value must be aggregate value!");
|
|
|
|
|
|
|
|
// If the result is ignored, don't copy from the value.
|
|
|
|
if (DestPtr == 0)
|
2007-11-01 06:04:46 +08:00
|
|
|
// FIXME: If the source is volatile, we must read from it.
|
|
|
|
return;
|
|
|
|
|
2008-09-10 04:49:46 +08:00
|
|
|
CGF.EmitAggregateCopy(DestPtr, RV.getAggregateAddr(), E->getType());
|
2007-11-01 06:04:46 +08:00
|
|
|
}
|
|
|
|
|
2008-07-27 06:37:01 +08:00
|
|
|
void AggExprEmitter::VisitBinComma(const BinaryOperator *E) {
|
2008-05-20 15:56:31 +08:00
|
|
|
CGF.EmitAnyExpr(E->getLHS());
|
|
|
|
CGF.EmitAggExpr(E->getRHS(), DestPtr, false);
|
|
|
|
}
|
|
|
|
|
2007-09-01 06:54:14 +08:00
|
|
|
void AggExprEmitter::VisitStmtExpr(const StmtExpr *E) {
|
|
|
|
CGF.EmitCompoundStmt(*E->getSubStmt(), true, DestPtr, VolatileDest);
|
|
|
|
}
|
|
|
|
|
2007-08-21 12:25:47 +08:00
|
|
|
void AggExprEmitter::VisitBinaryOperator(const BinaryOperator *E) {
|
2008-08-16 08:56:44 +08:00
|
|
|
CGF.ErrorUnsupported(E, "aggregate binary expression");
|
2007-08-21 12:59:27 +08:00
|
|
|
}
|
|
|
|
|
2007-08-21 12:43:17 +08:00
|
|
|
void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) {
|
2008-02-11 09:09:17 +08:00
|
|
|
// For an assignment to work, the value on the right has
|
|
|
|
// to be compatible with the value on the left.
|
|
|
|
assert(CGF.getContext().typesAreCompatible(
|
|
|
|
E->getLHS()->getType().getUnqualifiedType(),
|
|
|
|
E->getRHS()->getType().getUnqualifiedType())
|
|
|
|
&& "Invalid assignment");
|
2007-08-21 12:25:47 +08:00
|
|
|
LValue LHS = CGF.EmitLValue(E->getLHS());
|
2007-08-11 08:04:45 +08:00
|
|
|
|
2008-08-30 13:35:15 +08:00
|
|
|
// We have to special case property setters, otherwise we must have
|
|
|
|
// a simple lvalue (no aggregates inside vectors, bitfields).
|
|
|
|
if (LHS.isPropertyRef()) {
|
|
|
|
// FIXME: Volatility?
|
|
|
|
llvm::Value *AggLoc = DestPtr;
|
|
|
|
if (!AggLoc)
|
|
|
|
AggLoc = CGF.CreateTempAlloca(CGF.ConvertType(E->getRHS()->getType()));
|
|
|
|
CGF.EmitAggExpr(E->getRHS(), AggLoc, false);
|
|
|
|
CGF.EmitObjCPropertySet(LHS.getPropertyRefExpr(),
|
|
|
|
RValue::getAggregate(AggLoc));
|
2008-11-23 06:30:21 +08:00
|
|
|
}
|
|
|
|
else if (LHS.isKVCRef()) {
|
|
|
|
// FIXME: Volatility?
|
|
|
|
llvm::Value *AggLoc = DestPtr;
|
|
|
|
if (!AggLoc)
|
|
|
|
AggLoc = CGF.CreateTempAlloca(CGF.ConvertType(E->getRHS()->getType()));
|
|
|
|
CGF.EmitAggExpr(E->getRHS(), AggLoc, false);
|
|
|
|
CGF.EmitObjCPropertySet(LHS.getKVCRefExpr(),
|
|
|
|
RValue::getAggregate(AggLoc));
|
2008-08-30 13:35:15 +08:00
|
|
|
} else {
|
|
|
|
// Codegen the RHS so that it stores directly into the LHS.
|
|
|
|
CGF.EmitAggExpr(E->getRHS(), LHS.getAddress(), false /*FIXME: VOLATILE LHS*/);
|
|
|
|
|
|
|
|
if (DestPtr == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// If the result of the assignment is used, copy the RHS there also.
|
2008-09-10 04:49:46 +08:00
|
|
|
CGF.EmitAggregateCopy(DestPtr, LHS.getAddress(), E->getType());
|
2008-08-30 13:35:15 +08:00
|
|
|
}
|
2007-08-11 08:04:45 +08:00
|
|
|
}
|
|
|
|
|
2007-08-21 12:25:47 +08:00
|
|
|
void AggExprEmitter::VisitConditionalOperator(const ConditionalOperator *E) {
|
2008-11-13 09:38:36 +08:00
|
|
|
llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.true");
|
|
|
|
llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false");
|
|
|
|
llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end");
|
2007-08-11 08:04:45 +08:00
|
|
|
|
2007-08-21 12:25:47 +08:00
|
|
|
llvm::Value *Cond = CGF.EvaluateExprAsBool(E->getCond());
|
2007-08-27 07:13:56 +08:00
|
|
|
Builder.CreateCondBr(Cond, LHSBlock, RHSBlock);
|
2007-08-11 08:04:45 +08:00
|
|
|
|
2007-08-21 12:25:47 +08:00
|
|
|
CGF.EmitBlock(LHSBlock);
|
2007-08-11 08:04:45 +08:00
|
|
|
|
|
|
|
// Handle the GNU extension for missing LHS.
|
|
|
|
assert(E->getLHS() && "Must have LHS for aggregate value");
|
|
|
|
|
2007-08-21 13:02:10 +08:00
|
|
|
Visit(E->getLHS());
|
2008-11-11 17:41:28 +08:00
|
|
|
CGF.EmitBranch(ContBlock);
|
2007-08-11 08:04:45 +08:00
|
|
|
|
2007-08-21 12:25:47 +08:00
|
|
|
CGF.EmitBlock(RHSBlock);
|
2007-08-11 08:04:45 +08:00
|
|
|
|
2007-08-21 13:02:10 +08:00
|
|
|
Visit(E->getRHS());
|
2008-11-11 17:41:28 +08:00
|
|
|
CGF.EmitBranch(ContBlock);
|
2007-08-11 08:04:45 +08:00
|
|
|
|
2007-08-21 12:25:47 +08:00
|
|
|
CGF.EmitBlock(ContBlock);
|
2007-08-11 08:04:45 +08:00
|
|
|
}
|
2007-08-21 12:59:27 +08:00
|
|
|
|
2008-05-27 23:51:49 +08:00
|
|
|
void AggExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {
|
|
|
|
llvm::Value *ArgValue = CGF.EmitLValue(VE->getSubExpr()).getAddress();
|
2008-11-04 13:30:00 +08:00
|
|
|
llvm::Value *ArgPtr = CGF.EmitVAArg(ArgValue, VE->getType());
|
|
|
|
|
|
|
|
if (!ArgPtr)
|
|
|
|
CGF.ErrorUnsupported(VE, "aggregate va_arg expression");
|
|
|
|
|
2008-05-27 23:51:49 +08:00
|
|
|
if (DestPtr)
|
2008-06-14 07:01:12 +08:00
|
|
|
// FIXME: volatility
|
2008-11-04 13:30:00 +08:00
|
|
|
CGF.EmitAggregateCopy(DestPtr, ArgPtr, VE->getType());
|
2008-05-27 23:51:49 +08:00
|
|
|
}
|
|
|
|
|
2008-02-20 06:04:22 +08:00
|
|
|
void AggExprEmitter::EmitNonConstInit(InitListExpr *E) {
|
2008-10-27 07:53:12 +08:00
|
|
|
if (E->hadDesignators()) {
|
|
|
|
CGF.ErrorUnsupported(E, "initializer list with designators");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-02-20 06:04:22 +08:00
|
|
|
const llvm::PointerType *APType =
|
|
|
|
cast<llvm::PointerType>(DestPtr->getType());
|
|
|
|
const llvm::Type *DestType = APType->getElementType();
|
2008-02-19 06:44:02 +08:00
|
|
|
|
2008-02-20 06:04:22 +08:00
|
|
|
if (const llvm::ArrayType *AType = dyn_cast<llvm::ArrayType>(DestType)) {
|
|
|
|
unsigned NumInitElements = E->getNumInits();
|
2008-02-19 06:44:02 +08:00
|
|
|
|
|
|
|
unsigned i;
|
|
|
|
for (i = 0; i != NumInitElements; ++i) {
|
2008-03-19 13:19:41 +08:00
|
|
|
llvm::Value *NextVal = Builder.CreateStructGEP(DestPtr, i, ".array");
|
2008-02-20 06:04:22 +08:00
|
|
|
Expr *Init = E->getInit(i);
|
|
|
|
if (isa<InitListExpr>(Init))
|
|
|
|
CGF.EmitAggExpr(Init, NextVal, VolatileDest);
|
|
|
|
else
|
2008-06-14 07:01:12 +08:00
|
|
|
// FIXME: volatility
|
2008-02-20 06:04:22 +08:00
|
|
|
Builder.CreateStore(CGF.EmitScalarExpr(Init), NextVal);
|
2008-02-19 06:44:02 +08:00
|
|
|
}
|
2007-10-27 01:44:44 +08:00
|
|
|
|
2008-02-19 06:44:02 +08:00
|
|
|
// Emit remaining default initializers
|
|
|
|
unsigned NumArrayElements = AType->getNumElements();
|
2008-02-20 06:04:22 +08:00
|
|
|
QualType QType = E->getInit(0)->getType();
|
|
|
|
const llvm::Type *EType = AType->getElementType();
|
2008-02-19 06:44:02 +08:00
|
|
|
for (/*Do not initialize i*/; i < NumArrayElements; ++i) {
|
2008-03-19 13:19:41 +08:00
|
|
|
llvm::Value *NextVal = Builder.CreateStructGEP(DestPtr, i, ".array");
|
2008-05-23 06:12:56 +08:00
|
|
|
if (EType->isSingleValueType())
|
2008-06-14 07:01:12 +08:00
|
|
|
// FIXME: volatility
|
2008-02-20 06:04:22 +08:00
|
|
|
Builder.CreateStore(llvm::Constant::getNullValue(EType), NextVal);
|
|
|
|
else
|
2008-09-10 04:49:46 +08:00
|
|
|
CGF.EmitAggregateClear(NextVal, QType);
|
2008-02-19 06:44:02 +08:00
|
|
|
}
|
2008-02-20 06:04:22 +08:00
|
|
|
} else
|
|
|
|
assert(false && "Invalid initializer");
|
2008-02-19 06:44:02 +08:00
|
|
|
}
|
2007-10-27 01:44:44 +08:00
|
|
|
|
2008-04-05 02:42:16 +08:00
|
|
|
void AggExprEmitter::EmitInitializationToLValue(Expr* E, LValue LV) {
|
|
|
|
// FIXME: Are initializers affected by volatile?
|
|
|
|
if (E->getType()->isComplexType()) {
|
|
|
|
CGF.EmitComplexExprIntoAddr(E, LV.getAddress(), false);
|
2008-05-12 23:06:05 +08:00
|
|
|
} else if (CGF.hasAggregateLLVMType(E->getType())) {
|
|
|
|
CGF.EmitAnyExpr(E, LV.getAddress(), false);
|
|
|
|
} else {
|
|
|
|
CGF.EmitStoreThroughLValue(CGF.EmitAnyExpr(E), LV, E->getType());
|
2008-04-05 02:42:16 +08:00
|
|
|
}
|
|
|
|
}
|
2008-02-19 06:44:02 +08:00
|
|
|
|
2008-04-05 02:42:16 +08:00
|
|
|
void AggExprEmitter::EmitNullInitializationToLValue(LValue LV, QualType T) {
|
|
|
|
if (!CGF.hasAggregateLLVMType(T)) {
|
|
|
|
// For non-aggregates, we can store zero
|
2008-08-06 13:32:55 +08:00
|
|
|
llvm::Value *Null = llvm::Constant::getNullValue(CGF.ConvertType(T));
|
|
|
|
CGF.EmitStoreThroughLValue(RValue::get(Null), LV, T);
|
2008-04-05 02:42:16 +08:00
|
|
|
} else {
|
|
|
|
// Otherwise, just memset the whole thing to zero. This is legal
|
|
|
|
// because in LLVM, all default initializers are guaranteed to have a
|
|
|
|
// bit pattern of all zeros.
|
|
|
|
// There's a potential optimization opportunity in combining
|
|
|
|
// memsets; that would be easy for arrays, but relatively
|
|
|
|
// difficult for structures with the current code.
|
2008-11-22 00:43:15 +08:00
|
|
|
const llvm::Type *SizeTy = llvm::Type::Int64Ty;
|
|
|
|
llvm::Value *MemSet = CGF.CGM.getIntrinsic(llvm::Intrinsic::memset,
|
|
|
|
&SizeTy, 1);
|
2008-04-05 02:42:16 +08:00
|
|
|
uint64_t Size = CGF.getContext().getTypeSize(T);
|
|
|
|
|
|
|
|
const llvm::Type *BP = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
|
|
|
|
llvm::Value* DestPtr = Builder.CreateBitCast(LV.getAddress(), BP, "tmp");
|
2008-05-06 08:56:42 +08:00
|
|
|
Builder.CreateCall4(MemSet, DestPtr,
|
|
|
|
llvm::ConstantInt::get(llvm::Type::Int8Ty, 0),
|
2008-11-22 00:43:15 +08:00
|
|
|
llvm::ConstantInt::get(SizeTy, Size/8),
|
2008-05-06 08:56:42 +08:00
|
|
|
llvm::ConstantInt::get(llvm::Type::Int32Ty, 0));
|
2008-04-05 02:42:16 +08:00
|
|
|
}
|
|
|
|
}
|
2008-02-19 06:44:02 +08:00
|
|
|
|
2008-04-05 02:42:16 +08:00
|
|
|
void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
|
2008-10-27 07:53:12 +08:00
|
|
|
if (E->hadDesignators()) {
|
|
|
|
CGF.ErrorUnsupported(E, "initializer list with designators");
|
|
|
|
return;
|
|
|
|
}
|
2008-11-30 10:11:09 +08:00
|
|
|
|
2008-12-02 09:17:45 +08:00
|
|
|
#if 0
|
|
|
|
// FIXME: Disabled while we figure out what to do about
|
|
|
|
// test/CodeGen/bitfield.c
|
|
|
|
//
|
2008-11-30 10:11:09 +08:00
|
|
|
// If we can, prefer a copy from a global; this is a lot less
|
|
|
|
// code for long globals, and it's easier for the current optimizers
|
|
|
|
// to analyze.
|
|
|
|
// FIXME: Should we really be doing this? Should we try to avoid
|
|
|
|
// cases where we emit a global with a lot of zeros? Should
|
|
|
|
// we try to avoid short globals?
|
|
|
|
if (E->isConstantExpr(CGF.getContext(), 0)) {
|
|
|
|
llvm::Constant* C = CGF.CGM.EmitConstantExpr(E, &CGF);
|
|
|
|
llvm::GlobalVariable* GV =
|
|
|
|
new llvm::GlobalVariable(C->getType(), true,
|
|
|
|
llvm::GlobalValue::InternalLinkage,
|
|
|
|
C, "", &CGF.CGM.getModule(), 0);
|
|
|
|
CGF.EmitAggregateCopy(DestPtr, GV, E->getType());
|
|
|
|
return;
|
|
|
|
}
|
2008-12-02 09:17:45 +08:00
|
|
|
#endif
|
2008-04-05 02:42:16 +08:00
|
|
|
// Handle initialization of an array.
|
|
|
|
if (E->getType()->isArrayType()) {
|
|
|
|
const llvm::PointerType *APType =
|
|
|
|
cast<llvm::PointerType>(DestPtr->getType());
|
|
|
|
const llvm::ArrayType *AType =
|
|
|
|
cast<llvm::ArrayType>(APType->getElementType());
|
|
|
|
|
|
|
|
uint64_t NumInitElements = E->getNumInits();
|
2008-05-20 01:51:16 +08:00
|
|
|
|
2008-07-27 06:37:01 +08:00
|
|
|
if (E->getNumInits() > 0) {
|
|
|
|
QualType T1 = E->getType();
|
|
|
|
QualType T2 = E->getInit(0)->getType();
|
|
|
|
if (CGF.getContext().getCanonicalType(T1).getUnqualifiedType() ==
|
|
|
|
CGF.getContext().getCanonicalType(T2).getUnqualifiedType()) {
|
|
|
|
EmitAggLoadOfLValue(E->getInit(0));
|
|
|
|
return;
|
|
|
|
}
|
2008-05-20 01:51:16 +08:00
|
|
|
}
|
|
|
|
|
2008-04-05 02:42:16 +08:00
|
|
|
uint64_t NumArrayElements = AType->getNumElements();
|
2008-08-04 15:31:14 +08:00
|
|
|
QualType ElementType = CGF.getContext().getCanonicalType(E->getType());
|
|
|
|
ElementType =CGF.getContext().getAsArrayType(ElementType)->getElementType();
|
2008-04-05 02:42:16 +08:00
|
|
|
|
2008-08-04 15:31:14 +08:00
|
|
|
unsigned CVRqualifier = ElementType.getCVRQualifiers();
|
2008-06-14 07:01:12 +08:00
|
|
|
|
2008-04-05 02:42:16 +08:00
|
|
|
for (uint64_t i = 0; i != NumArrayElements; ++i) {
|
|
|
|
llvm::Value *NextVal = Builder.CreateStructGEP(DestPtr, i, ".array");
|
|
|
|
if (i < NumInitElements)
|
2008-06-14 07:01:12 +08:00
|
|
|
EmitInitializationToLValue(E->getInit(i),
|
|
|
|
LValue::MakeAddr(NextVal, CVRqualifier));
|
2008-04-05 02:42:16 +08:00
|
|
|
else
|
2008-06-14 07:01:12 +08:00
|
|
|
EmitNullInitializationToLValue(LValue::MakeAddr(NextVal, CVRqualifier),
|
2008-04-05 02:42:16 +08:00
|
|
|
ElementType);
|
|
|
|
}
|
2008-02-19 06:44:02 +08:00
|
|
|
return;
|
2008-04-05 02:42:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
assert(E->getType()->isRecordType() && "Only support structs/unions here!");
|
|
|
|
|
|
|
|
// Do struct initialization; this code just sets each individual member
|
|
|
|
// to the approprate value. This makes bitfield support automatic;
|
|
|
|
// the disadvantage is that the generated code is more difficult for
|
|
|
|
// the optimizer, especially with bitfields.
|
|
|
|
unsigned NumInitElements = E->getNumInits();
|
|
|
|
RecordDecl *SD = E->getType()->getAsRecordType()->getDecl();
|
|
|
|
unsigned NumMembers = SD->getNumMembers() - SD->hasFlexibleArrayMember();
|
|
|
|
unsigned CurInitVal = 0;
|
|
|
|
bool isUnion = E->getType()->isUnionType();
|
|
|
|
|
|
|
|
// Here we iterate over the fields; this makes it simpler to both
|
|
|
|
// default-initialize fields and skip over unnamed fields.
|
|
|
|
for (unsigned CurFieldNo = 0; CurFieldNo != NumMembers; ++CurFieldNo) {
|
|
|
|
FieldDecl *CurField = SD->getMember(CurFieldNo);
|
|
|
|
if (CurField->getIdentifier() == 0) {
|
|
|
|
// Initializers can't initialize unnamed fields, e.g. "int : 20;"
|
|
|
|
continue;
|
|
|
|
}
|
2008-06-14 07:01:12 +08:00
|
|
|
// FIXME: volatility
|
|
|
|
LValue FieldLoc = CGF.EmitLValueForField(DestPtr, CurField, isUnion,0);
|
2008-04-05 02:42:16 +08:00
|
|
|
if (CurInitVal < NumInitElements) {
|
|
|
|
// Store the initializer into the field
|
|
|
|
// This will probably have to get a bit smarter when we support
|
|
|
|
// designators in initializers
|
|
|
|
EmitInitializationToLValue(E->getInit(CurInitVal++), FieldLoc);
|
|
|
|
} else {
|
|
|
|
// We're out of initalizers; default-initialize to null
|
|
|
|
EmitNullInitializationToLValue(FieldLoc, CurField->getType());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unions only initialize one field.
|
|
|
|
// (things can get weird with designators, but they aren't
|
|
|
|
// supported yet.)
|
|
|
|
if (E->getType()->isUnionType())
|
|
|
|
break;
|
2008-02-20 03:27:31 +08:00
|
|
|
}
|
2007-10-27 01:44:44 +08:00
|
|
|
}
|
|
|
|
|
2007-08-21 12:59:27 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Entry Points into this File
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// EmitAggExpr - Emit the computation of the specified expression of
|
|
|
|
/// aggregate type. The result is computed into DestPtr. Note that if
|
|
|
|
/// DestPtr is null, the value of the aggregate expression is not needed.
|
|
|
|
void CodeGenFunction::EmitAggExpr(const Expr *E, llvm::Value *DestPtr,
|
|
|
|
bool VolatileDest) {
|
|
|
|
assert(E && hasAggregateLLVMType(E->getType()) &&
|
|
|
|
"Invalid aggregate expression to emit");
|
|
|
|
|
|
|
|
AggExprEmitter(*this, DestPtr, VolatileDest).Visit(const_cast<Expr*>(E));
|
|
|
|
}
|
2008-09-10 04:49:46 +08:00
|
|
|
|
|
|
|
void CodeGenFunction::EmitAggregateClear(llvm::Value *DestPtr, QualType Ty) {
|
|
|
|
assert(!Ty->isAnyComplexType() && "Shouldn't happen for complex");
|
|
|
|
|
|
|
|
EmitMemSetToZero(DestPtr, Ty);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,
|
|
|
|
llvm::Value *SrcPtr, QualType Ty) {
|
|
|
|
assert(!Ty->isAnyComplexType() && "Shouldn't happen for complex");
|
|
|
|
|
|
|
|
// Aggregate assignment turns into llvm.memmove.
|
|
|
|
const llvm::Type *BP = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
|
|
|
|
if (DestPtr->getType() != BP)
|
|
|
|
DestPtr = Builder.CreateBitCast(DestPtr, BP, "tmp");
|
|
|
|
if (SrcPtr->getType() != BP)
|
|
|
|
SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp");
|
|
|
|
|
|
|
|
// Get size and alignment info for this aggregate.
|
|
|
|
std::pair<uint64_t, unsigned> TypeInfo = getContext().getTypeInfo(Ty);
|
|
|
|
|
|
|
|
// FIXME: Handle variable sized types.
|
|
|
|
const llvm::Type *IntPtr = llvm::IntegerType::get(LLVMPointerWidth);
|
|
|
|
|
|
|
|
Builder.CreateCall4(CGM.getMemMoveFn(),
|
|
|
|
DestPtr, SrcPtr,
|
|
|
|
// TypeInfo.first describes size in bits.
|
|
|
|
llvm::ConstantInt::get(IntPtr, TypeInfo.first/8),
|
|
|
|
llvm::ConstantInt::get(llvm::Type::Int32Ty,
|
|
|
|
TypeInfo.second/8));
|
|
|
|
}
|