// storeByType returns the store instruction of the given type. private static obj.As storeByType(ref types.Type _t) => func(_t, (ref types.Type t, Defer _, Panic panic, Recover __) => { if (t.IsFloat()) { switch (t.Size()) { case 4L: return arm64.AFMOVS; break; case 8L: return arm64.AFMOVD; break; } } else { switch (t.Size()) { case 1L: return arm64.AMOVB; break; case 2L: return arm64.AMOVH; break; case 4L: return arm64.AMOVW; break; case 8L: return arm64.AMOVD; break; } } panic("bad store type"); });
// loadByType returns the load instruction of the given type. private static obj.As loadByType(ref types.Type _t) => func(_t, (ref types.Type t, Defer _, Panic panic, Recover __) => { if (t.IsFloat()) { switch (t.Size()) { case 4L: return arm64.AFMOVS; break; case 8L: return arm64.AFMOVD; break; } } else { switch (t.Size()) { case 1L: if (t.IsSigned()) { return arm64.AMOVB; } else { return arm64.AMOVBU; } break; case 2L: if (t.IsSigned()) { return arm64.AMOVH; } else { return arm64.AMOVHU; } break; case 4L: if (t.IsSigned()) { return arm64.AMOVW; } else { return arm64.AMOVWU; } break; case 8L: return arm64.AMOVD; break; } } panic("bad load type"); });
// IncomparableField returns an incomparable Field of struct Type t, if any. public static ref types.Field IncomparableField(ref types.Type t) { foreach (var(_, f) in t.FieldSlice()) { if (!IsComparable(f.Type)) { return(f); } } return(null); }
// algtype1 returns the AlgKind used for comparing and hashing Type t. // If it returns ANOEQ, it also returns the component type of t that // makes it incomparable. private static (AlgKind, ref types.Type) algtype1(ref types.Type t) { if (t.Broke()) { return(AMEM, null); } if (t.Noalg()) { return(ANOEQ, t); } if (t.Etype == TANY || t.Etype == TFORW) { // will be defined later. return(ANOEQ, t); } else if (t.Etype == TINT8 || t.Etype == TUINT8 || t.Etype == TINT16 || t.Etype == TUINT16 || t.Etype == TINT32 || t.Etype == TUINT32 || t.Etype == TINT64 || t.Etype == TUINT64 || t.Etype == TINT || t.Etype == TUINT || t.Etype == TUINTPTR || t.Etype == TBOOL || t.Etype == TPTR32 || t.Etype == TPTR64 || t.Etype == TCHAN || t.Etype == TUNSAFEPTR) { return(AMEM, null); } else if (t.Etype == TFUNC || t.Etype == TMAP) { return(ANOEQ, t); } else if (t.Etype == TFLOAT32) { return(AFLOAT32, null); } else if (t.Etype == TFLOAT64) { return(AFLOAT64, null); } else if (t.Etype == TCOMPLEX64) { return(ACPLX64, null); } else if (t.Etype == TCOMPLEX128) { return(ACPLX128, null); } else if (t.Etype == TSTRING) { return(ASTRING, null); } else if (t.Etype == TINTER) { if (t.IsEmptyInterface()) { return(ANILINTER, null); } } return(AINTER, null);
// algtype is like algtype1, except it returns the fixed-width AMEMxx variants // instead of the general AMEM kind when possible. private static AlgKind algtype(ref types.Type t) { var(a, _) = algtype1(t); if (a == AMEM) { switch (t.Width) { case 0L: return(AMEM0); break; case 1L: return(AMEM8); break; case 2L: return(AMEM16); break; case 4L: return(AMEM32); break; case 8L: return(AMEM64); break; case 16L: return(AMEM128); break; } } return(a); }
// IsRegularMemory reports whether t can be compared/hashed as regular memory. public static bool IsRegularMemory(ref types.Type t) { var(a, _) = algtype1(t); return(a == AMEM); }
// IsComparable reports whether t is a comparable type. public static bool IsComparable(ref types.Type t) { var(a, _) = algtype1(t); return(a != ANOEQ); }
// expandiface computes the method set for interface type t by // expanding embedded interfaces. private static void expandiface(ref types.Type t) { slice <ref types.Field> fields = default;