diff options
Diffstat (limited to 'vendor/modernc.org/cc/v3/operand.go')
-rw-r--r-- | vendor/modernc.org/cc/v3/operand.go | 1337 |
1 files changed, 1337 insertions, 0 deletions
diff --git a/vendor/modernc.org/cc/v3/operand.go b/vendor/modernc.org/cc/v3/operand.go new file mode 100644 index 00000000..24c46616 --- /dev/null +++ b/vendor/modernc.org/cc/v3/operand.go @@ -0,0 +1,1337 @@ +// 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 +} |