/* * Merge two type sets into an aggregate set. If one of the sets * is a subset of the other, then that other subset is returned; * if the two sets are equal, then the ss1 instance is returned. * * If merging is not possible (incompatible basic types), then * null is returned, and err is set to an appropriate error * message. Otherwise, the merged type is returned, and err is * set to null. */ internal static CCTypeSet MergeNF(CCTypeSet ss1, CCTypeSet ss2, out string err) { err = null; if (ss2.IsSubsetOf(ss1)) { return(ss1); } if (ss1.IsSubsetOf(ss2)) { return(ss2); } /* * Handling of restricted types relies on the following * features: * * - A CCTypeSet that contains a restricted type can * only contain that restricted type, none other. * * - Restricted types cannot have allocation nodes, * variants, or be std::type. * * - The tests with IsSubsetOf() above have already * ruled out the case of two identical restricted types. */ if (ss1.types.Count == 1 && ss2.types.Count == 1) { CCType ct1 = ss1.types.Min; CCType ct2 = ss2.types.Min; if (ct1.xType.IsRestricted || ct2.xType.IsRestricted) { err = string.Format("forbidden type merging between {0} and {1}", ct1, ct2); return(null); } } CCTypeSet ss3 = new CCTypeSet(); foreach (CCType t in ss1.types) { ss3.types.Add(t); ss3.xTypes.Add(t.xType); } foreach (CCType t in ss2.types) { ss3.types.Add(t); ss3.xTypes.Add(t.xType); } return(ss3); }
internal CCLocals Set(int index, CCTypeSet cts) { CCTypeSet octs = locals[index]; if (!cts.IsSubsetOf(octs)) { CCLocals r = new CCLocals(locals.Length); Array.Copy(locals, 0, r.locals, 0, locals.Length); r.locals[index] = cts; return(r); } else { return(this); } }
internal static CCLocals MergeNF( CCLocals l1, CCLocals l2, out string err) { err = null; if (object.ReferenceEquals(l1, l2)) { return(l1); } int n = l1.locals.Length; if (n != l2.locals.Length) { err = string.Format("internal error: mismatch on number of locals ({0} / {1})", n, l2.locals.Length); return(null); } /* * Merge entries one by one. The destination is lazily * updated to avoid allocation when not needed. */ bool r1ok = true, r2ok = true; CCTypeSet[] nlocals = null; for (int i = 0; i < n; i++) { CCTypeSet cts1 = l1.locals[i]; CCTypeSet cts2 = l2.locals[i]; if (cts1.Equals(cts2)) { if (nlocals != null) { nlocals[i] = cts1; } } else if (cts1.IsSubsetOf(cts2)) { r1ok = false; if (r2ok) { continue; } if (nlocals != null) { nlocals[i] = cts2; } } else if (cts2.IsSubsetOf(cts1)) { r2ok = false; if (r1ok) { continue; } if (nlocals != null) { nlocals[i] = cts1; } } else { if (nlocals == null) { r1ok = false; r2ok = false; nlocals = new CCTypeSet[n]; Array.Copy(l1.locals, 0, nlocals, 0, i); } CCTypeSet cts = CCTypeSet.MergeNF( cts1, cts2, out err); if (cts == null) { return(null); } nlocals[i] = cts; } } if (r1ok) { return(l1); } if (r2ok) { return(l2); } return(new CCLocals(nlocals)); }