aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CGExpr.cpp38
-rw-r--r--lib/CodeGen/CGExprScalar.cpp7
-rw-r--r--lib/CodeGen/CodeGenFunction.h8
3 files changed, 49 insertions, 4 deletions
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index c5a89e032b..6773d0bbe8 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -208,6 +208,34 @@ unsigned CodeGenFunction::getAccessedFieldNo(unsigned Idx,
return cast<llvm::ConstantInt>(Elts->getOperand(Idx))->getZExtValue();
}
+void CodeGenFunction::EmitCheck(llvm::Value *Address, unsigned Size) {
+ if (!CatchUndefined)
+ return;
+
+ const llvm::IntegerType *Size_tTy
+ = llvm::IntegerType::get(VMContext, LLVMPointerWidth);
+ Address = Builder.CreateBitCast(Address, PtrToInt8Ty);
+
+ const llvm::Type *ResType[] = {
+ Size_tTy
+ };
+ llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::objectsize, ResType, 1);
+ const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
+ CGM.getTypes().ConvertType(CGM.getContext().IntTy));
+ // In time, people may want to control this and use a 1 here.
+ llvm::Value *Arg = llvm::ConstantInt::get(IntTy, 0);
+ llvm::Value *C = Builder.CreateCall2(F, Address, Arg);
+ llvm::BasicBlock *Cont = createBasicBlock();
+ llvm::BasicBlock *Check = createBasicBlock();
+ llvm::Value *NegativeOne = llvm::ConstantInt::get(Size_tTy, -1ULL);
+ Builder.CreateCondBr(Builder.CreateICmpEQ(C, NegativeOne), Cont, Check);
+
+ EmitBlock(Check);
+ Builder.CreateCondBr(Builder.CreateICmpUGE(C,
+ llvm::ConstantInt::get(Size_tTy, Size)),
+ Cont, getTrapBB());
+ EmitBlock(Cont);
+}
//===----------------------------------------------------------------------===//
// LValue Expression Emission
@@ -245,6 +273,13 @@ LValue CodeGenFunction::EmitUnsupportedLValue(const Expr *E,
MakeQualifiers(E->getType()));
}
+LValue CodeGenFunction::EmitCheckedLValue(const Expr *E) {
+ LValue LV = EmitLValue(E);
+ if (!isa<DeclRefExpr>(E) && !LV.isBitfield() && LV.isSimple())
+ EmitCheck(LV.getAddress(), getContext().getTypeSize(E->getType()) / 8);
+ return LV;
+}
+
/// EmitLValue - Emit code to compute a designator that specifies the location
/// of the expression.
///
@@ -1071,8 +1106,9 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) {
llvm::IntegerType::get(VMContext, LLVMPointerWidth),
IdxSigned, "idxprom");
+ // FIXME: As llvm implements the object size checking, this can come out.
if (CatchUndefined) {
- if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E->getBase())) {
+ if (const ImplicitCastExpr *ICE=dyn_cast<ImplicitCastExpr>(E->getBase())) {
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr())) {
if (ICE->getCastKind() == CastExpr::CK_ArrayToPointerDecay) {
if (const ConstantArrayType *CAT
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 2f31c051a7..07909faa75 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -69,6 +69,7 @@ public:
const llvm::Type *ConvertType(QualType T) { return CGF.ConvertType(T); }
LValue EmitLValue(const Expr *E) { return CGF.EmitLValue(E); }
+ LValue EmitCheckedLValue(const Expr *E) { return CGF.EmitCheckedLValue(E); }
Value *EmitLoadOfLValue(LValue LV, QualType T) {
return CGF.EmitLoadOfLValue(LV, T).getScalarVal();
@@ -78,7 +79,7 @@ public:
/// value l-value, this method emits the address of the l-value, then loads
/// and returns the result.
Value *EmitLoadOfLValue(const Expr *E) {
- return EmitLoadOfLValue(EmitLValue(E), E->getType());
+ return EmitLoadOfLValue(EmitCheckedLValue(E), E->getType());
}
/// EmitConversionToBool - Convert the specified expression value to a
@@ -1217,7 +1218,7 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E,
OpInfo.Ty = E->getComputationResultType();
OpInfo.E = E;
// Load/convert the LHS.
- LValue LHSLV = EmitLValue(E->getLHS());
+ LValue LHSLV = EmitCheckedLValue(E->getLHS());
OpInfo.LHS = EmitLoadOfLValue(LHSLV, LHSTy);
OpInfo.LHS = EmitScalarConversion(OpInfo.LHS, LHSTy,
E->getComputationLHSType());
@@ -1654,7 +1655,7 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) {
// __block variables need to have the rhs evaluated first, plus this should
// improve codegen just a little.
Value *RHS = Visit(E->getRHS());
- LValue LHS = EmitLValue(E->getLHS());
+ LValue LHS = EmitCheckedLValue(E->getLHS());
// Store the value into the LHS. Bit-fields are handled specially
// because the result is altered by the store, i.e., [C99 6.5.16p1]
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 12e636c897..4bacd16f92 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -807,6 +807,8 @@ public:
llvm::Value* EmitCXXTypeidExpr(const CXXTypeidExpr *E);
llvm::Value *EmitDynamicCast(llvm::Value *V, const CXXDynamicCastExpr *DCE);
+ void EmitCheck(llvm::Value *, unsigned Size);
+
//===--------------------------------------------------------------------===//
// Declaration Emission
//===--------------------------------------------------------------------===//
@@ -921,6 +923,12 @@ public:
///
LValue EmitLValue(const Expr *E);
+ /// EmitCheckedLValue - Same as EmitLValue but additionally we generate
+ /// checking code to guard against undefined behavior. This is only
+ /// suitable when we know that the address will be used to access the
+ /// object.
+ LValue EmitCheckedLValue(const Expr *E);
+
/// EmitLoadOfScalar - Load a scalar value from an address, taking
/// care to appropriately convert from the memory representation to
/// the LLVM value representation.