Skip to content

Commit 295d298

Browse files
committed
+ modify runtime check insertion for bounds cast operation (checkedc#256)
+ dynamic_bounds_cast operation SHOULD always succeed if runtime value of subexpression of cast is NULL(0) it finally emits dynamic_check(E == NULL || (lb <= castlb && castub <= ub)) it checks if subexpression value is NULL if subexpression value is not NULL, then it emits range bounds check code Otherwise(E == NULL), it skips range bounds check range bounds check is generated only if E is not NULL generated code is as follows: if (E == NULL) { success_block: } else { fallthrough_block: if (lb <= castlb && castub <= ub) { success_block: } else { fail_block: trap(); llvm_unreachable(); } } To check this code, we have checked generated llvm IR code for test code & modified test code
1 parent 6146ff4 commit 295d298

File tree

3 files changed

+42
-58
lines changed

3 files changed

+42
-58
lines changed

include/clang/AST/Expr.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2798,8 +2798,9 @@ class BoundsExpr : public Expr {
27982798
/// classes).
27992799
class CastExpr : public Expr {
28002800
private:
2801-
// CASTBOUNDS - for expanded bounds of cast expression
2802-
// SUBEXPRBOUNDS - for bounds of subexpression
2801+
// BOUNDS - declared bounds of the result of the cast expression
2802+
// CASTBOUNDS - inferred bounds of cast expression
2803+
// SUBEXPRBOUNDS - inferred bounds of subexpression
28032804
enum { OP, BOUNDS, CASTBOUNDS, SUBEXPRBOUNDS, END_EXPR = 4 };
28042805
Stmt* SubExprs[END_EXPR];
28052806

lib/CodeGen/CGDynamicCheck.cpp

Lines changed: 39 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,36 @@ void CodeGenFunction::EmitDynamicBoundsCheck(const Address BaseAddr,
141141

142142
++NumDynamicChecksRange;
143143

144+
// Dynamic_check(Base == NULL || (Lower <= CastLower && CastUpper <= Upper))
145+
// Emit code blocks as follows:
146+
// if (Base == NULL) {...}
147+
// else {
148+
// if (Lower <= CastLower && CastUpper <= Upper) {...}
149+
// else { trap(); llvm_unreachable(); }
150+
// }
151+
152+
Value *Cond1 =
153+
Builder.CreateIsNull(BaseAddr.getPointer(), "_Dynamic_check.null");
154+
155+
// Constant Folding:
156+
// If we have generated a constant condition, and the condition is true,
157+
// then the check will always pass and we can elide it.
158+
if (const ConstantInt *ConditionConstant = dyn_cast<ConstantInt>(Cond1)) {
159+
if (ConditionConstant->isOne()) {
160+
++NumDynamicChecksElided;
161+
return;
162+
}
163+
}
164+
165+
++NumDynamicChecksInserted;
166+
167+
BasicBlock *Begin, *DyCkSuccess, *DyCkFail, *DyCkFallThrough;
168+
Begin = Builder.GetInsertBlock();
169+
DyCkSuccess = createBasicBlock("_Dynamic_check.succeeded");
170+
DyCkFallThrough = createBasicBlock("_Dynamic_check.fallthrough", this->CurFn);
171+
DyCkFail = createBasicBlock("_Dynamic_check.failed", this->CurFn);
172+
173+
Builder.SetInsertPoint(DyCkFallThrough);
144174
// SubRange - bounds(lb, ub) vs CastRange - bounds(castlb, castub)
145175
// Dynamic_check(lb <= castlb && castub <= ub)
146176

@@ -169,38 +199,8 @@ void CodeGenFunction::EmitDynamicBoundsCheck(const Address BaseAddr,
169199
Value *UpperChk =
170200
Builder.CreateICmpULE(CastUpperInt, UpperInt, "_Dynamic_check.upper_cmp");
171201

172-
// if expression E is NULL, skip dynamic_check
173-
// Dynamic_check(E == NULL || (lb <= castlb && castub <= ub))
174-
// if (cond1) {...}
175-
// else {
176-
// if (cond2) {...}
177-
// else { trap(); llvm_unreachable(); }
178-
// }
179-
EmitDynamicCheckBlocks(
180-
Builder.CreateIsNull(BaseAddr.getPointer(), "_Dynamic_check.null"),
181-
Builder.CreateAnd(LowerChk, UpperChk, "_Dynamic_check.range"));
182-
}
183-
184-
void CodeGenFunction::EmitDynamicCheckBlocks(Value *Condition) {
185-
assert(Condition->getType()->isIntegerTy(1) &&
186-
"May only dynamic check boolean conditions");
187-
188-
// Constant Folding:
189-
// If we have generated a constant condition, and the condition is true,
190-
// then the check will always pass and we can elide it.
191-
if (const ConstantInt *ConditionConstant = dyn_cast<ConstantInt>(Condition)) {
192-
if (ConditionConstant->isOne()) {
193-
++NumDynamicChecksElided;
194-
return;
195-
}
196-
}
197-
198-
++NumDynamicChecksInserted;
199-
200-
BasicBlock *Begin, *DyCkSuccess, *DyCkFail;
201-
Begin = Builder.GetInsertBlock();
202-
DyCkSuccess = createBasicBlock("_Dynamic_check.succeeded");
203-
DyCkFail = createBasicBlock("_Dynamic_check.failed", this->CurFn);
202+
Value *Cond2 = Builder.CreateAnd(LowerChk, UpperChk, "_Dynamic_check.range");
203+
Builder.CreateCondBr(Cond2, DyCkSuccess, DyCkFail);
204204

205205
Builder.SetInsertPoint(DyCkFail);
206206
CallInst *TrapCall = Builder.CreateCall(CGM.getIntrinsic(Intrinsic::trap));
@@ -209,22 +209,21 @@ void CodeGenFunction::EmitDynamicCheckBlocks(Value *Condition) {
209209
Builder.CreateUnreachable();
210210

211211
Builder.SetInsertPoint(Begin);
212-
Builder.CreateCondBr(Condition, DyCkSuccess, DyCkFail);
212+
Builder.CreateCondBr(Cond1, DyCkSuccess, DyCkFallThrough);
213213
// This ensures the success block comes directly after the branch
214214
EmitBlock(DyCkSuccess);
215215

216216
Builder.SetInsertPoint(DyCkSuccess);
217217
}
218218

219-
// emit code for dynamic_check(cond1 || cond2)
220-
void CodeGenFunction::EmitDynamicCheckBlocks(Value *Cond1, Value *Cond2) {
221-
assert(Cond1->getType()->isIntegerTy(1) &&
219+
void CodeGenFunction::EmitDynamicCheckBlocks(Value *Condition) {
220+
assert(Condition->getType()->isIntegerTy(1) &&
222221
"May only dynamic check boolean conditions");
223222

224223
// Constant Folding:
225224
// If we have generated a constant condition, and the condition is true,
226225
// then the check will always pass and we can elide it.
227-
if (const ConstantInt *ConditionConstant = dyn_cast<ConstantInt>(Cond1)) {
226+
if (const ConstantInt *ConditionConstant = dyn_cast<ConstantInt>(Condition)) {
228227
if (ConditionConstant->isOne()) {
229228
++NumDynamicChecksElided;
230229
return;
@@ -233,36 +232,22 @@ void CodeGenFunction::EmitDynamicCheckBlocks(Value *Cond1, Value *Cond2) {
233232

234233
++NumDynamicChecksInserted;
235234

236-
// if (cond1) {...}
237-
// else {
238-
// if (cond2) {...}
239-
// else { trap(); llvm_unreachable(); }
240-
// }
241-
242-
BasicBlock *Begin, *DyCkSuccess, *DyCkFail, *DyCkFallThrough;
235+
BasicBlock *Begin, *DyCkSuccess, *DyCkFail;
243236
Begin = Builder.GetInsertBlock();
244237
DyCkSuccess = createBasicBlock("_Dynamic_check.succeeded");
245-
DyCkFallThrough = createBasicBlock("_Dynamic_check.fallthrough", this->CurFn);
246238
DyCkFail = createBasicBlock("_Dynamic_check.failed", this->CurFn);
247239

248-
// if (cond1) Success
249-
// else { FallThrough
250-
// if (cond2) Success
251-
// else { Fail, trap; llvm_unreachable; }
252-
// }
253-
Builder.SetInsertPoint(DyCkFallThrough);
254-
Builder.CreateCondBr(Cond2, DyCkSuccess, DyCkFail);
255-
256240
Builder.SetInsertPoint(DyCkFail);
257241
CallInst *TrapCall = Builder.CreateCall(CGM.getIntrinsic(Intrinsic::trap));
258242
TrapCall->setDoesNotReturn();
259243
TrapCall->setDoesNotThrow();
260244
Builder.CreateUnreachable();
261245

262246
Builder.SetInsertPoint(Begin);
263-
Builder.CreateCondBr(Cond1, DyCkSuccess, DyCkFallThrough);
247+
Builder.CreateCondBr(Condition, DyCkSuccess, DyCkFail);
264248
// This ensures the success block comes directly after the branch
265249
EmitBlock(DyCkSuccess);
266250

267251
Builder.SetInsertPoint(DyCkSuccess);
268252
}
253+

lib/CodeGen/CodeGenFunction.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2294,8 +2294,6 @@ class CodeGenFunction : public CodeGenTypeCache {
22942294
/// \brief Create a basic block that will call the trap intrinsic, and emit
22952295
/// a conditional branch to it, for Checked C's dynamic checks.
22962296
void EmitDynamicCheckBlocks(llvm::Value *Condition);
2297-
/// Emit code blocks for dynamic_check(cond1 || cond2)
2298-
void EmitDynamicCheckBlocks(llvm::Value *Cond1, llvm::Value *Cond2);
22992297

23002298
llvm::Value *EmitBoundsCast(CastExpr *CE);
23012299

0 commit comments

Comments
 (0)