mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2024-11-27 14:16:39 +00:00
1338 lines
42 KiB
Go
1338 lines
42 KiB
Go
|
// Copyright 2019 The CC Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style
|
||
|
// license that can be found in the LICENSE file.
|
||
|
|
||
|
package cc // import "modernc.org/cc/v3"
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"math"
|
||
|
"math/big"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
_ Value = (*Float128Value)(nil)
|
||
|
_ Value = (*InitializerValue)(nil)
|
||
|
_ Value = Complex128Value(0)
|
||
|
_ Value = Complex256Value{}
|
||
|
_ Value = Complex64Value(0)
|
||
|
_ Value = Float32Value(0)
|
||
|
_ Value = Float64Value(0)
|
||
|
_ Value = Int64Value(0)
|
||
|
_ Value = StringValue(0)
|
||
|
_ Value = Uint64Value(0)
|
||
|
_ Value = WideStringValue(0)
|
||
|
|
||
|
_ Operand = (*funcDesignator)(nil)
|
||
|
_ Operand = (*lvalue)(nil)
|
||
|
_ Operand = (*operand)(nil)
|
||
|
_ Operand = noOperand
|
||
|
|
||
|
noOperand = &operand{typ: noType}
|
||
|
)
|
||
|
|
||
|
type Operand interface {
|
||
|
// IsAssingmentCompatible reports whether the operand can be
|
||
|
// assigned to lhs. [0], 6.5.16.1.
|
||
|
IsAssingmentCompatible(lhs Type) bool
|
||
|
ConvertTo(Type) Operand
|
||
|
Declarator() *Declarator
|
||
|
IsConst() bool
|
||
|
IsLValue() bool
|
||
|
IsNonZero() bool
|
||
|
IsZero() bool
|
||
|
Offset() uintptr // Valid only for non nil Declarator() value
|
||
|
Type() Type
|
||
|
Value() Value
|
||
|
convertFromInt(*context, Node, Type) Operand
|
||
|
convertTo(*context, Node, Type) Operand
|
||
|
convertToInt(*context, Node, Type) Operand
|
||
|
getABI() *ABI
|
||
|
integerPromotion(*context, Node) Operand
|
||
|
normalize(*context, Node) Operand
|
||
|
}
|
||
|
|
||
|
type Value interface {
|
||
|
IsConst() bool
|
||
|
IsNonZero() bool
|
||
|
IsZero() bool
|
||
|
add(b Value) Value
|
||
|
and(b Value) Value
|
||
|
cpl() Value
|
||
|
div(b Value) Value
|
||
|
eq(b Value) Value
|
||
|
ge(b Value) Value
|
||
|
gt(b Value) Value
|
||
|
le(b Value) Value
|
||
|
lsh(b Value) Value
|
||
|
lt(b Value) Value
|
||
|
mod(b Value) Value
|
||
|
mul(b Value) Value
|
||
|
neg() Value
|
||
|
neq(b Value) Value
|
||
|
or(b Value) Value
|
||
|
rsh(b Value) Value
|
||
|
sub(b Value) Value
|
||
|
xor(b Value) Value
|
||
|
}
|
||
|
|
||
|
type WideStringValue StringID
|
||
|
|
||
|
func (v WideStringValue) add(b Value) Value { panic(todo("")) }
|
||
|
func (v WideStringValue) and(b Value) Value { panic(todo("")) }
|
||
|
func (v WideStringValue) cpl() Value { panic(todo("")) }
|
||
|
func (v WideStringValue) div(b Value) Value { panic(todo("")) }
|
||
|
func (v WideStringValue) eq(b Value) Value { return boolValue(v == b.(WideStringValue)) }
|
||
|
func (v WideStringValue) IsConst() bool { return true }
|
||
|
func (v WideStringValue) IsNonZero() bool { return true }
|
||
|
func (v WideStringValue) IsZero() bool { return false }
|
||
|
func (v WideStringValue) lsh(b Value) Value { panic(todo("")) }
|
||
|
func (v WideStringValue) mod(b Value) Value { panic(todo("")) }
|
||
|
func (v WideStringValue) mul(b Value) Value { panic(todo("")) }
|
||
|
func (v WideStringValue) neg() Value { panic(todo("")) }
|
||
|
func (v WideStringValue) neq(b Value) Value { return boolValue(v != b.(WideStringValue)) }
|
||
|
func (v WideStringValue) or(b Value) Value { panic(todo("")) }
|
||
|
func (v WideStringValue) rsh(b Value) Value { panic(todo("")) }
|
||
|
func (v WideStringValue) sub(b Value) Value { panic(todo("")) }
|
||
|
func (v WideStringValue) xor(b Value) Value { panic(todo("")) }
|
||
|
|
||
|
func (v WideStringValue) le(b Value) Value {
|
||
|
return boolValue(StringID(v).String() <= StringID(b.(WideStringValue)).String())
|
||
|
}
|
||
|
|
||
|
func (v WideStringValue) ge(b Value) Value {
|
||
|
return boolValue(StringID(v).String() >= StringID(b.(WideStringValue)).String())
|
||
|
}
|
||
|
|
||
|
func (v WideStringValue) gt(b Value) Value {
|
||
|
return boolValue(StringID(v).String() > StringID(b.(WideStringValue)).String())
|
||
|
}
|
||
|
|
||
|
func (v WideStringValue) lt(b Value) Value {
|
||
|
return boolValue(StringID(v).String() < StringID(b.(WideStringValue)).String())
|
||
|
}
|
||
|
|
||
|
type StringValue StringID
|
||
|
|
||
|
func (v StringValue) add(b Value) Value { panic(todo("")) }
|
||
|
func (v StringValue) and(b Value) Value { panic(todo("")) }
|
||
|
func (v StringValue) cpl() Value { panic(todo("")) }
|
||
|
func (v StringValue) div(b Value) Value { panic(todo("")) }
|
||
|
func (v StringValue) eq(b Value) Value { return boolValue(v == b.(StringValue)) }
|
||
|
func (v StringValue) IsConst() bool { return true }
|
||
|
func (v StringValue) IsNonZero() bool { return true }
|
||
|
func (v StringValue) IsZero() bool { return false }
|
||
|
func (v StringValue) lsh(b Value) Value { panic(todo("")) }
|
||
|
func (v StringValue) mod(b Value) Value { panic(todo("")) }
|
||
|
func (v StringValue) mul(b Value) Value { panic(todo("")) }
|
||
|
func (v StringValue) neg() Value { panic(todo("")) }
|
||
|
func (v StringValue) neq(b Value) Value { return boolValue(v != b.(StringValue)) }
|
||
|
func (v StringValue) or(b Value) Value { panic(todo("")) }
|
||
|
func (v StringValue) rsh(b Value) Value { panic(todo("")) }
|
||
|
func (v StringValue) sub(b Value) Value { panic(todo("")) }
|
||
|
func (v StringValue) xor(b Value) Value { panic(todo("")) }
|
||
|
|
||
|
func (v StringValue) le(b Value) Value {
|
||
|
return boolValue(StringID(v).String() <= StringID(b.(StringValue)).String())
|
||
|
}
|
||
|
|
||
|
func (v StringValue) ge(b Value) Value {
|
||
|
return boolValue(StringID(v).String() >= StringID(b.(StringValue)).String())
|
||
|
}
|
||
|
|
||
|
func (v StringValue) gt(b Value) Value {
|
||
|
return boolValue(StringID(v).String() > StringID(b.(StringValue)).String())
|
||
|
}
|
||
|
|
||
|
func (v StringValue) lt(b Value) Value {
|
||
|
return boolValue(StringID(v).String() < StringID(b.(StringValue)).String())
|
||
|
}
|
||
|
|
||
|
type Int64Value int64
|
||
|
|
||
|
func (v Int64Value) add(b Value) Value { return v + b.(Int64Value) }
|
||
|
func (v Int64Value) and(b Value) Value { return v & b.(Int64Value) }
|
||
|
func (v Int64Value) cpl() Value { return ^v }
|
||
|
func (v Int64Value) eq(b Value) Value { return boolValue(v == b.(Int64Value)) }
|
||
|
func (v Int64Value) ge(b Value) Value { return boolValue(v >= b.(Int64Value)) }
|
||
|
func (v Int64Value) gt(b Value) Value { return boolValue(v > b.(Int64Value)) }
|
||
|
func (v Int64Value) IsConst() bool { return true }
|
||
|
func (v Int64Value) IsNonZero() bool { return v != 0 }
|
||
|
func (v Int64Value) IsZero() bool { return v == 0 }
|
||
|
func (v Int64Value) le(b Value) Value { return boolValue(v <= b.(Int64Value)) }
|
||
|
func (v Int64Value) lt(b Value) Value { return boolValue(v < b.(Int64Value)) }
|
||
|
func (v Int64Value) mul(b Value) Value { return v * b.(Int64Value) }
|
||
|
func (v Int64Value) neg() Value { return -v }
|
||
|
func (v Int64Value) neq(b Value) Value { return boolValue(v != b.(Int64Value)) }
|
||
|
func (v Int64Value) or(b Value) Value { return v | b.(Int64Value) }
|
||
|
func (v Int64Value) sub(b Value) Value { return v - b.(Int64Value) }
|
||
|
func (v Int64Value) xor(b Value) Value { return v ^ b.(Int64Value) }
|
||
|
|
||
|
func (v Int64Value) div(b Value) Value {
|
||
|
if b.IsZero() {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return v / b.(Int64Value)
|
||
|
}
|
||
|
|
||
|
func (v Int64Value) lsh(b Value) Value {
|
||
|
switch y := b.(type) {
|
||
|
case Int64Value:
|
||
|
return v << uint64(y)
|
||
|
case Uint64Value:
|
||
|
return v << y
|
||
|
default:
|
||
|
panic(todo(""))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (v Int64Value) rsh(b Value) Value {
|
||
|
switch y := b.(type) {
|
||
|
case Int64Value:
|
||
|
return v >> uint64(y)
|
||
|
case Uint64Value:
|
||
|
return v >> y
|
||
|
default:
|
||
|
panic(todo(""))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (v Int64Value) mod(b Value) Value {
|
||
|
if b.IsZero() {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return v % b.(Int64Value)
|
||
|
}
|
||
|
|
||
|
type Uint64Value uint64
|
||
|
|
||
|
func (v Uint64Value) add(b Value) Value { return v + b.(Uint64Value) }
|
||
|
func (v Uint64Value) and(b Value) Value { return v & b.(Uint64Value) }
|
||
|
func (v Uint64Value) cpl() Value { return ^v }
|
||
|
func (v Uint64Value) eq(b Value) Value { return boolValue(v == b.(Uint64Value)) }
|
||
|
func (v Uint64Value) ge(b Value) Value { return boolValue(v >= b.(Uint64Value)) }
|
||
|
func (v Uint64Value) gt(b Value) Value { return boolValue(v > b.(Uint64Value)) }
|
||
|
func (v Uint64Value) IsConst() bool { return true }
|
||
|
func (v Uint64Value) IsNonZero() bool { return v != 0 }
|
||
|
func (v Uint64Value) IsZero() bool { return v == 0 }
|
||
|
func (v Uint64Value) le(b Value) Value { return boolValue(v <= b.(Uint64Value)) }
|
||
|
func (v Uint64Value) lt(b Value) Value { return boolValue(v < b.(Uint64Value)) }
|
||
|
func (v Uint64Value) mul(b Value) Value { return v * b.(Uint64Value) }
|
||
|
func (v Uint64Value) neg() Value { return -v }
|
||
|
func (v Uint64Value) neq(b Value) Value { return boolValue(v != b.(Uint64Value)) }
|
||
|
func (v Uint64Value) or(b Value) Value { return v | b.(Uint64Value) }
|
||
|
func (v Uint64Value) sub(b Value) Value { return v - b.(Uint64Value) }
|
||
|
func (v Uint64Value) xor(b Value) Value { return v ^ b.(Uint64Value) }
|
||
|
|
||
|
func (v Uint64Value) div(b Value) Value {
|
||
|
if b.IsZero() {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return v / b.(Uint64Value)
|
||
|
}
|
||
|
|
||
|
func (v Uint64Value) lsh(b Value) Value {
|
||
|
switch y := b.(type) {
|
||
|
case Int64Value:
|
||
|
return v << uint64(y)
|
||
|
case Uint64Value:
|
||
|
return v << y
|
||
|
default:
|
||
|
panic(todo(""))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (v Uint64Value) rsh(b Value) Value {
|
||
|
switch y := b.(type) {
|
||
|
case Int64Value:
|
||
|
return v >> uint64(y)
|
||
|
case Uint64Value:
|
||
|
return v >> y
|
||
|
default:
|
||
|
panic(todo(""))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (v Uint64Value) mod(b Value) Value {
|
||
|
if b.IsZero() {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return v % b.(Uint64Value)
|
||
|
}
|
||
|
|
||
|
type Float32Value float32
|
||
|
|
||
|
func (v Float32Value) add(b Value) Value { return v + b.(Float32Value) }
|
||
|
func (v Float32Value) and(b Value) Value { panic(todo("")) }
|
||
|
func (v Float32Value) cpl() Value { panic(todo("")) }
|
||
|
func (v Float32Value) div(b Value) Value { return v / b.(Float32Value) }
|
||
|
func (v Float32Value) eq(b Value) Value { return boolValue(v == b.(Float32Value)) }
|
||
|
func (v Float32Value) ge(b Value) Value { return boolValue(v >= b.(Float32Value)) }
|
||
|
func (v Float32Value) gt(b Value) Value { return boolValue(v > b.(Float32Value)) }
|
||
|
func (v Float32Value) IsConst() bool { return true }
|
||
|
func (v Float32Value) IsNonZero() bool { return v != 0 }
|
||
|
func (v Float32Value) IsZero() bool { return !math.Signbit(float64(v)) && v == 0 }
|
||
|
func (v Float32Value) le(b Value) Value { return boolValue(v <= b.(Float32Value)) }
|
||
|
func (v Float32Value) lsh(b Value) Value { panic(todo("")) }
|
||
|
func (v Float32Value) lt(b Value) Value { return boolValue(v < b.(Float32Value)) }
|
||
|
func (v Float32Value) mod(b Value) Value { panic(todo("")) }
|
||
|
func (v Float32Value) mul(b Value) Value { return v * b.(Float32Value) }
|
||
|
func (v Float32Value) neg() Value { return -v }
|
||
|
func (v Float32Value) neq(b Value) Value { return boolValue(v != b.(Float32Value)) }
|
||
|
func (v Float32Value) or(b Value) Value { panic(todo("")) }
|
||
|
func (v Float32Value) rsh(b Value) Value { panic(todo("")) }
|
||
|
func (v Float32Value) sub(b Value) Value { return v - b.(Float32Value) }
|
||
|
func (v Float32Value) xor(b Value) Value { panic(todo("")) }
|
||
|
|
||
|
type Float64Value float64
|
||
|
|
||
|
func (v Float64Value) add(b Value) Value { return v + b.(Float64Value) }
|
||
|
func (v Float64Value) and(b Value) Value { panic(todo("")) }
|
||
|
func (v Float64Value) cpl() Value { panic(todo("")) }
|
||
|
func (v Float64Value) div(b Value) Value { return v / b.(Float64Value) }
|
||
|
func (v Float64Value) eq(b Value) Value { return boolValue(v == b.(Float64Value)) }
|
||
|
func (v Float64Value) ge(b Value) Value { return boolValue(v >= b.(Float64Value)) }
|
||
|
func (v Float64Value) gt(b Value) Value { return boolValue(v > b.(Float64Value)) }
|
||
|
func (v Float64Value) IsConst() bool { return true }
|
||
|
func (v Float64Value) IsNonZero() bool { return v != 0 }
|
||
|
func (v Float64Value) IsZero() bool { return !math.Signbit(float64(v)) && v == 0 }
|
||
|
func (v Float64Value) le(b Value) Value { return boolValue(v <= b.(Float64Value)) }
|
||
|
func (v Float64Value) lsh(b Value) Value { panic(todo("")) }
|
||
|
func (v Float64Value) lt(b Value) Value { return boolValue(v < b.(Float64Value)) }
|
||
|
func (v Float64Value) mod(b Value) Value { panic(todo("")) }
|
||
|
func (v Float64Value) mul(b Value) Value { return v * b.(Float64Value) }
|
||
|
func (v Float64Value) neg() Value { return -v }
|
||
|
func (v Float64Value) neq(b Value) Value { return boolValue(v != b.(Float64Value)) }
|
||
|
func (v Float64Value) or(b Value) Value { panic(todo("")) }
|
||
|
func (v Float64Value) rsh(b Value) Value { panic(todo("")) }
|
||
|
func (v Float64Value) sub(b Value) Value { return v - b.(Float64Value) }
|
||
|
func (v Float64Value) xor(b Value) Value { panic(todo("")) }
|
||
|
|
||
|
var float128Zero = &Float128Value{N: big.NewFloat(0)}
|
||
|
|
||
|
type Float128Value struct {
|
||
|
N *big.Float
|
||
|
NaN bool
|
||
|
}
|
||
|
|
||
|
func (v *Float128Value) add(b Value) Value { return v.safe(b, func(x, y *big.Float) { x.Add(x, y) }) }
|
||
|
func (v *Float128Value) and(b Value) Value { panic(todo("")) }
|
||
|
func (v *Float128Value) cpl() Value { panic(todo("")) }
|
||
|
func (v *Float128Value) div(b Value) Value { return v.safe(b, func(x, y *big.Float) { x.Quo(x, y) }) }
|
||
|
func (v *Float128Value) eq(b Value) Value { panic(todo("")) }
|
||
|
func (v *Float128Value) ge(b Value) Value { panic(todo("")) }
|
||
|
func (v *Float128Value) gt(b Value) Value { return boolValue(v.cmp(b, -1, 0)) }
|
||
|
func (v *Float128Value) IsNonZero() bool { panic(todo("")) }
|
||
|
func (v *Float128Value) IsConst() bool { return true }
|
||
|
func (v *Float128Value) IsZero() bool { return !v.NaN && !v.N.Signbit() && v.cmp(float128Zero, 0) }
|
||
|
func (v *Float128Value) le(b Value) Value { panic(todo("")) }
|
||
|
func (v *Float128Value) lsh(b Value) Value { panic(todo("")) }
|
||
|
func (v *Float128Value) lt(b Value) Value { panic(todo("")) }
|
||
|
func (v *Float128Value) mod(b Value) Value { panic(todo("")) }
|
||
|
func (v *Float128Value) mul(b Value) Value { return v.safe(b, func(x, y *big.Float) { x.Mul(x, y) }) }
|
||
|
func (v *Float128Value) neg() Value { return v.safe(nil, func(x, y *big.Float) { x.Neg(x) }) }
|
||
|
func (v *Float128Value) neq(b Value) Value { panic(todo("")) }
|
||
|
func (v *Float128Value) or(b Value) Value { panic(todo("")) }
|
||
|
func (v *Float128Value) rsh(b Value) Value { panic(todo("")) }
|
||
|
func (v *Float128Value) sub(b Value) Value { return v.safe(b, func(x, y *big.Float) { x.Sub(x, y) }) }
|
||
|
func (v *Float128Value) xor(b Value) Value { panic(todo("")) }
|
||
|
|
||
|
func (v *Float128Value) cmp(b Value, accept ...int) bool {
|
||
|
w := b.(*Float128Value)
|
||
|
if v.NaN || w.NaN {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
x := v.N.Cmp(w.N)
|
||
|
for _, v := range accept {
|
||
|
if v == x {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
func (v *Float128Value) String() string {
|
||
|
switch {
|
||
|
case v == nil:
|
||
|
return "<nil>"
|
||
|
case v.NaN:
|
||
|
return "NaN"
|
||
|
default:
|
||
|
return fmt.Sprint(v.N)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (v *Float128Value) safe(b Value, f func(*big.Float, *big.Float)) (ret Value) {
|
||
|
var w *Float128Value
|
||
|
if b != nil {
|
||
|
w = b.(*Float128Value)
|
||
|
}
|
||
|
if v.NaN || w != nil && w.NaN {
|
||
|
return &Float128Value{NaN: true}
|
||
|
}
|
||
|
|
||
|
r := &Float128Value{}
|
||
|
|
||
|
defer func() {
|
||
|
switch x := recover().(type) {
|
||
|
case big.ErrNaN:
|
||
|
r.N = nil
|
||
|
r.NaN = true
|
||
|
ret = r
|
||
|
case nil:
|
||
|
// ok
|
||
|
default:
|
||
|
panic(x)
|
||
|
}
|
||
|
}()
|
||
|
|
||
|
r.N = big.NewFloat(0).SetPrec(0).Set(v.N)
|
||
|
var wn *big.Float
|
||
|
if w != nil {
|
||
|
wn = w.N
|
||
|
}
|
||
|
f(r.N, wn)
|
||
|
return r
|
||
|
}
|
||
|
|
||
|
type Complex64Value complex64
|
||
|
|
||
|
func (v Complex64Value) add(b Value) Value { return v + b.(Complex64Value) }
|
||
|
func (v Complex64Value) and(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex64Value) cpl() Value { panic(todo("")) }
|
||
|
func (v Complex64Value) div(b Value) Value { return v / b.(Complex64Value) }
|
||
|
func (v Complex64Value) eq(b Value) Value { return boolValue(v == b.(Complex64Value)) }
|
||
|
func (v Complex64Value) ge(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex64Value) gt(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex64Value) IsConst() bool { return true }
|
||
|
func (v Complex64Value) IsNonZero() bool { return v != 0 }
|
||
|
func (v Complex64Value) IsZero() bool { return v == 0 }
|
||
|
func (v Complex64Value) le(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex64Value) lsh(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex64Value) lt(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex64Value) mod(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex64Value) mul(b Value) Value { return v * b.(Complex64Value) }
|
||
|
func (v Complex64Value) neg() Value { return -v }
|
||
|
func (v Complex64Value) neq(b Value) Value { return boolValue(v != b.(Complex64Value)) }
|
||
|
func (v Complex64Value) or(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex64Value) rsh(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex64Value) sub(b Value) Value { return v - b.(Complex64Value) }
|
||
|
func (v Complex64Value) xor(b Value) Value { panic(todo("")) }
|
||
|
|
||
|
type Complex128Value complex128
|
||
|
|
||
|
func (v Complex128Value) add(b Value) Value { return v + b.(Complex128Value) }
|
||
|
func (v Complex128Value) and(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex128Value) cpl() Value { panic(todo("")) }
|
||
|
func (v Complex128Value) div(b Value) Value { return v / b.(Complex128Value) }
|
||
|
func (v Complex128Value) eq(b Value) Value { return boolValue(v == b.(Complex128Value)) }
|
||
|
func (v Complex128Value) ge(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex128Value) gt(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex128Value) IsConst() bool { return true }
|
||
|
func (v Complex128Value) IsNonZero() bool { return v != 0 }
|
||
|
func (v Complex128Value) IsZero() bool { return v == 0 }
|
||
|
func (v Complex128Value) le(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex128Value) lsh(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex128Value) lt(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex128Value) mod(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex128Value) mul(b Value) Value { return v * b.(Complex128Value) }
|
||
|
func (v Complex128Value) neg() Value { return -v }
|
||
|
func (v Complex128Value) neq(b Value) Value { return boolValue(v != b.(Complex128Value)) }
|
||
|
func (v Complex128Value) or(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex128Value) rsh(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex128Value) sub(b Value) Value { return v - b.(Complex128Value) }
|
||
|
func (v Complex128Value) xor(b Value) Value { panic(todo("")) }
|
||
|
|
||
|
type Complex256Value struct {
|
||
|
Re, Im *Float128Value
|
||
|
}
|
||
|
|
||
|
func (v Complex256Value) add(b Value) Value {
|
||
|
w := b.(Complex256Value)
|
||
|
return Complex256Value{v.Re.add(w.Re).(*Float128Value), v.Im.add(w.Im).(*Float128Value)}
|
||
|
}
|
||
|
|
||
|
func (v Complex256Value) and(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex256Value) cpl() Value { panic(todo("")) }
|
||
|
func (v Complex256Value) div(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex256Value) eq(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex256Value) ge(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex256Value) gt(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex256Value) IsConst() bool { return true }
|
||
|
func (v Complex256Value) IsNonZero() bool { panic(todo("")) }
|
||
|
func (v Complex256Value) IsZero() bool { return v.Re.IsZero() && v.Im.IsZero() }
|
||
|
func (v Complex256Value) le(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex256Value) lsh(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex256Value) lt(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex256Value) mod(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex256Value) mul(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex256Value) neg() Value { panic(todo("")) }
|
||
|
func (v Complex256Value) neq(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex256Value) or(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex256Value) rsh(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex256Value) sub(b Value) Value { panic(todo("")) }
|
||
|
func (v Complex256Value) xor(b Value) Value { panic(todo("")) }
|
||
|
|
||
|
type lvalue struct {
|
||
|
Operand
|
||
|
declarator *Declarator
|
||
|
}
|
||
|
|
||
|
func (o *lvalue) ConvertTo(to Type) (r Operand) { return o.convertTo(nil, nil, to) }
|
||
|
func (o *lvalue) Declarator() *Declarator { return o.declarator }
|
||
|
func (o *lvalue) IsLValue() bool { return true }
|
||
|
|
||
|
func (o *lvalue) IsConst() bool {
|
||
|
if v := o.Value(); v != nil {
|
||
|
return v.IsConst()
|
||
|
}
|
||
|
|
||
|
d := o.Declarator()
|
||
|
return d != nil && (d.Linkage != None || d.IsStatic())
|
||
|
}
|
||
|
|
||
|
func (o *lvalue) convertTo(ctx *context, n Node, to Type) (r Operand) {
|
||
|
return &lvalue{Operand: o.Operand.convertTo(ctx, n, to), declarator: o.declarator}
|
||
|
}
|
||
|
|
||
|
type funcDesignator struct {
|
||
|
Operand
|
||
|
declarator *Declarator
|
||
|
}
|
||
|
|
||
|
func (o *funcDesignator) ConvertTo(to Type) (r Operand) { return o.convertTo(nil, nil, to) }
|
||
|
func (o *funcDesignator) Declarator() *Declarator { return o.declarator }
|
||
|
func (o *funcDesignator) IsLValue() bool { return false }
|
||
|
func (o *funcDesignator) IsConst() bool { return true }
|
||
|
|
||
|
func (o *funcDesignator) convertTo(ctx *context, n Node, to Type) (r Operand) {
|
||
|
return &lvalue{Operand: o.Operand.convertTo(ctx, n, to), declarator: o.declarator}
|
||
|
}
|
||
|
|
||
|
type operand struct {
|
||
|
abi *ABI
|
||
|
typ Type
|
||
|
value Value
|
||
|
offset uintptr
|
||
|
}
|
||
|
|
||
|
func (o *operand) ConvertTo(to Type) (r Operand) { return o.convertTo(nil, nil, to) }
|
||
|
func (o *operand) Declarator() *Declarator { return nil }
|
||
|
func (o *operand) Offset() uintptr { return o.offset }
|
||
|
func (o *operand) IsLValue() bool { return false }
|
||
|
func (o *operand) IsNonZero() bool { return o.value != nil && o.value.IsNonZero() }
|
||
|
func (o *operand) IsZero() bool { return o.value != nil && o.value.IsZero() }
|
||
|
func (o *operand) Type() Type { return o.typ }
|
||
|
func (o *operand) Value() Value { return o.value }
|
||
|
func (o *operand) getABI() *ABI { return o.abi }
|
||
|
|
||
|
// IsAssingmentCompatible implements Operand.
|
||
|
func (o *operand) IsAssingmentCompatible(lhs Type) bool { return lhs.isAssingmentCompatibleOperand(o) }
|
||
|
|
||
|
func (o *operand) IsConst() bool {
|
||
|
if v := o.Value(); v != nil {
|
||
|
return v.IsConst()
|
||
|
}
|
||
|
|
||
|
d := o.Declarator()
|
||
|
return d != nil && (d.Linkage != None || d.IsStatic())
|
||
|
}
|
||
|
|
||
|
// [0]6.3.1.8
|
||
|
//
|
||
|
// Many operators that expect operands of arithmetic type cause conversions and
|
||
|
// yield result types in a similar way. The purpose is to determine a common
|
||
|
// real type for the operands and result. For the specified operands, each
|
||
|
// operand is converted, without change of type domain, to a type whose
|
||
|
// corresponding real type is the common real type. Unless explicitly stated
|
||
|
// otherwise, the common real type is also the corresponding real type of the
|
||
|
// result, whose type domain is the type domain of the operands if they are the
|
||
|
// same, and complex otherwise. This pattern is called the usual arithmetic
|
||
|
// conversions:
|
||
|
func usualArithmeticConversions(ctx *context, n Node, a, b Operand, normalize bool) (Operand, Operand) {
|
||
|
if a.Type().Kind() == Invalid || b.Type().Kind() == Invalid {
|
||
|
return noOperand, noOperand
|
||
|
}
|
||
|
|
||
|
abi := a.getABI()
|
||
|
if !a.Type().IsArithmeticType() {
|
||
|
if ctx != nil {
|
||
|
ctx.errNode(n, "not an arithmetic type: %s", a.Type())
|
||
|
}
|
||
|
return noOperand, noOperand
|
||
|
}
|
||
|
|
||
|
if !b.Type().IsArithmeticType() {
|
||
|
if ctx != nil {
|
||
|
ctx.errNode(n, "not an arithmetic type: %s", b.Type())
|
||
|
}
|
||
|
return noOperand, noOperand
|
||
|
}
|
||
|
|
||
|
if a.Type() == nil || b.Type() == nil {
|
||
|
return a, b
|
||
|
}
|
||
|
|
||
|
if normalize {
|
||
|
a = a.normalize(ctx, n)
|
||
|
b = b.normalize(ctx, n)
|
||
|
}
|
||
|
if a == noOperand || b == noOperand {
|
||
|
return noOperand, noOperand
|
||
|
}
|
||
|
|
||
|
at := a.Type()
|
||
|
bt := b.Type()
|
||
|
cplx := at.IsComplexType() || bt.IsComplexType()
|
||
|
|
||
|
// First, if the corresponding real type of either operand is long
|
||
|
// double, the other operand is converted, without change of type
|
||
|
// domain, to a type whose corresponding real type is long double.
|
||
|
if at.Kind() == ComplexLongDouble || bt.Kind() == ComplexLongDouble || at.Kind() == LongDouble || bt.Kind() == LongDouble {
|
||
|
switch {
|
||
|
case cplx:
|
||
|
return a.convertTo(ctx, n, abi.Type(ComplexLongDouble)), b.convertTo(ctx, n, abi.Type(ComplexLongDouble))
|
||
|
default:
|
||
|
return a.convertTo(ctx, n, abi.Type(LongDouble)), b.convertTo(ctx, n, abi.Type(LongDouble))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Otherwise, if the corresponding real type of either operand is
|
||
|
// double, the other operand is converted, without change of type
|
||
|
// domain, to a type whose corresponding real type is double.
|
||
|
if at.Kind() == ComplexDouble || bt.Kind() == ComplexDouble || at.Kind() == Double || bt.Kind() == Double {
|
||
|
switch {
|
||
|
case cplx:
|
||
|
return a.convertTo(ctx, n, abi.Type(ComplexDouble)), b.convertTo(ctx, n, abi.Type(ComplexDouble))
|
||
|
default:
|
||
|
return a.convertTo(ctx, n, abi.Type(Double)), b.convertTo(ctx, n, abi.Type(Double))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Otherwise, if the corresponding real type of either operand is
|
||
|
// float, the other operand is converted, without change of type
|
||
|
// domain, to a type whose corresponding real type is float.
|
||
|
if at.Kind() == ComplexFloat || bt.Kind() == ComplexFloat || at.Kind() == Float || bt.Kind() == Float {
|
||
|
switch {
|
||
|
case cplx:
|
||
|
return a.convertTo(ctx, n, abi.Type(ComplexFloat)), b.convertTo(ctx, n, abi.Type(ComplexFloat))
|
||
|
default:
|
||
|
return a.convertTo(ctx, n, abi.Type(Float)), b.convertTo(ctx, n, abi.Type(Float))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if cplx {
|
||
|
panic(internalErrorf("TODO %v, %v", at, bt))
|
||
|
}
|
||
|
|
||
|
if !a.Type().IsIntegerType() || !b.Type().IsIntegerType() {
|
||
|
panic(todo(""))
|
||
|
}
|
||
|
|
||
|
// Otherwise, the integer promotions are performed on both operands.
|
||
|
a = a.integerPromotion(ctx, n)
|
||
|
b = b.integerPromotion(ctx, n)
|
||
|
at = a.Type()
|
||
|
bt = b.Type()
|
||
|
|
||
|
// Then the following rules are applied to the promoted operands:
|
||
|
|
||
|
// If both operands have the same type, then no further conversion is
|
||
|
// needed.
|
||
|
if at.Kind() == bt.Kind() {
|
||
|
return a, b
|
||
|
}
|
||
|
|
||
|
// Otherwise, if both operands have signed integer types or both have
|
||
|
// unsigned integer types, the operand with the type of lesser integer
|
||
|
// conversion rank is converted to the type of the operand with greater
|
||
|
// rank.
|
||
|
if abi.isSignedInteger(at.Kind()) == abi.isSignedInteger(bt.Kind()) {
|
||
|
t := a.Type()
|
||
|
if intConvRank[bt.Kind()] > intConvRank[at.Kind()] {
|
||
|
t = b.Type()
|
||
|
}
|
||
|
return a.convertTo(ctx, n, t), b.convertTo(ctx, n, t)
|
||
|
|
||
|
}
|
||
|
|
||
|
// Otherwise, if the operand that has unsigned integer type has rank
|
||
|
// greater or equal to the rank of the type of the other operand, then
|
||
|
// the operand with signed integer type is converted to the type of the
|
||
|
// operand with unsigned integer type.
|
||
|
switch {
|
||
|
case a.Type().IsSignedType(): // b is unsigned
|
||
|
if intConvRank[bt.Kind()] >= intConvRank[a.Type().Kind()] {
|
||
|
return a.convertTo(ctx, n, b.Type()), b
|
||
|
}
|
||
|
case b.Type().IsSignedType(): // a is unsigned
|
||
|
if intConvRank[at.Kind()] >= intConvRank[b.Type().Kind()] {
|
||
|
return a, b.convertTo(ctx, n, a.Type())
|
||
|
}
|
||
|
default:
|
||
|
panic(fmt.Errorf("TODO %v %v", a.Type(), b.Type()))
|
||
|
}
|
||
|
|
||
|
// Otherwise, if the type of the operand with signed integer type can
|
||
|
// represent all of the values of the type of the operand with unsigned
|
||
|
// integer type, then the operand with unsigned integer type is
|
||
|
// converted to the type of the operand with signed integer type.
|
||
|
var signed Type
|
||
|
switch {
|
||
|
case abi.isSignedInteger(at.Kind()): // b is unsigned
|
||
|
signed = a.Type()
|
||
|
if at.Size() > bt.Size() {
|
||
|
return a, b.convertTo(ctx, n, a.Type())
|
||
|
}
|
||
|
case abi.isSignedInteger(bt.Kind()): // a is unsigned
|
||
|
signed = b.Type()
|
||
|
if bt.Size() > at.Size() {
|
||
|
return a.convertTo(ctx, n, b.Type()), b
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// Otherwise, both operands are converted to the unsigned integer type
|
||
|
// corresponding to the type of the operand with signed integer type.
|
||
|
var typ Type
|
||
|
switch signed.Kind() {
|
||
|
case Int:
|
||
|
//TODO if a.IsEnumConst || b.IsEnumConst {
|
||
|
//TODO return a, b
|
||
|
//TODO }
|
||
|
|
||
|
typ = abi.Type(UInt)
|
||
|
case Long:
|
||
|
typ = abi.Type(ULong)
|
||
|
case LongLong:
|
||
|
typ = abi.Type(ULongLong)
|
||
|
default:
|
||
|
panic(todo(""))
|
||
|
}
|
||
|
return a.convertTo(ctx, n, typ), b.convertTo(ctx, n, typ)
|
||
|
}
|
||
|
|
||
|
// [0]6.3.1.1-2
|
||
|
//
|
||
|
// If an int can represent all values of the original type, the value is
|
||
|
// converted to an int; otherwise, it is converted to an unsigned int. These
|
||
|
// are called the integer promotions. All other types are unchanged by the
|
||
|
// integer promotions.
|
||
|
func (o *operand) integerPromotion(ctx *context, n Node) Operand {
|
||
|
t := o.Type()
|
||
|
if t2 := integerPromotion(o.abi, t); t2.Kind() != t.Kind() {
|
||
|
return o.convertTo(ctx, n, t2)
|
||
|
}
|
||
|
|
||
|
return o
|
||
|
}
|
||
|
|
||
|
// [0]6.3.1.1-2
|
||
|
//
|
||
|
// If an int can represent all values of the original type, the value is
|
||
|
// converted to an int; otherwise, it is converted to an unsigned int. These
|
||
|
// are called the integer promotions. All other types are unchanged by the
|
||
|
// integer promotions.
|
||
|
func integerPromotion(abi *ABI, t Type) Type {
|
||
|
// github.com/gcc-mirror/gcc/gcc/testsuite/gcc.c-torture/execute/bf-sign-2.c
|
||
|
//
|
||
|
// This test checks promotion of bitfields. Bitfields
|
||
|
// should be promoted very much like chars and shorts:
|
||
|
//
|
||
|
// Bitfields (signed or unsigned) should be promoted to
|
||
|
// signed int if their value will fit in a signed int,
|
||
|
// otherwise to an unsigned int if their value will fit
|
||
|
// in an unsigned int, otherwise we don't promote them
|
||
|
// (ANSI/ISO does not specify the behavior of bitfields
|
||
|
// larger than an unsigned int).
|
||
|
if t.IsBitFieldType() {
|
||
|
f := t.BitField()
|
||
|
intBits := int(abi.Types[Int].Size) * 8
|
||
|
switch {
|
||
|
case t.IsSignedType():
|
||
|
if f.BitFieldWidth() < intBits-1 {
|
||
|
return abi.Type(Int)
|
||
|
}
|
||
|
default:
|
||
|
if f.BitFieldWidth() < intBits {
|
||
|
return abi.Type(Int)
|
||
|
}
|
||
|
}
|
||
|
return t
|
||
|
}
|
||
|
|
||
|
switch t.Kind() {
|
||
|
case Invalid:
|
||
|
return t
|
||
|
case Char, SChar, UChar, Short, UShort:
|
||
|
return abi.Type(Int)
|
||
|
default:
|
||
|
return t
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (o *operand) convertTo(ctx *context, n Node, to Type) Operand {
|
||
|
if o.Type().Kind() == Invalid {
|
||
|
return o
|
||
|
}
|
||
|
|
||
|
v := o.Value()
|
||
|
r := &operand{abi: o.abi, typ: to, offset: o.offset, value: v}
|
||
|
switch v.(type) {
|
||
|
case nil, *InitializerValue:
|
||
|
return r
|
||
|
}
|
||
|
|
||
|
if o.Type().Kind() == to.Kind() {
|
||
|
return r.normalize(ctx, n)
|
||
|
}
|
||
|
|
||
|
if o.Type().IsIntegerType() {
|
||
|
return o.convertFromInt(ctx, n, to)
|
||
|
}
|
||
|
|
||
|
if to.IsIntegerType() {
|
||
|
return o.convertToInt(ctx, n, to)
|
||
|
}
|
||
|
|
||
|
switch o.Type().Kind() {
|
||
|
case Array:
|
||
|
switch to.Kind() {
|
||
|
case Ptr:
|
||
|
return r
|
||
|
default:
|
||
|
panic(todo("", n.Position()))
|
||
|
}
|
||
|
case ComplexFloat:
|
||
|
v := v.(Complex64Value)
|
||
|
switch to.Kind() {
|
||
|
case ComplexDouble:
|
||
|
r.value = Complex128Value(v)
|
||
|
case Float:
|
||
|
r.value = Float32Value(real(v))
|
||
|
case Double:
|
||
|
r.value = Float64Value(real(v))
|
||
|
case ComplexLongDouble:
|
||
|
panic(todo("", n.Position()))
|
||
|
default:
|
||
|
panic(todo("", n.Position()))
|
||
|
}
|
||
|
case ComplexDouble:
|
||
|
v := v.(Complex128Value)
|
||
|
switch to.Kind() {
|
||
|
case ComplexFloat:
|
||
|
r.value = Complex64Value(v)
|
||
|
case ComplexLongDouble:
|
||
|
//TODO panic(todo("", n.Position()))
|
||
|
r.value = nil
|
||
|
case Float:
|
||
|
r.value = Float32Value(real(v))
|
||
|
case Double:
|
||
|
r.value = Float64Value(real(v))
|
||
|
default:
|
||
|
//TODO panic(todo("", n.Position(), o.Type(), to))
|
||
|
r.value = nil
|
||
|
}
|
||
|
case Float:
|
||
|
v := v.(Float32Value)
|
||
|
switch to.Kind() {
|
||
|
case ComplexFloat:
|
||
|
r.value = Complex64Value(complex(v, 0))
|
||
|
case ComplexDouble:
|
||
|
r.value = Complex128Value(complex(v, 0))
|
||
|
case Double:
|
||
|
r.value = Float64Value(v)
|
||
|
case ComplexLongDouble:
|
||
|
panic(todo("", n.Position()))
|
||
|
case LongDouble:
|
||
|
r.value = &Float128Value{N: big.NewFloat(float64(v))}
|
||
|
case Decimal32, Decimal64, Decimal128:
|
||
|
// ok
|
||
|
default:
|
||
|
panic(todo("695 %s", to.Kind()))
|
||
|
}
|
||
|
case Double:
|
||
|
v := v.(Float64Value)
|
||
|
switch to.Kind() {
|
||
|
case ComplexFloat:
|
||
|
r.value = Complex64Value(complex(v, 0))
|
||
|
case ComplexDouble:
|
||
|
r.value = Complex128Value(complex(v, 0))
|
||
|
case LongDouble:
|
||
|
f := float64(v)
|
||
|
switch {
|
||
|
case math.IsNaN(f):
|
||
|
r.value = &Float128Value{NaN: true}
|
||
|
default:
|
||
|
r.value = &Float128Value{N: big.NewFloat(f)}
|
||
|
}
|
||
|
case Float:
|
||
|
r.value = Float32Value(v)
|
||
|
case ComplexLongDouble:
|
||
|
panic(todo("", n.Position()))
|
||
|
case Vector:
|
||
|
r.value = nil
|
||
|
case Decimal32, Decimal64, Decimal128:
|
||
|
// ok
|
||
|
default:
|
||
|
panic(todo("", to.Kind()))
|
||
|
}
|
||
|
case LongDouble:
|
||
|
v := v.(*Float128Value)
|
||
|
switch to.Kind() {
|
||
|
case Double:
|
||
|
if v.NaN {
|
||
|
r.value = Float64Value(math.NaN())
|
||
|
break
|
||
|
}
|
||
|
|
||
|
d, _ := v.N.Float64()
|
||
|
r.value = Float64Value(d)
|
||
|
case Float:
|
||
|
if v.NaN {
|
||
|
r.value = Float32Value(math.NaN())
|
||
|
break
|
||
|
}
|
||
|
|
||
|
d, _ := v.N.Float64()
|
||
|
r.value = Float32Value(d)
|
||
|
case ComplexLongDouble:
|
||
|
if v.NaN {
|
||
|
r.value = Complex256Value{v, &Float128Value{NaN: true}}
|
||
|
break
|
||
|
}
|
||
|
|
||
|
r.value = Complex256Value{v, &Float128Value{N: big.NewFloat(0)}}
|
||
|
case Decimal32, Decimal64, Decimal128:
|
||
|
// ok
|
||
|
default:
|
||
|
panic(todo("813 %v", to.Kind()))
|
||
|
}
|
||
|
case Ptr:
|
||
|
switch to.Kind() {
|
||
|
case Void:
|
||
|
return noOperand
|
||
|
default:
|
||
|
panic(internalErrorf("%v: %v y-> %v %v", n.Position(), o.Type(), to, to.Kind()))
|
||
|
}
|
||
|
default:
|
||
|
panic(internalErrorf("%v: %v -> %v %v", n.Position(), o.Type(), to, to.Kind()))
|
||
|
}
|
||
|
return r.normalize(ctx, n)
|
||
|
}
|
||
|
|
||
|
type signedSaturationLimit struct {
|
||
|
fmin, fmax float64
|
||
|
min, max int64
|
||
|
}
|
||
|
|
||
|
type unsignedSaturationLimit struct {
|
||
|
fmax float64
|
||
|
max uint64
|
||
|
}
|
||
|
|
||
|
var (
|
||
|
signedSaturationLimits = [...]signedSaturationLimit{
|
||
|
1: {math.Nextafter(math.MinInt32, 0), math.Nextafter(math.MaxInt32, 0), math.MinInt32, math.MaxInt32},
|
||
|
2: {math.Nextafter(math.MinInt32, 0), math.Nextafter(math.MaxInt32, 0), math.MinInt32, math.MaxInt32},
|
||
|
4: {math.Nextafter(math.MinInt32, 0), math.Nextafter(math.MaxInt32, 0), math.MinInt32, math.MaxInt32},
|
||
|
8: {math.Nextafter(math.MinInt64, 0), math.Nextafter(math.MaxInt64, 0), math.MinInt64, math.MaxInt64},
|
||
|
}
|
||
|
|
||
|
unsignedSaturationLimits = [...]unsignedSaturationLimit{
|
||
|
1: {math.Nextafter(math.MaxUint32, 0), math.MaxUint32},
|
||
|
2: {math.Nextafter(math.MaxUint32, 0), math.MaxUint32},
|
||
|
4: {math.Nextafter(math.MaxUint32, 0), math.MaxUint32},
|
||
|
8: {math.Nextafter(math.MaxUint64, 0), math.MaxUint64},
|
||
|
}
|
||
|
)
|
||
|
|
||
|
func (o *operand) convertToInt(ctx *context, n Node, to Type) (r Operand) {
|
||
|
v := o.Value()
|
||
|
switch o.Type().Kind() {
|
||
|
case Float:
|
||
|
v := float64(v.(Float32Value))
|
||
|
switch {
|
||
|
case to.IsSignedType():
|
||
|
limits := &signedSaturationLimits[to.Size()]
|
||
|
if v > limits.fmax {
|
||
|
return (&operand{abi: o.abi, typ: to, value: Int64Value(limits.max)}).normalize(ctx, n)
|
||
|
}
|
||
|
|
||
|
if v < limits.fmin {
|
||
|
return (&operand{abi: o.abi, typ: to, value: Int64Value(limits.min)}).normalize(ctx, n)
|
||
|
}
|
||
|
|
||
|
return (&operand{abi: o.abi, typ: to, value: Int64Value(v)}).normalize(ctx, n)
|
||
|
default:
|
||
|
limits := &unsignedSaturationLimits[to.Size()]
|
||
|
if v > limits.fmax {
|
||
|
return (&operand{abi: o.abi, typ: to, value: Uint64Value(limits.max)}).normalize(ctx, n)
|
||
|
}
|
||
|
|
||
|
return (&operand{abi: o.abi, typ: to, value: Uint64Value(v)}).normalize(ctx, n)
|
||
|
}
|
||
|
case Double:
|
||
|
v := float64(v.(Float64Value))
|
||
|
switch {
|
||
|
case to.IsSignedType():
|
||
|
limits := &signedSaturationLimits[to.Size()]
|
||
|
if v > limits.fmax {
|
||
|
return (&operand{abi: o.abi, typ: to, value: Int64Value(limits.max)}).normalize(ctx, n)
|
||
|
}
|
||
|
|
||
|
if v < limits.fmin {
|
||
|
return (&operand{abi: o.abi, typ: to, value: Int64Value(limits.min)}).normalize(ctx, n)
|
||
|
}
|
||
|
|
||
|
return (&operand{abi: o.abi, typ: to, value: Int64Value(v)}).normalize(ctx, n)
|
||
|
default:
|
||
|
limits := &unsignedSaturationLimits[to.Size()]
|
||
|
if v > limits.fmax {
|
||
|
return (&operand{abi: o.abi, typ: to, value: Uint64Value(limits.max)}).normalize(ctx, n)
|
||
|
}
|
||
|
|
||
|
return (&operand{abi: o.abi, typ: to, value: Uint64Value(v)}).normalize(ctx, n)
|
||
|
}
|
||
|
case LongDouble:
|
||
|
panic(todo("", n.Position()))
|
||
|
case Ptr:
|
||
|
var v uint64
|
||
|
switch x := o.Value().(type) {
|
||
|
case Int64Value:
|
||
|
v = uint64(x)
|
||
|
case Uint64Value:
|
||
|
v = uint64(x)
|
||
|
case *InitializerValue:
|
||
|
return (&operand{abi: o.abi, typ: to})
|
||
|
default:
|
||
|
panic(internalErrorf("%v: %T", n.Position(), x))
|
||
|
}
|
||
|
switch {
|
||
|
case to.IsSignedType():
|
||
|
return (&operand{abi: o.abi, typ: to, value: Int64Value(v)}).normalize(ctx, n)
|
||
|
default:
|
||
|
return (&operand{abi: o.abi, typ: to, value: Uint64Value(v)}).normalize(ctx, n)
|
||
|
}
|
||
|
case Array:
|
||
|
return &operand{abi: o.abi, typ: to}
|
||
|
case Vector:
|
||
|
if o.Type().Size() == to.Size() {
|
||
|
return &operand{abi: o.abi, typ: to}
|
||
|
}
|
||
|
}
|
||
|
if ctx != nil {
|
||
|
ctx.errNode(n, "cannot convert %s to %s", o.Type(), to)
|
||
|
}
|
||
|
return &operand{abi: o.abi, typ: to}
|
||
|
}
|
||
|
|
||
|
func (o *operand) convertFromInt(ctx *context, n Node, to Type) (r Operand) {
|
||
|
var v uint64
|
||
|
switch x := o.Value().(type) {
|
||
|
case Int64Value:
|
||
|
v = uint64(x)
|
||
|
case Uint64Value:
|
||
|
v = uint64(x)
|
||
|
default:
|
||
|
if ctx != nil {
|
||
|
ctx.errNode(n, "conversion to integer: invalid value")
|
||
|
}
|
||
|
return &operand{abi: o.abi, typ: to}
|
||
|
}
|
||
|
|
||
|
if to.IsIntegerType() {
|
||
|
switch {
|
||
|
case to.IsSignedType():
|
||
|
return (&operand{abi: o.abi, typ: to, value: Int64Value(v)}).normalize(ctx, n)
|
||
|
default:
|
||
|
return (&operand{abi: o.abi, typ: to, value: Uint64Value(v)}).normalize(ctx, n)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
switch to.Kind() {
|
||
|
case ComplexFloat:
|
||
|
switch {
|
||
|
case o.Type().IsSignedType():
|
||
|
return (&operand{abi: o.abi, typ: to, value: Complex64Value(complex(float64(int64(v)), 0))}).normalize(ctx, n)
|
||
|
default:
|
||
|
return (&operand{abi: o.abi, typ: to, value: Complex64Value(complex(float64(v), 0))}).normalize(ctx, n)
|
||
|
}
|
||
|
case ComplexDouble:
|
||
|
switch {
|
||
|
case o.Type().IsSignedType():
|
||
|
return (&operand{abi: o.abi, typ: to, value: Complex128Value(complex(float64(int64(v)), 0))}).normalize(ctx, n)
|
||
|
default:
|
||
|
return (&operand{abi: o.abi, typ: to, value: Complex128Value(complex(float64(v), 0))}).normalize(ctx, n)
|
||
|
}
|
||
|
case Float:
|
||
|
switch {
|
||
|
case o.Type().IsSignedType():
|
||
|
return (&operand{abi: o.abi, typ: to, value: Float32Value(float64(int64(v)))}).normalize(ctx, n)
|
||
|
default:
|
||
|
return (&operand{abi: o.abi, typ: to, value: Float32Value(float64(v))}).normalize(ctx, n)
|
||
|
}
|
||
|
case ComplexLongDouble:
|
||
|
panic(todo("", n.Position()))
|
||
|
case Double:
|
||
|
switch {
|
||
|
case o.Type().IsSignedType():
|
||
|
return (&operand{abi: o.abi, typ: to, value: Float64Value(int64(v))}).normalize(ctx, n)
|
||
|
default:
|
||
|
return (&operand{abi: o.abi, typ: to, value: Float64Value(v)}).normalize(ctx, n)
|
||
|
}
|
||
|
case LongDouble:
|
||
|
switch {
|
||
|
case o.Type().IsSignedType():
|
||
|
return (&operand{abi: o.abi, typ: to, value: &Float128Value{N: big.NewFloat(0).SetInt64(int64(v))}}).normalize(ctx, n)
|
||
|
default:
|
||
|
return (&operand{abi: o.abi, typ: to, value: &Float128Value{N: big.NewFloat(0).SetUint64(v)}}).normalize(ctx, n)
|
||
|
}
|
||
|
case Ptr:
|
||
|
return (&operand{abi: o.abi, typ: to, value: Uint64Value(v)}).normalize(ctx, n)
|
||
|
case Struct, Union, Array, Void, Int128, UInt128:
|
||
|
return &operand{abi: o.abi, typ: to}
|
||
|
case Vector:
|
||
|
if o.Type().Size() == to.Size() {
|
||
|
return &operand{abi: o.abi, typ: to}
|
||
|
}
|
||
|
}
|
||
|
if ctx != nil {
|
||
|
ctx.errNode(n, "cannot convert %s to %s", o.Type(), to)
|
||
|
}
|
||
|
return &operand{abi: o.abi, typ: to}
|
||
|
}
|
||
|
|
||
|
func (o *operand) normalize(ctx *context, n Node) (r Operand) {
|
||
|
if o.Type() == nil {
|
||
|
ctx.errNode(n, "operand has unsupported, invalid or incomplete type")
|
||
|
return noOperand
|
||
|
}
|
||
|
|
||
|
if o.Type().IsIntegerType() {
|
||
|
switch {
|
||
|
case o.Type().IsSignedType():
|
||
|
if x, ok := o.value.(Uint64Value); ok {
|
||
|
o.value = Int64Value(x)
|
||
|
}
|
||
|
default:
|
||
|
if x, ok := o.value.(Int64Value); ok {
|
||
|
o.value = Uint64Value(x)
|
||
|
}
|
||
|
}
|
||
|
switch x := o.Value().(type) {
|
||
|
case Int64Value:
|
||
|
if v := convertInt64(int64(x), o.Type(), o.abi); v != int64(x) {
|
||
|
o.value = Int64Value(v)
|
||
|
}
|
||
|
case Uint64Value:
|
||
|
v := uint64(x)
|
||
|
switch o.Type().Size() {
|
||
|
case 1:
|
||
|
v &= 0xff
|
||
|
case 2:
|
||
|
v &= 0xffff
|
||
|
case 4:
|
||
|
v &= 0xffffffff
|
||
|
}
|
||
|
if v != uint64(x) {
|
||
|
o.value = Uint64Value(v)
|
||
|
}
|
||
|
case *InitializerValue, nil:
|
||
|
// ok
|
||
|
default:
|
||
|
panic(internalErrorf("%T %v", x, x))
|
||
|
}
|
||
|
return o
|
||
|
}
|
||
|
|
||
|
switch o.Type().Kind() {
|
||
|
case ComplexFloat:
|
||
|
switch o.Value().(type) {
|
||
|
case Complex64Value, nil:
|
||
|
return o
|
||
|
default:
|
||
|
panic(todo(""))
|
||
|
}
|
||
|
case ComplexDouble:
|
||
|
switch o.Value().(type) {
|
||
|
case Complex128Value, nil:
|
||
|
return o
|
||
|
default:
|
||
|
panic(todo(""))
|
||
|
}
|
||
|
case ComplexLongDouble:
|
||
|
switch o.Value().(type) {
|
||
|
case Complex256Value, nil:
|
||
|
return o
|
||
|
default:
|
||
|
panic(todo("934 %v", o.Type().Kind()))
|
||
|
}
|
||
|
case Float:
|
||
|
switch o.Value().(type) {
|
||
|
case Float32Value, *InitializerValue, nil:
|
||
|
return o
|
||
|
default:
|
||
|
panic(todo(""))
|
||
|
}
|
||
|
case Double:
|
||
|
switch x := o.Value().(type) {
|
||
|
case Float64Value, *InitializerValue, nil:
|
||
|
return o
|
||
|
default:
|
||
|
panic(internalErrorf("%T %v", x, x))
|
||
|
}
|
||
|
case LongDouble:
|
||
|
switch x := o.Value().(type) {
|
||
|
case *Float128Value, nil:
|
||
|
return o
|
||
|
default:
|
||
|
panic(internalErrorf("%T %v TODO980 %v", x, x, n.Position()))
|
||
|
}
|
||
|
case Ptr:
|
||
|
switch o.Value().(type) {
|
||
|
case Int64Value, Uint64Value, *InitializerValue, StringValue, WideStringValue, nil:
|
||
|
return o
|
||
|
default:
|
||
|
panic(todo(""))
|
||
|
}
|
||
|
case Array, Void, Function, Struct, Union, Vector, Decimal32, Decimal64, Decimal128:
|
||
|
return o
|
||
|
case ComplexChar, ComplexInt, ComplexLong, ComplexLongLong, ComplexShort, ComplexUInt, ComplexUShort:
|
||
|
//TOD
|
||
|
if ctx != nil {
|
||
|
ctx.errNode(n, "unsupported type: %s", o.Type())
|
||
|
}
|
||
|
return noOperand
|
||
|
}
|
||
|
panic(internalErrorf("%v, %v", o.Type(), o.Type().Kind()))
|
||
|
}
|
||
|
|
||
|
func convertInt64(n int64, t Type, abi *ABI) int64 {
|
||
|
k := t.Kind()
|
||
|
if k == Enum {
|
||
|
//TODO
|
||
|
}
|
||
|
signed := abi.isSignedInteger(k)
|
||
|
switch sz := abi.size(k); sz {
|
||
|
case 1:
|
||
|
switch {
|
||
|
case signed:
|
||
|
switch {
|
||
|
case int8(n) < 0:
|
||
|
return n | ^math.MaxUint8
|
||
|
default:
|
||
|
return n & math.MaxUint8
|
||
|
}
|
||
|
default:
|
||
|
return n & math.MaxUint8
|
||
|
}
|
||
|
case 2:
|
||
|
switch {
|
||
|
case signed:
|
||
|
switch {
|
||
|
case int16(n) < 0:
|
||
|
return n | ^math.MaxUint16
|
||
|
default:
|
||
|
return n & math.MaxUint16
|
||
|
}
|
||
|
default:
|
||
|
return n & math.MaxUint16
|
||
|
}
|
||
|
case 4:
|
||
|
switch {
|
||
|
case signed:
|
||
|
switch {
|
||
|
case int32(n) < 0:
|
||
|
return n | ^math.MaxUint32
|
||
|
default:
|
||
|
return n & math.MaxUint32
|
||
|
}
|
||
|
default:
|
||
|
return n & math.MaxUint32
|
||
|
}
|
||
|
default:
|
||
|
return n
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func boolValue(b bool) Value {
|
||
|
if b {
|
||
|
return Int64Value(1)
|
||
|
}
|
||
|
|
||
|
return Int64Value(0)
|
||
|
}
|
||
|
|
||
|
type initializer interface {
|
||
|
List() []*Initializer
|
||
|
IsConst() bool
|
||
|
}
|
||
|
|
||
|
type InitializerValue struct {
|
||
|
typ Type
|
||
|
initializer initializer
|
||
|
}
|
||
|
|
||
|
func (v *InitializerValue) List() []*Initializer {
|
||
|
if v == nil || v.initializer == nil {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return v.initializer.List()
|
||
|
}
|
||
|
|
||
|
func (v *InitializerValue) IsConst() bool {
|
||
|
return v != nil && v.initializer != nil && v.initializer.IsConst()
|
||
|
}
|
||
|
func (v *InitializerValue) Type() Type { return v.typ }
|
||
|
func (v *InitializerValue) add(b Value) Value { return nil }
|
||
|
func (v *InitializerValue) and(b Value) Value { return nil }
|
||
|
func (v *InitializerValue) cpl() Value { return nil }
|
||
|
func (v *InitializerValue) div(b Value) Value { return nil }
|
||
|
func (v *InitializerValue) eq(b Value) Value { return nil }
|
||
|
func (v *InitializerValue) ge(b Value) Value { return nil }
|
||
|
func (v *InitializerValue) gt(b Value) Value { return nil }
|
||
|
func (v *InitializerValue) le(b Value) Value { return nil }
|
||
|
func (v *InitializerValue) lsh(b Value) Value { return nil }
|
||
|
func (v *InitializerValue) lt(b Value) Value { return nil }
|
||
|
func (v *InitializerValue) mod(b Value) Value { return nil }
|
||
|
func (v *InitializerValue) mul(b Value) Value { return nil }
|
||
|
func (v *InitializerValue) neg() Value { return nil }
|
||
|
func (v *InitializerValue) neq(b Value) Value { return nil }
|
||
|
func (v *InitializerValue) or(b Value) Value { return nil }
|
||
|
func (v *InitializerValue) rsh(b Value) Value { return nil }
|
||
|
func (v *InitializerValue) sub(b Value) Value { return nil }
|
||
|
func (v *InitializerValue) xor(b Value) Value { return nil }
|
||
|
|
||
|
func (v *InitializerValue) IsNonZero() bool {
|
||
|
if v == nil {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
for _, v := range v.List() {
|
||
|
if !v.AssignmentExpression.Operand.IsZero() {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
func (v *InitializerValue) IsZero() bool {
|
||
|
if v == nil {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
for _, v := range v.List() {
|
||
|
if !v.AssignmentExpression.Operand.IsZero() {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
return true
|
||
|
}
|