func sysVClassifyType(typ types.Type) []sysVParameterClass { switch typ := typ.(type) { case *types.Struct: return sysVClassifyStructType(typ) case *types.Array: return sysVClassifyArrayType(typ) case *types.Int: switch typ.Width() { case 1, 8, 16, 32, 64, 128: return []sysVParameterClass{sysVClassINTEGER} default: panic("unim") } case *types.Pointer: return []sysVParameterClass{sysVClassINTEGER} case *types.Float: switch typ.Type() { case types.Float32, types.Float64: return []sysVParameterClass{sysVClassSSE} default: panic("unim") } case types.Void: return []sysVParameterClass{sysVClassNO_CLASS} default: panic("amd64.classifyType: unim: " + reflect.TypeOf(typ).String()) } }
func errIfNotPointerType(i ssa.Instruction, t types.Type) error { _, ok := t.(*types.Pointer) if !ok { return &InstrError{ Instr: i, Message: "Expected pointer type, found `" + t.String() + "`", } } return nil }
func errIfNotFloatType(i ssa.Instruction, t types.Type) error { _, ok := t.(*types.Float) if !ok { return &InstrError{ Instr: i, Message: "Expected float type, found `" + t.String() + "`", } } return nil }
func errIfMismatchedTypes(t1, t2 types.Type, i ssa.Instruction) error { if !t1.Equals(t2) { return &InstrError{ Message: fmt.Sprintf("Mismatched types `%s` and `%s`", t1, t2), Instr: i, } } return nil }
func TypeSizeInBits(typ types.Type) int { switch typ := typ.(type) { case *types.Int: w := typ.Width() for w%8 != 0 { w++ } return w case *types.Float: return typ.Type().Width() case *types.Pointer: return 64 case *types.Array: return TypeSizeInBits(typ.Element()) * typ.Length() case *types.Struct: return newStructLayout(typ).size default: panic("unim") } }
// will always be multiple of 8 func TypeAlignmentInBits(typ types.Type) int { switch typ := typ.(type) { case *types.Struct: return newStructLayout(typ).alignment case *types.Array: return TypeAlignmentInBits(typ.Element()) } sz := TypeSizeInBits(typ) i := 8 for i < sz { i *= 2 } return i }
func checkMismatchedTypesGlobal(t1, t2 types.Type, g *ssa.Global) error { if !t1.Equals(t2) { return &GlobalError{ Global: g, Message: "Mismatched types: `" + t1.String() + "` and `" + t2.String() + "`", } } return nil }
func checkTypeSupported(typ types.Type) { switch typ := typ.(type) { case *types.Int: switch typ.Width() { case 1, 8, 16, 32, 64: // all good default: goto unsupported } case *types.Array: checkTypeSupported(typ.Element()) case *types.Struct: for _, field := range typ.Fields() { checkTypeSupported(field) } } return unsupported: panic(fmt.Sprintf("unsupported type: %s", typ)) }