forked from OSchip/llvm-project
move scalar inc/dec codegen into ScalarExprEmitter instead
of being in CGF. No functionality change. llvm-svn: 106961
This commit is contained in:
parent
93e63a0218
commit
05dc78c096
|
@ -385,95 +385,6 @@ void CodeGenFunction::EmitCheck(llvm::Value *Address, unsigned Size) {
|
|||
}
|
||||
|
||||
|
||||
llvm::Value *CodeGenFunction::
|
||||
EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
|
||||
bool isInc, bool isPre) {
|
||||
QualType ValTy = E->getSubExpr()->getType();
|
||||
llvm::Value *InVal = EmitLoadOfLValue(LV, ValTy).getScalarVal();
|
||||
|
||||
int AmountVal = isInc ? 1 : -1;
|
||||
|
||||
if (ValTy->isPointerType() &&
|
||||
ValTy->getAs<PointerType>()->isVariableArrayType()) {
|
||||
// The amount of the addition/subtraction needs to account for the VLA size
|
||||
ErrorUnsupported(E, "VLA pointer inc/dec");
|
||||
}
|
||||
|
||||
llvm::Value *NextVal;
|
||||
if (const llvm::PointerType *PT =
|
||||
dyn_cast<llvm::PointerType>(InVal->getType())) {
|
||||
llvm::Constant *Inc =
|
||||
llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), AmountVal);
|
||||
if (!isa<llvm::FunctionType>(PT->getElementType())) {
|
||||
QualType PTEE = ValTy->getPointeeType();
|
||||
if (const ObjCObjectType *OIT = PTEE->getAs<ObjCObjectType>()) {
|
||||
// Handle interface types, which are not represented with a concrete
|
||||
// type.
|
||||
int size = getContext().getTypeSize(OIT) / 8;
|
||||
if (!isInc)
|
||||
size = -size;
|
||||
Inc = llvm::ConstantInt::get(Inc->getType(), size);
|
||||
const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(VMContext);
|
||||
InVal = Builder.CreateBitCast(InVal, i8Ty);
|
||||
NextVal = Builder.CreateGEP(InVal, Inc, "add.ptr");
|
||||
llvm::Value *lhs = LV.getAddress();
|
||||
lhs = Builder.CreateBitCast(lhs, llvm::PointerType::getUnqual(i8Ty));
|
||||
LV = LValue::MakeAddr(lhs, MakeQualifiers(ValTy));
|
||||
} else
|
||||
NextVal = Builder.CreateInBoundsGEP(InVal, Inc, "ptrincdec");
|
||||
} else {
|
||||
const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(VMContext);
|
||||
NextVal = Builder.CreateBitCast(InVal, i8Ty, "tmp");
|
||||
NextVal = Builder.CreateGEP(NextVal, Inc, "ptrincdec");
|
||||
NextVal = Builder.CreateBitCast(NextVal, InVal->getType());
|
||||
}
|
||||
} else if (InVal->getType()->isIntegerTy(1) && isInc) {
|
||||
// Bool++ is an interesting case, due to promotion rules, we get:
|
||||
// Bool++ -> Bool = Bool+1 -> Bool = (int)Bool+1 ->
|
||||
// Bool = ((int)Bool+1) != 0
|
||||
// An interesting aspect of this is that increment is always true.
|
||||
// Decrement does not have this property.
|
||||
NextVal = llvm::ConstantInt::getTrue(VMContext);
|
||||
} else if (isa<llvm::IntegerType>(InVal->getType())) {
|
||||
NextVal = llvm::ConstantInt::get(InVal->getType(), AmountVal);
|
||||
|
||||
// Signed integer overflow is undefined behavior.
|
||||
if (ValTy->isSignedIntegerType())
|
||||
NextVal = Builder.CreateNSWAdd(InVal, NextVal, isInc ? "inc" : "dec");
|
||||
else
|
||||
NextVal = Builder.CreateAdd(InVal, NextVal, isInc ? "inc" : "dec");
|
||||
} else {
|
||||
// Add the inc/dec to the real part.
|
||||
if (InVal->getType()->isFloatTy())
|
||||
NextVal =
|
||||
llvm::ConstantFP::get(VMContext,
|
||||
llvm::APFloat(static_cast<float>(AmountVal)));
|
||||
else if (InVal->getType()->isDoubleTy())
|
||||
NextVal =
|
||||
llvm::ConstantFP::get(VMContext,
|
||||
llvm::APFloat(static_cast<double>(AmountVal)));
|
||||
else {
|
||||
llvm::APFloat F(static_cast<float>(AmountVal));
|
||||
bool ignored;
|
||||
F.convert(Target.getLongDoubleFormat(), llvm::APFloat::rmTowardZero,
|
||||
&ignored);
|
||||
NextVal = llvm::ConstantFP::get(VMContext, F);
|
||||
}
|
||||
NextVal = Builder.CreateFAdd(InVal, NextVal, isInc ? "inc" : "dec");
|
||||
}
|
||||
|
||||
// Store the updated result through the lvalue.
|
||||
if (LV.isBitField())
|
||||
EmitStoreThroughBitfieldLValue(RValue::get(NextVal), LV, ValTy, &NextVal);
|
||||
else
|
||||
EmitStoreThroughLValue(RValue::get(NextVal), LV, ValTy);
|
||||
|
||||
// If this is a postinc, return the value read from memory, otherwise use the
|
||||
// updated value.
|
||||
return isPre ? NextVal : InVal;
|
||||
}
|
||||
|
||||
|
||||
CodeGenFunction::ComplexPairTy CodeGenFunction::
|
||||
EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV,
|
||||
bool isInc, bool isPre) {
|
||||
|
|
|
@ -213,22 +213,27 @@ public:
|
|||
Value *VisitBlockDeclRefExpr(const BlockDeclRefExpr *E);
|
||||
|
||||
// Unary Operators.
|
||||
Value *VisitPrePostIncDec(const UnaryOperator *E, bool isInc, bool isPre) {
|
||||
LValue LV = EmitLValue(E->getSubExpr());
|
||||
return CGF.EmitScalarPrePostIncDec(E, LV, isInc, isPre);
|
||||
}
|
||||
Value *VisitUnaryPostDec(const UnaryOperator *E) {
|
||||
return VisitPrePostIncDec(E, false, false);
|
||||
LValue LV = EmitLValue(E->getSubExpr());
|
||||
return EmitScalarPrePostIncDec(E, LV, false, false);
|
||||
}
|
||||
Value *VisitUnaryPostInc(const UnaryOperator *E) {
|
||||
return VisitPrePostIncDec(E, true, false);
|
||||
LValue LV = EmitLValue(E->getSubExpr());
|
||||
return EmitScalarPrePostIncDec(E, LV, true, false);
|
||||
}
|
||||
Value *VisitUnaryPreDec(const UnaryOperator *E) {
|
||||
return VisitPrePostIncDec(E, false, true);
|
||||
LValue LV = EmitLValue(E->getSubExpr());
|
||||
return EmitScalarPrePostIncDec(E, LV, false, true);
|
||||
}
|
||||
Value *VisitUnaryPreInc(const UnaryOperator *E) {
|
||||
return VisitPrePostIncDec(E, true, true);
|
||||
LValue LV = EmitLValue(E->getSubExpr());
|
||||
return EmitScalarPrePostIncDec(E, LV, true, true);
|
||||
}
|
||||
|
||||
llvm::Value *EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
|
||||
bool isInc, bool isPre);
|
||||
|
||||
|
||||
Value *VisitUnaryAddrOf(const UnaryOperator *E) {
|
||||
return EmitLValue(E->getSubExpr()).getAddress();
|
||||
}
|
||||
|
@ -1121,6 +1126,97 @@ Value *ScalarExprEmitter::VisitBlockDeclRefExpr(const BlockDeclRefExpr *E) {
|
|||
// Unary Operators
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
llvm::Value *ScalarExprEmitter::
|
||||
EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
|
||||
bool isInc, bool isPre) {
|
||||
|
||||
QualType ValTy = E->getSubExpr()->getType();
|
||||
llvm::Value *InVal = EmitLoadOfLValue(LV, ValTy);
|
||||
|
||||
int AmountVal = isInc ? 1 : -1;
|
||||
|
||||
if (ValTy->isPointerType() &&
|
||||
ValTy->getAs<PointerType>()->isVariableArrayType()) {
|
||||
// The amount of the addition/subtraction needs to account for the VLA size
|
||||
CGF.ErrorUnsupported(E, "VLA pointer inc/dec");
|
||||
}
|
||||
|
||||
llvm::Value *NextVal;
|
||||
if (const llvm::PointerType *PT =
|
||||
dyn_cast<llvm::PointerType>(InVal->getType())) {
|
||||
llvm::Constant *Inc =
|
||||
llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), AmountVal);
|
||||
if (!isa<llvm::FunctionType>(PT->getElementType())) {
|
||||
QualType PTEE = ValTy->getPointeeType();
|
||||
if (const ObjCObjectType *OIT = PTEE->getAs<ObjCObjectType>()) {
|
||||
// Handle interface types, which are not represented with a concrete
|
||||
// type.
|
||||
int size = CGF.getContext().getTypeSize(OIT) / 8;
|
||||
if (!isInc)
|
||||
size = -size;
|
||||
Inc = llvm::ConstantInt::get(Inc->getType(), size);
|
||||
const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(VMContext);
|
||||
InVal = Builder.CreateBitCast(InVal, i8Ty);
|
||||
NextVal = Builder.CreateGEP(InVal, Inc, "add.ptr");
|
||||
llvm::Value *lhs = LV.getAddress();
|
||||
lhs = Builder.CreateBitCast(lhs, llvm::PointerType::getUnqual(i8Ty));
|
||||
LV = LValue::MakeAddr(lhs, CGF.MakeQualifiers(ValTy));
|
||||
} else
|
||||
NextVal = Builder.CreateInBoundsGEP(InVal, Inc, "ptrincdec");
|
||||
} else {
|
||||
const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(VMContext);
|
||||
NextVal = Builder.CreateBitCast(InVal, i8Ty, "tmp");
|
||||
NextVal = Builder.CreateGEP(NextVal, Inc, "ptrincdec");
|
||||
NextVal = Builder.CreateBitCast(NextVal, InVal->getType());
|
||||
}
|
||||
} else if (InVal->getType()->isIntegerTy(1) && isInc) {
|
||||
// Bool++ is an interesting case, due to promotion rules, we get:
|
||||
// Bool++ -> Bool = Bool+1 -> Bool = (int)Bool+1 ->
|
||||
// Bool = ((int)Bool+1) != 0
|
||||
// An interesting aspect of this is that increment is always true.
|
||||
// Decrement does not have this property.
|
||||
NextVal = llvm::ConstantInt::getTrue(VMContext);
|
||||
} else if (isa<llvm::IntegerType>(InVal->getType())) {
|
||||
NextVal = llvm::ConstantInt::get(InVal->getType(), AmountVal);
|
||||
|
||||
// Signed integer overflow is undefined behavior.
|
||||
if (ValTy->isSignedIntegerType())
|
||||
NextVal = Builder.CreateNSWAdd(InVal, NextVal, isInc ? "inc" : "dec");
|
||||
else
|
||||
NextVal = Builder.CreateAdd(InVal, NextVal, isInc ? "inc" : "dec");
|
||||
} else {
|
||||
// Add the inc/dec to the real part.
|
||||
if (InVal->getType()->isFloatTy())
|
||||
NextVal =
|
||||
llvm::ConstantFP::get(VMContext,
|
||||
llvm::APFloat(static_cast<float>(AmountVal)));
|
||||
else if (InVal->getType()->isDoubleTy())
|
||||
NextVal =
|
||||
llvm::ConstantFP::get(VMContext,
|
||||
llvm::APFloat(static_cast<double>(AmountVal)));
|
||||
else {
|
||||
llvm::APFloat F(static_cast<float>(AmountVal));
|
||||
bool ignored;
|
||||
F.convert(CGF.Target.getLongDoubleFormat(), llvm::APFloat::rmTowardZero,
|
||||
&ignored);
|
||||
NextVal = llvm::ConstantFP::get(VMContext, F);
|
||||
}
|
||||
NextVal = Builder.CreateFAdd(InVal, NextVal, isInc ? "inc" : "dec");
|
||||
}
|
||||
|
||||
// Store the updated result through the lvalue.
|
||||
if (LV.isBitField())
|
||||
CGF.EmitStoreThroughBitfieldLValue(RValue::get(NextVal), LV, ValTy, &NextVal);
|
||||
else
|
||||
CGF.EmitStoreThroughLValue(RValue::get(NextVal), LV, ValTy);
|
||||
|
||||
// If this is a postinc, return the value read from memory, otherwise use the
|
||||
// updated value.
|
||||
return isPre ? NextVal : InVal;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Value *ScalarExprEmitter::VisitUnaryMinus(const UnaryOperator *E) {
|
||||
TestAndClearIgnoreResultAssign();
|
||||
// Emit unary minus with EmitSub so we handle overflow cases etc.
|
||||
|
@ -2047,6 +2143,13 @@ Value *CodeGenFunction::EmitComplexToScalarConversion(ComplexPairTy Src,
|
|||
DstTy);
|
||||
}
|
||||
|
||||
|
||||
llvm::Value *CodeGenFunction::
|
||||
EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
|
||||
bool isInc, bool isPre) {
|
||||
return ScalarExprEmitter(*this).EmitScalarPrePostIncDec(E, LV, isInc, isPre);
|
||||
}
|
||||
|
||||
LValue CodeGenFunction::EmitObjCIsaExpr(const ObjCIsaExpr *E) {
|
||||
llvm::Value *V;
|
||||
// object->isa or (*object).isa
|
||||
|
|
Loading…
Reference in New Issue