Răsfoiți Sursa

more small DCE fixes (Cpp target still crashes)

Simon Krajewski 13 ani în urmă
părinte
comite
837ed3f729
1 a modificat fișierele cu 15 adăugiri și 8 ștergeri
  1. 15 8
      dce.ml

+ 15 - 8
dce.ml

@@ -22,11 +22,11 @@
  * 6. Filter the types by keeping those that are used explicitly or have a used field.
  *
  * Notes:
- *	- the only influence of the typer is @:?used marking on structural subtyping
+ *  - the only influence of the typer is @:?used marking on structural subtyping
  *  - properties are currently tricky to handle on some targets
  *  - cpp target does not like removing unused overridden fields
  *  - most targets seem to require keeping a property field even if it is used only through its accessor methods
- *	- I did not consider inlining at all because I'm pretty sure I don't have to at this compilation stage
+ *  - I did not consider inlining at all because I'm pretty sure I don't have to at this compilation stage
  * 
  *)
 
@@ -69,7 +69,6 @@ let keep_field dce cf =
 	|| has_meta ":used" cf.cf_meta
 	|| cf.cf_name = "__init__"
 
-
 (* marking *)
 
 (* mark a field as kept *)
@@ -109,8 +108,9 @@ let rec mark_dependent_fields dce csup n stat =
 			let rec loop c =
 				(try
 					let cf = PMap.find n (if stat then c.cl_statics else c.cl_fields) in
-					(* if it's clear that the class is kept, the field has to be kept as well *)
-					if has_meta ":used" c.cl_meta then mark_field dce c cf stat
+					(* if it's clear that the class is kept, the field has to be kept as well. This is also true for
+					   extern interfaces because we cannot remove fields from them *)
+					if has_meta ":used" c.cl_meta || (csup.cl_interface && csup.cl_extern) then mark_field dce c cf stat
 					(* otherwise it might be kept if the class is kept later, so mark it as :?used *)
 					else if not (has_meta ":?used" cf.cf_meta) then cf.cf_meta <- (":?used",[],cf.cf_pos) :: cf.cf_meta;
 					(* Cpp currently requires all base methods to be marked too *)
@@ -189,6 +189,12 @@ and expr dce e =
 		) vl;
 	| TTypeExpr (TClassDecl c) ->
 		mark_class dce c;
+	| TCast(e, Some (TEnumDecl en)) ->
+		mark_t dce (TEnum(en,[]));
+		expr dce e;
+	| TTypeExpr (TEnumDecl e)
+	| TEnumField(e,_) ->
+		mark_t dce (TEnum(e,[]));		
 	| TCall ({eexpr = TConst TSuper} as e,el) ->
 		mark_t dce e.etype;
 		List.iter (expr dce) el;
@@ -221,7 +227,7 @@ let run ctx main types modules =
 			let keep_class = keep_whole_class dce c in
 			if keep_class then mark_class dce c;
 			(* extern classes should never serve as entry point *)
-			let keep_class = keep_class && not c.cl_extern in
+			let keep_class = keep_class && (not c.cl_extern || c.cl_interface) in
 			let rec loop2 acc cfl stat = match cfl with
 				| cf :: l when keep_class || keep_field dce cf ->
 					loop2 ((c,cf,stat) :: acc) l stat
@@ -295,13 +301,14 @@ let run ctx main types modules =
 				end;
 				b
 			) c.cl_ordered_fields;
-			(match c.cl_constructor with Some cf when not (keep_field dce cf) -> c.cl_constructor <- None | _ -> ());
+			if c.cl_path <> ([],"EReg") then
+				(match c.cl_constructor with Some cf when not (keep_field dce cf) -> c.cl_constructor <- None | _ -> ());
 			(* we keep a class if it was used or has a used field *)
 			if has_meta ":used" c.cl_meta || c.cl_ordered_statics <> [] || c.cl_ordered_fields <> [] then loop (mt :: acc) l else begin
 				if dce.debug then print_endline ("[DCE] Removed class " ^ (s_type_path c.cl_path));
 				loop acc l
 			end
-		| (TEnumDecl e) as mt :: l when has_meta ":used" e.e_meta || has_meta ":keep" e.e_meta || e.e_extern ->
+ 		| (TEnumDecl e) as mt :: l when has_meta ":used" e.e_meta || has_meta ":keep" e.e_meta || e.e_extern ->
 			loop (mt :: acc) l
 		| TEnumDecl _ :: l ->
 			loop acc l