modernc.org/qbe@v0.0.9/cc/literal.go (about) 1 // Copyright 2021 The QBE Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package cc // import "modernc.org/qbe/cc" 6 7 import ( 8 "fmt" 9 "math" 10 "math/big" 11 12 "modernc.org/cc/v3" 13 "modernc.org/token" 14 ) 15 16 func (g *gen) intLit(n cc.Node, v cc.Value, op, from, t cc.Type) operand { 17 if t == nil { 18 panic(todo("", n.Position())) 19 } 20 21 switch t.Kind() { 22 case cc.Float, cc.Double: 23 return g.floatLitFromValue(n, v, from, t) 24 } 25 26 var u uint64 27 switch x := v.(type) { 28 case cc.Int64Value: 29 u = uint64(x) 30 case cc.Uint64Value: 31 u = uint64(x) 32 default: 33 panic(todo("%v: %T(%[2]v)", n.Position(), x)) 34 } 35 36 r := g.newVal(nil) 37 g.w("\n%s", g.line(n)) 38 g.w("\n\t%s =%s copy %d", r, g.baseType(n, t), u) 39 return r 40 } 41 42 func (g *gen) floatLitFromValue(n cc.Node, v cc.Value, from, t cc.Type) operand { 43 g.w("\n%s", g.line(n)) 44 switch x := v.(type) { 45 case cc.Float64Value: 46 r := g.newVal(nil) 47 g.w("\n\t%s =d copy %d", r, math.Float64bits(float64(x))) 48 return g.convert(n, r, from, t) 49 case cc.Float32Value: 50 r := g.newVal(nil) 51 g.w("\n\t%s =s copy %d", r, math.Float32bits(float32(x))) 52 return g.convert(n, r, from, t) 53 case cc.Int64Value: 54 switch t.Kind() { 55 case cc.Float, cc.Double: 56 r := g.newVal(nil) 57 g.w("\n\t%s =%s sltof %d", r, g.baseType(n, t), x) 58 return r 59 default: 60 panic(todo("%v: %v", n.Position(), t.Kind())) 61 } 62 case *cc.Float128Value: 63 r := g.newVal(nil) 64 g.w("\n\t%s =ld copy %s", r, g.longDoubleString(n, x)) 65 return g.convert(n, r, from, t) 66 default: 67 panic(todo("%v: %T(%[2]v)", n.Position(), x)) 68 } 69 } 70 71 func (g *gen) longDoubleString(n cc.Node, v cc.Value) string { 72 switch x := v.(type) { 73 case *cc.Float128Value: 74 switch { 75 case x.NaN: 76 return "ld_nan" 77 case x.N.IsInf(): 78 switch { 79 case x.N.Sign() > 0: 80 return "ld_inf" 81 default: 82 return "ld_-inf" 83 } 84 default: 85 m := big.NewFloat(0).SetPrec(uint(g.cLongDouble.Size()) * 8).Set(x.N) 86 return "ld_" + m.Text('p', 0) 87 } 88 case cc.Float64Value: 89 switch { 90 case math.IsNaN(float64(x)): 91 return "ld_nan" 92 case math.IsInf(float64(x), 1): 93 return "ld_inf" 94 case math.IsInf(float64(x), -1): 95 return "ld_-inf" 96 default: 97 return fmt.Sprintf("ld_%g", x) 98 } 99 case cc.Float32Value: 100 switch { 101 case math.IsNaN(float64(x)): 102 return "ld_nan" 103 case math.IsInf(float64(x), 1): 104 return "ld_inf" 105 case math.IsInf(float64(x), -1): 106 return "ld_-inf" 107 default: 108 return fmt.Sprintf("ld_%g", x) 109 } 110 case cc.Int64Value: 111 return fmt.Sprintf("ld_%v", x) 112 default: 113 panic(todo("%v: %T(%[2]v)", pos(n), x)) 114 } 115 } 116 117 func pos(n cc.Node) (r token.Position) { 118 if n == nil { 119 return r 120 } 121 122 return n.Position() 123 } 124 125 func (g *gen) floatLit(n *cc.PrimaryExpression, t cc.Type) operand { 126 return g.floatLitFromValue(n, n.Operand.Value(), n.Operand.Type(), t) 127 } 128 129 func (g *gen) longStringLit(n cc.Node, v cc.Value) operand { 130 switch x := v.(type) { 131 case cc.WideStringValue: 132 s := cc.StringID(x).String() 133 r, ok := g.longStringLiterals[s] 134 if !ok { 135 r = g.newStaticGlobalArray() 136 if g.longStringLiterals == nil { 137 g.longStringLiterals = map[string]operand{} 138 } 139 g.longStringLiterals[s] = r 140 } 141 return r 142 default: 143 panic(todo("%v: %T", n.Position(), x)) 144 } 145 } 146 147 func (g *gen) stringLit(n cc.Node, v cc.Value) operand { 148 switch x := v.(type) { 149 case cc.StringValue: 150 s := cc.StringID(x).String() 151 r, ok := g.stringLiterals[s] 152 if !ok { 153 r = g.newStaticGlobalArray() 154 if g.stringLiterals == nil { 155 g.stringLiterals = map[string]operand{} 156 } 157 g.stringLiterals[s] = r 158 } 159 return r 160 default: 161 panic(todo("%v: %T", n.Position(), x)) 162 } 163 }