// constValue returns the value of the constant with the // dynamic type tag appropriate for c.Type(). func constValue(c *ssa.Const) value { if c.IsNil() { return zero(c.Type()) // typed nil } // By destination type: switch t := c.Type().Underlying().(type) { case *types.Basic: // TODO(adonovan): eliminate untyped constants from SSA form. switch t.Kind() { case types.Bool, types.UntypedBool: return exact.BoolVal(c.Value) case types.Int, types.UntypedInt: // Assume sizeof(int) is same on host and target. return int(c.Int64()) case types.Int8: return int8(c.Int64()) case types.Int16: return int16(c.Int64()) case types.Int32, types.UntypedRune: return int32(c.Int64()) case types.Int64: return c.Int64() case types.Uint: // Assume sizeof(uint) is same on host and target. return uint(c.Uint64()) case types.Uint8: return uint8(c.Uint64()) case types.Uint16: return uint16(c.Uint64()) case types.Uint32: return uint32(c.Uint64()) case types.Uint64: return c.Uint64() case types.Uintptr: // Assume sizeof(uintptr) is same on host and target. return uintptr(c.Uint64()) case types.Float32: return float32(c.Float64()) case types.Float64, types.UntypedFloat: return c.Float64() case types.Complex64: return complex64(c.Complex128()) case types.Complex128, types.UntypedComplex: return c.Complex128() case types.String, types.UntypedString: if c.Value.Kind() == exact.String { return exact.StringVal(c.Value) } return string(rune(c.Int64())) case types.UnsafePointer: panic("unsafe.Pointer constant") // not possible case types.UntypedNil: // nil was handled above. } case *types.Slice: switch et := t.Elem().Underlying().(type) { case *types.Basic: switch et.Kind() { case types.Byte: // string -> []byte var v []value for _, b := range []byte(exact.StringVal(c.Value)) { v = append(v, b) } return v case types.Rune: // string -> []rune var v []value for _, r := range []rune(exact.StringVal(c.Value)) { v = append(v, r) } return v } } } panic(fmt.Sprintf("constValue: Value.(type)=%T Type()=%s", c.Value, c.Type())) }