Skip to content

Commit b255965

Browse files
committed
CHB:ARM: update typing rules (in progress)
1 parent cbba28a commit b255965

File tree

2 files changed

+164
-52
lines changed

2 files changed

+164
-52
lines changed

CodeHawk/CHB/bchlibarm32/bCHFnARMTypeConstraints.ml

Lines changed: 163 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ open CHTraceResult
3636

3737
(* xprlib *)
3838
open XprTypes
39+
open XprUtil
3940
open Xsimplify
4041

4142
(* bchlib *)
@@ -255,6 +256,43 @@ object (self)
255256
linenumber
256257
[(p2s floc#l#toPretty) ^ ": " ^ (btype_to_string ty)] in
257258

259+
let operand_is_zero (op: arm_operand_int): bool =
260+
(* Returns true if the value of the operand is known to be zero at
261+
this location. This result is primarily intended to avoid spurious
262+
typing relationships in cases where the compiler 'knows' that the value
263+
is zero, and may use it as an alternate for the the immediate value zero
264+
in certain instructions, like ADD, MOV, or SUB. *)
265+
TR.tfold_default
266+
(fun v ->
267+
match v with
268+
| XConst (IntConst n) -> n#equal numerical_zero
269+
| _ -> false)
270+
false
271+
(TR.tmap rewrite_expr (op#to_expr floc)) in
272+
273+
let operand_is_zero_in_cc_context
274+
(cc: arm_opcode_cc_t) (op: arm_operand_int): bool =
275+
match cc with
276+
| ACCAlways -> operand_is_zero op
277+
| _ when instr#is_condition_covered -> operand_is_zero op
278+
| _ when is_cond_conditional cc && floc#has_test_expr ->
279+
TR.tfold_default
280+
(fun xx ->
281+
let txpr = floc#get_test_expr in
282+
let tcond = rewrite_expr txpr in
283+
(match tcond with
284+
| XOp (XEq, [XVar vr; XConst (IntConst n)]) ->
285+
let subst v =
286+
if v#equal vr then XConst (IntConst n) else XVar vr in
287+
let result = simplify_xpr (substitute_expr subst xx) in
288+
(match result with
289+
| XConst (IntConst n) -> n#equal numerical_zero
290+
| _ -> operand_is_zero op)
291+
| _ -> operand_is_zero op))
292+
(operand_is_zero op)
293+
(TR.tmap rewrite_expr (op#to_expr floc))
294+
| _ -> operand_is_zero op in
295+
258296
match instr#get_opcode with
259297

260298
| Add (_, _, rd, rn, rm, _) ->
@@ -275,7 +313,26 @@ object (self)
275313
| _ -> ())
276314
| _ -> ());
277315

278-
(if rm#is_immediate && (rm#to_numerical#toInt < 256) then
316+
(* Heuristic: if a small number (taken here as < 256) is added to
317+
a register value it is assumed that the value in the destination
318+
register has the same type as the value in the source register.
319+
320+
The case where the value of the source register is known to be zero
321+
is excluded, because this construct, rd = rn (=0) + imm, is often
322+
used as an alternate for MOV rd, #imm, in which case the type of
323+
the source value may be entirely related to the type of the type of
324+
the destination value (giving rise to very hard to diagnose typing
325+
errors)
326+
327+
This heuristic also fails when applied to pointers to access
328+
different fields in a struct. Although this case is not so common,
329+
(ARM allows offsets to be specified as part of memory accesses),
330+
it does happen (it has been observed), and hence this heuristic
331+
is disabled for now, until we have a way to explicitly exclude
332+
this case.
333+
(if rm#is_immediate
334+
&& (rm#to_numerical#toInt < 256)
335+
&& (not (operand_is_zero rn)) then
279336
let rdreg = rd#to_register in
280337
let lhstypevar = mk_reglhs_typevar rdreg faddr iaddr in
281338
let rndefs = get_variable_rdefs_r (rn#to_variable floc) in
@@ -288,7 +345,7 @@ object (self)
288345
begin
289346
log_subtype_constraint __LINE__ "ADD-imm" rntypeterm lhstypeterm;
290347
store#add_subtype_constraint rntypeterm lhstypeterm
291-
end) rndefs);
348+
end) rndefs); *)
292349

293350
(match getopt_global_address_r (rn#to_expr floc) with
294351
| Some gaddr ->
@@ -389,7 +446,19 @@ object (self)
389446
begin
390447
log_subtype_constraint __LINE__ "MVN" tctypeterm lhstypeterm;
391448
store#add_subtype_constraint tctypeterm lhstypeterm
392-
end)
449+
end);
450+
451+
(* propagate function return type *)
452+
(if rd#get_register = AR0 && (has_exit_use_r (rd#to_variable floc)) then
453+
let regvar = mk_reglhs_typevar rdreg faddr iaddr in
454+
let fvar = mk_function_typevar faddr in
455+
let fvar = add_return_capability fvar in
456+
let regterm = mk_vty_term regvar in
457+
let fterm = mk_vty_term fvar in
458+
begin
459+
log_subtype_constraint __LINE__ "MVN-freturn" regterm fterm;
460+
store#add_subtype_constraint regterm fterm
461+
end);
393462

394463
end
395464

@@ -399,15 +468,28 @@ object (self)
399468
let rmdefs = get_variable_rdefs_r (rm#to_variable floc) in
400469
let rmreg = rm#to_register in
401470
begin
402-
List.iter (fun rmsym ->
403-
let rmaddr = rmsym#getBaseName in
404-
let rmtypevar = mk_reglhs_typevar rmreg faddr rmaddr in
405-
let rmtypeterm = mk_vty_term rmtypevar in
406-
let lhstypeterm = mk_vty_term lhstypevar in
407-
begin
408-
log_subtype_constraint __LINE__ "MVN-rdef" rmtypeterm lhstypeterm;
409-
store#add_subtype_constraint rmtypeterm lhstypeterm
410-
end) rmdefs
471+
(List.iter (fun rmsym ->
472+
let rmaddr = rmsym#getBaseName in
473+
let rmtypevar = mk_reglhs_typevar rmreg faddr rmaddr in
474+
let rmtypeterm = mk_vty_term rmtypevar in
475+
let lhstypeterm = mk_vty_term lhstypevar in
476+
begin
477+
log_subtype_constraint __LINE__ "MVN-rdef" rmtypeterm lhstypeterm;
478+
store#add_subtype_constraint rmtypeterm lhstypeterm
479+
end) rmdefs);
480+
481+
(* propagate function return type *)
482+
(if rd#get_register = AR0 && (has_exit_use_r (rd#to_variable floc)) then
483+
let regvar = mk_reglhs_typevar rdreg faddr iaddr in
484+
let fvar = mk_function_typevar faddr in
485+
let fvar = add_return_capability fvar in
486+
let regterm = mk_vty_term regvar in
487+
let fterm = mk_vty_term fvar in
488+
begin
489+
log_subtype_constraint __LINE__ "MVN-freturn" regterm fterm;
490+
store#add_subtype_constraint regterm fterm
491+
end);
492+
411493
end
412494

413495
| BitwiseOr (_, _, rd, rn, _, _) ->
@@ -962,6 +1044,7 @@ object (self)
9621044
store#add_subtype_constraint tctypeterm rntypeterm
9631045
end) rndefs)
9641046

1047+
(*
9651048
| LogicalShiftRight (_, _, rd, rn, rm, _) when rm#is_immediate ->
9661049
let rdreg = rd#to_register in
9671050
let lhstypevar = mk_reglhs_typevar rdreg faddr iaddr in
@@ -988,29 +1071,45 @@ object (self)
9881071
log_subtype_constraint __LINE__ "LSR-rhs" tctypeterm rntypeterm;
9891072
store#add_subtype_constraint tctypeterm rntypeterm
9901073
end) rndefs)
991-
1074+
*)
9921075
| Move (_, _, rd, rm, _, _) when rm#is_immediate ->
993-
let rmval = rm#to_numerical#toInt in
994-
(* 0 provides no information about the type *)
995-
if rmval = 0 then
996-
()
997-
else
998-
let rdreg = rd#to_register in
999-
let lhstypevar = mk_reglhs_typevar rdreg faddr iaddr in
1000-
let tyc = get_intvalue_type_constant rmval in
1001-
let lhstypeterm = mk_vty_term lhstypevar in
1002-
let tctypeterm = mk_cty_term tyc in
1003-
begin
1004-
log_subtype_constraint __LINE__ "MOV-imm" tctypeterm lhstypeterm;
1005-
store#add_subtype_constraint tctypeterm lhstypeterm
1006-
end
1076+
let rdreg = rd#to_register in
1077+
let lhstypevar = mk_reglhs_typevar rdreg faddr iaddr in
1078+
begin
1079+
1080+
(* variable introduction for lhs with type *)
1081+
(match get_regvar_type_annotation () with
1082+
| Some t ->
1083+
let opttc = mk_btype_constraint lhstypevar t in
1084+
(match opttc with
1085+
| Some tc ->
1086+
begin
1087+
log_type_constraint __LINE__ "MOV-rvintro" tc;
1088+
store#add_constraint tc
1089+
end
1090+
| _ -> ())
1091+
| _ -> ());
1092+
1093+
(let rmval = rm#to_numerical#toInt in
1094+
(* 0 provides no information about the type *)
1095+
if rmval = 0 then
1096+
()
1097+
else
1098+
let tyc = get_intvalue_type_constant rmval in
1099+
let lhstypeterm = mk_vty_term lhstypevar in
1100+
let tctypeterm = mk_cty_term tyc in
1101+
begin
1102+
log_subtype_constraint __LINE__ "MOV-imm" tctypeterm lhstypeterm;
1103+
store#add_subtype_constraint tctypeterm lhstypeterm
1104+
end)
1105+
end
10071106

10081107
| Move (_, _, rd, rm, _, _) when rd#get_register = rm#get_register ->
10091108
(* exclude to avoid spurious rdefs to get involved *)
10101109
()
10111110

10121111
(* Move x, y --- x := y --- Y <: X *)
1013-
| Move (_, _, rd, rm, _, _) when rm#is_register ->
1112+
| Move (_, c, rd, rm, _, _) when rm#is_register ->
10141113
let xrm_r = rm#to_expr floc in
10151114
let rdreg = rd#to_register in
10161115
let rdtypevar = mk_reglhs_typevar rdreg faddr iaddr in
@@ -1058,19 +1157,28 @@ object (self)
10581157

10591158
(* use reaching defs *)
10601159
(let rmreg = rm#to_register in
1061-
let rmvar_r = rm#to_variable floc in
1062-
let rmrdefs = get_variable_rdefs_r rmvar_r in
1063-
let lhstypevar = mk_reglhs_typevar rdreg faddr iaddr in
1064-
List.iter (fun rmrdef ->
1065-
let rmaddr = rmrdef#getBaseName in
1066-
if rmaddr != "init" then
1067-
let rmtypevar = mk_reglhs_typevar rmreg faddr rmaddr in
1068-
let rmtypeterm = mk_vty_term rmtypevar in
1069-
let lhstypeterm = mk_vty_term lhstypevar in
1070-
begin
1071-
log_subtype_constraint __LINE__ "MOV-reg" rmtypeterm lhstypeterm;
1072-
store#add_subtype_constraint rmtypeterm lhstypeterm
1073-
end) rmrdefs)
1160+
if operand_is_zero_in_cc_context c rm then
1161+
(* This case is excluded, because the move from a register
1162+
that contains zero can be done as a substitute for the
1163+
move of an immediate value, without any relationships in
1164+
types between the source and destination register. It is
1165+
often used by compilers as a convenience, if the register
1166+
is known to have the value zero at this point. *)
1167+
()
1168+
else
1169+
let rmvar_r = rm#to_variable floc in
1170+
let rmrdefs = get_variable_rdefs_r rmvar_r in
1171+
let lhstypevar = mk_reglhs_typevar rdreg faddr iaddr in
1172+
List.iter (fun rmrdef ->
1173+
let rmaddr = rmrdef#getBaseName in
1174+
if rmaddr != "init" then
1175+
let rmtypevar = mk_reglhs_typevar rmreg faddr rmaddr in
1176+
let rmtypeterm = mk_vty_term rmtypevar in
1177+
let lhstypeterm = mk_vty_term lhstypevar in
1178+
begin
1179+
log_subtype_constraint __LINE__ "MOV-reg" rmtypeterm lhstypeterm;
1180+
store#add_subtype_constraint rmtypeterm lhstypeterm
1181+
end) rmrdefs)
10741182
end
10751183

10761184
| Pop (_, _, rl, _) when rl#includes_pc ->
@@ -1283,7 +1391,7 @@ object (self)
12831391

12841392
end
12851393

1286-
| Subtract (_, _, rd, rn, _, _, _) ->
1394+
| Subtract (_, _, rd, rn, rm, _, _) ->
12871395
let rdreg = rd#to_register in
12881396
let lhstypevar = mk_reglhs_typevar rdreg faddr iaddr in
12891397
let rndefs = get_variable_rdefs_r (rn#to_variable floc) in
@@ -1292,15 +1400,19 @@ object (self)
12921400

12931401
(* Note: Does not take into consideration the possibility of the
12941402
subtraction of two pointers *)
1295-
List.iter (fun rnsym ->
1296-
let rnaddr = rnsym#getBaseName in
1297-
let rntypevar = mk_reglhs_typevar rnreg faddr rnaddr in
1298-
let rntypeterm = mk_vty_term rntypevar in
1299-
let lhstypeterm = mk_vty_term lhstypevar in
1300-
begin
1301-
log_subtype_constraint __LINE__ "SUB-rdef-1" rntypeterm lhstypeterm;
1302-
store#add_subtype_constraint rntypeterm lhstypeterm
1303-
end) rndefs;
1403+
(if rm#is_immediate && (rm#to_numerical#toInt = 0) then
1404+
()
1405+
else
1406+
List.iter (fun rnsym ->
1407+
let rnaddr = rnsym#getBaseName in
1408+
let rntypevar = mk_reglhs_typevar rnreg faddr rnaddr in
1409+
let rntypeterm = mk_vty_term rntypevar in
1410+
let lhstypeterm = mk_vty_term lhstypevar in
1411+
begin
1412+
log_subtype_constraint
1413+
__LINE__ "SUB-rdef-1" rntypeterm lhstypeterm;
1414+
store#add_subtype_constraint rntypeterm lhstypeterm
1415+
end) rndefs);
13041416

13051417
(* propagate function return type *)
13061418
(if rd#get_register = AR0 && (has_exit_use_r (rd#to_variable floc)) then

CodeHawk/CHT/CHB_tests/bchlibarm32_tests/txbchlibarm32/bCHTranslateARMToCHIFTest.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ let codemax = make_dw "0x400000"
7373
let translate_store () =
7474
let tests = [
7575
("PUSHLR", "0x1b960", "04e02de500",
76-
[("var_0004", "LR_in"); ("SP", "sv__5__sv")]);
76+
[("var_0004", "LR_in"); ("SP", "sv__3__sv")]);
7777
("PUSHR0_3", "0x19470", "0f002de900",
7878
[("var_0016", "R0_in");
7979
("var_0012", "R1_in");

0 commit comments

Comments
 (0)