Skip to content

Commit 7726475

Browse files
authored
[hl] allow assign struct to packed (#12043)
* [hl] allow assign struct to packed * Fix assign null cause access violation * Move is_packed check to only where it's needed * Add a space in args while we are here
1 parent b6b67ae commit 7726475

File tree

4 files changed

+101
-11
lines changed

4 files changed

+101
-11
lines changed

src/generators/genhl.ml

+12-9
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ type access =
130130
| AStaticFun of fundecl index
131131
| AInstanceFun of texpr * fundecl index
132132
| AInstanceProto of texpr * field index
133-
| AInstanceField of texpr * field index
133+
| AInstanceField of texpr * field index * bool
134134
| AArray of reg * (ttype * ttype) * reg
135135
| ACArray of reg * ttype * reg
136136
| AVirtualMethod of texpr * field index
@@ -1326,11 +1326,12 @@ and object_access ctx eobj t f =
13261326
match t with
13271327
| HObj p | HStruct p ->
13281328
(try
1329-
let fid = fst (get_index f.cf_name p) in
1329+
let fid, t = get_index f.cf_name p in
13301330
if f.cf_kind = Method MethNormal then
13311331
AInstanceProto (eobj, -fid-1)
13321332
else
1333-
AInstanceField (eobj, fid)
1333+
let is_packed = match t with | HPacked _ -> true | _ -> false in
1334+
AInstanceField (eobj, fid, is_packed)
13341335
with Not_found ->
13351336
ADynamic (eobj, alloc_string ctx f.cf_name))
13361337
| HVirtual v ->
@@ -1339,7 +1340,7 @@ and object_access ctx eobj t f =
13391340
if f.cf_kind = Method MethNormal then
13401341
AVirtualMethod (eobj, fid)
13411342
else
1342-
AInstanceField (eobj, fid)
1343+
AInstanceField (eobj, fid, false)
13431344
with Not_found ->
13441345
ADynamic (eobj, alloc_string ctx f.cf_name))
13451346
| HDyn ->
@@ -2175,7 +2176,7 @@ and eval_expr ctx e =
21752176
| _ -> abort "Constant mode required" e.epos
21762177
) in
21772178
(match get_access ctx value with
2178-
| AInstanceField (f, index) -> op ctx (OPrefetch (eval_expr ctx f, index + 1, mode))
2179+
| AInstanceField (f, index, _) -> op ctx (OPrefetch (eval_expr ctx f, index + 1, mode))
21792180
| _ -> op ctx (OPrefetch (eval_expr ctx value, 0, mode)));
21802181
alloc_tmp ctx HVoid
21812182
| "$unsafecast", [value] ->
@@ -2323,7 +2324,7 @@ and eval_expr ctx e =
23232324
op ctx (OStaticClosure (r,f));
23242325
| AInstanceFun (ethis, f) ->
23252326
op ctx (OInstanceClosure (r, f, eval_null_check ctx ethis))
2326-
| AInstanceField (ethis,fid) ->
2327+
| AInstanceField (ethis, fid, _) ->
23272328
let robj = eval_null_check ctx ethis in
23282329
op ctx (match ethis.eexpr with TConst TThis -> OGetThis (r,fid) | _ -> OField (r,robj,fid));
23292330
| AInstanceProto (ethis,fid) | AVirtualMethod (ethis, fid) ->
@@ -2521,15 +2522,17 @@ and eval_expr ctx e =
25212522
op ctx (OGetGlobal (o, g));
25222523
op ctx (OSetField (o, fid, r));
25232524
r
2524-
| AInstanceField ({ eexpr = TConst TThis }, fid) ->
2525+
| AInstanceField ({ eexpr = TConst TThis }, fid, is_packed) ->
25252526
let r = value() in
2527+
if is_packed then op ctx (ONullCheck r);
25262528
op ctx (OSetThis (fid,r));
25272529
r
2528-
| AInstanceField (ethis, fid) ->
2530+
| AInstanceField (ethis, fid, is_packed) ->
25292531
let rthis = eval_null_check ctx ethis in
25302532
hold ctx rthis;
25312533
let r = value() in
25322534
free ctx rthis;
2535+
if is_packed then op ctx (ONullCheck r);
25332536
op ctx (OSetField (rthis, fid, r));
25342537
r
25352538
| ALocal (v,l) ->
@@ -3087,7 +3090,7 @@ and gen_assign_op ctx acc e1 f =
30873090
f r
30883091
in
30893092
match acc with
3090-
| AInstanceField (eobj, findex) ->
3093+
| AInstanceField (eobj, findex, _) ->
30913094
let robj = eval_null_check ctx eobj in
30923095
hold ctx robj;
30933096
let t = real_type ctx e1 in

src/generators/hl2c.ml

+7-2
Original file line numberDiff line numberDiff line change
@@ -542,8 +542,13 @@ let generate_function ctx f =
542542
let funname fid = define_function ctx fid in
543543

544544
let rcast r t =
545-
if tsame (rtype r) t then (reg r)
546-
else Printf.sprintf "((%s)%s)" (ctype t) (reg r)
545+
let rt = (rtype r) in
546+
if tsame rt t then (reg r)
547+
else match t, rt with
548+
| HPacked _, HStruct _ ->
549+
Printf.sprintf "(*(%s*)%s)" (ctype t) (reg r)
550+
| _ ->
551+
Printf.sprintf "((%s)%s)" (ctype t) (reg r)
547552
in
548553

549554
let rfun r args t =

src/generators/hlcode.ml

+2
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,8 @@ let rec safe_cast t1 t2 =
355355
loop p1
356356
| HPacked t1, HStruct _ ->
357357
safe_cast t1 t2
358+
| HStruct _, HPacked t2 ->
359+
safe_cast t1 t2
358360
| HFun (args1,t1), HFun (args2,t2) when List.length args1 = List.length args2 ->
359361
List.for_all2 (fun t1 t2 -> safe_cast t2 t1 || (t1 = HDyn && is_dynamic t2)) args1 args2 && safe_cast t1 t2
360362
| HArray t1,HArray t2 ->
+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package unit.issues;
2+
3+
#if hl
4+
private class Parent {
5+
@:packed public var st : St;
6+
@:packed public var st1 : St;
7+
public function new() {
8+
}
9+
}
10+
11+
@:struct private class St {
12+
public var x : Single;
13+
public var y : Single;
14+
public var z : Single;
15+
public function new( x : Single, y : Single, z : Single ) {
16+
this.x = x;
17+
this.y = y;
18+
this.z = z;
19+
}
20+
}
21+
#end
22+
23+
class Issue12043 extends Test {
24+
#if hl
25+
var p : Parent;
26+
@:packed var st2 : St;
27+
var st3 : St;
28+
function test() {
29+
// assign @:struct to @:packed
30+
st3 = new St(16.3, 17.3, 18.3);
31+
st2 = new St(13.3, 14.3, 15.3);
32+
p = new Parent();
33+
p.st1 = st2;
34+
p.st = new St(10.3, 11.3, 12.3);
35+
feq(10.3, p.st.x);
36+
feq(11.3, p.st.y);
37+
feq(12.3, p.st.z);
38+
feq(13.3, p.st1.x);
39+
feq(14.3, p.st1.y);
40+
feq(15.3, p.st1.z);
41+
feq(13.3, st2.x);
42+
feq(14.3, st2.y);
43+
feq(15.3, st2.z);
44+
feq(16.3, st3.x);
45+
feq(17.3, st3.y);
46+
feq(18.3, st3.z);
47+
48+
// assign inside @:packed
49+
p.st.y = 7.7;
50+
st2.y = 8.8;
51+
st3.y = 9.9;
52+
feq(10.3, p.st.x);
53+
feq(7.7, p.st.y);
54+
feq(12.3, p.st.z);
55+
feq(13.3, p.st1.x);
56+
feq(14.3, p.st1.y); // p.st1 is a copy and is not impacted
57+
feq(15.3, p.st1.z);
58+
feq(13.3, st2.x);
59+
feq(8.8, st2.y);
60+
feq(15.3, st2.z);
61+
feq(16.3, st3.x);
62+
feq(9.9, st3.y);
63+
feq(18.3, st3.z);
64+
65+
// assign null to @:packed
66+
try {
67+
p.st = null;
68+
assert("Assign null to @:packed is currently not allowed");
69+
} catch (e) {
70+
eq("Null access", e.message);
71+
}
72+
try {
73+
st2 = null;
74+
assert("Assign null to @:packed is currently not allowed");
75+
} catch (e) {
76+
eq("Null access", e.message);
77+
}
78+
}
79+
#end
80+
}

0 commit comments

Comments
 (0)