aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGExprConstant.cpp
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2012-01-04 23:13:47 +0000
committerEli Friedman <eli.friedman@gmail.com>2012-01-04 23:13:47 +0000
commit65639284118d54ddf2e51a05d2ffccda567fe246 (patch)
tree66b7a7ae4545db073ada0549d8af683c5c2b4231 /lib/CodeGen/CGExprConstant.cpp
parent08f7760eb2bc25ba3335169be83f7ba492860135 (diff)
Add an APValue representation for the difference between two address-of-label expressions. Add support to Evaluate and CGExprConstant for generating/handling them. Remove the special-case for such differences in Expr::isConstantInitializer.
With that done, remove a bunch of buggy code from CGExprConstant for handling scalar expressions which is no longer necessary. Fixes PR11705. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147561 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGExprConstant.cpp')
-rw-r--r--lib/CodeGen/CGExprConstant.cpp94
1 files changed, 26 insertions, 68 deletions
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index 1bd94295d3..2c151328c7 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -500,27 +500,6 @@ public:
return 0;
}
- llvm::Constant *VisitBinSub(BinaryOperator *E) {
- // This must be a pointer/pointer subtraction. This only happens for
- // address of label.
- if (!isa<AddrLabelExpr>(E->getLHS()->IgnoreParenNoopCasts(CGM.getContext())) ||
- !isa<AddrLabelExpr>(E->getRHS()->IgnoreParenNoopCasts(CGM.getContext())))
- return 0;
-
- llvm::Constant *LHS = CGM.EmitConstantExpr(E->getLHS(),
- E->getLHS()->getType(), CGF);
- llvm::Constant *RHS = CGM.EmitConstantExpr(E->getRHS(),
- E->getRHS()->getType(), CGF);
-
- llvm::Type *ResultType = ConvertType(E->getType());
- LHS = llvm::ConstantExpr::getPtrToInt(LHS, ResultType);
- RHS = llvm::ConstantExpr::getPtrToInt(RHS, ResultType);
-
- // No need to divide by element size, since addr of label is always void*,
- // which has size 1 in GNUish.
- return llvm::ConstantExpr::getSub(LHS, RHS);
- }
-
llvm::Constant *VisitCastExpr(CastExpr* E) {
Expr *subExpr = E->getSubExpr();
llvm::Constant *C = CGM.EmitConstantExpr(subExpr, subExpr->getType(), CGF);
@@ -570,13 +549,6 @@ public:
case CK_NoOp:
return C;
- case CK_CPointerToObjCPointerCast:
- case CK_BlockPointerToObjCPointerCast:
- case CK_AnyPointerToBlockPointerCast:
- case CK_BitCast:
- if (C->getType() == destType) return C;
- return llvm::ConstantExpr::getBitCast(C, destType);
-
case CK_Dependent: llvm_unreachable("saw dependent cast!");
// These will never be supported.
@@ -595,7 +567,12 @@ public:
case CK_ConstructorConversion:
return 0;
- // These should eventually be supported.
+ // These don't need to be handled here because Evaluate knows how to
+ // evaluate all scalar expressions which can be constant-evaluated.
+ case CK_CPointerToObjCPointerCast:
+ case CK_BlockPointerToObjCPointerCast:
+ case CK_AnyPointerToBlockPointerCast:
+ case CK_BitCast:
case CK_ArrayToPointerDecay:
case CK_FunctionToPointerDecay:
case CK_BaseToDerived:
@@ -613,53 +590,17 @@ public:
case CK_IntegralComplexToBoolean:
case CK_IntegralComplexCast:
case CK_IntegralComplexToFloatingComplex:
- return 0;
-
case CK_PointerToIntegral:
- if (!E->getType()->isBooleanType())
- return llvm::ConstantExpr::getPtrToInt(C, destType);
- // fallthrough
-
case CK_PointerToBoolean:
- return llvm::ConstantExpr::getICmp(llvm::CmpInst::ICMP_EQ, C,
- llvm::ConstantPointerNull::get(cast<llvm::PointerType>(C->getType())));
-
case CK_NullToPointer:
- return llvm::ConstantPointerNull::get(cast<llvm::PointerType>(destType));
-
- case CK_IntegralCast: {
- bool isSigned = subExpr->getType()->isSignedIntegerOrEnumerationType();
- return llvm::ConstantExpr::getIntegerCast(C, destType, isSigned);
- }
-
- case CK_IntegralToPointer: {
- bool isSigned = subExpr->getType()->isSignedIntegerOrEnumerationType();
- C = llvm::ConstantExpr::getIntegerCast(C, CGM.IntPtrTy, isSigned);
- return llvm::ConstantExpr::getIntToPtr(C, destType);
- }
-
+ case CK_IntegralCast:
+ case CK_IntegralToPointer:
case CK_IntegralToBoolean:
- return llvm::ConstantExpr::getICmp(llvm::CmpInst::ICMP_EQ, C,
- llvm::Constant::getNullValue(C->getType()));
-
case CK_IntegralToFloating:
- if (subExpr->getType()->isSignedIntegerOrEnumerationType())
- return llvm::ConstantExpr::getSIToFP(C, destType);
- else
- return llvm::ConstantExpr::getUIToFP(C, destType);
-
case CK_FloatingToIntegral:
- if (E->getType()->isSignedIntegerOrEnumerationType())
- return llvm::ConstantExpr::getFPToSI(C, destType);
- else
- return llvm::ConstantExpr::getFPToUI(C, destType);
-
case CK_FloatingToBoolean:
- return llvm::ConstantExpr::getFCmp(llvm::CmpInst::FCMP_UNE, C,
- llvm::Constant::getNullValue(C->getType()));
-
case CK_FloatingCast:
- return llvm::ConstantExpr::getFPCast(C, destType);
+ return 0;
}
llvm_unreachable("Invalid CastKind");
}
@@ -1081,6 +1022,23 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E,
}
return llvm::ConstantVector::get(Inits);
}
+ case APValue::AddrLabelDiff: {
+ const AddrLabelExpr *LHSExpr = Result.Val.getAddrLabelDiffLHS();
+ const AddrLabelExpr *RHSExpr = Result.Val.getAddrLabelDiffRHS();
+ llvm::Constant *LHS = EmitConstantExpr(LHSExpr, LHSExpr->getType(), CGF);
+ llvm::Constant *RHS = EmitConstantExpr(RHSExpr, RHSExpr->getType(), CGF);
+
+ // Compute difference
+ llvm::Type *ResultType = getTypes().ConvertType(E->getType());
+ LHS = llvm::ConstantExpr::getPtrToInt(LHS, IntPtrTy);
+ RHS = llvm::ConstantExpr::getPtrToInt(RHS, IntPtrTy);
+ llvm::Constant *AddrLabelDiff = llvm::ConstantExpr::getSub(LHS, RHS);
+
+ // LLVM os a bit sensitive about the exact format of the
+ // address-of-label difference; make sure to truncate after
+ // the subtraction.
+ return llvm::ConstantExpr::getTruncOrBitCast(AddrLabelDiff, ResultType);
+ }
case APValue::Array:
case APValue::Struct:
case APValue::Union: