llgo/ssa: ChangeType, Convert
This commit is contained in:
@@ -300,6 +300,10 @@ func (p *context) compileInstrAndValue(b llssa.Builder, iv instrAndValue) (ret l
|
|||||||
t := v.Type()
|
t := v.Type()
|
||||||
x := p.compileValue(b, v.X)
|
x := p.compileValue(b, v.X)
|
||||||
ret = b.ChangeType(p.prog.Type(t), x)
|
ret = b.ChangeType(p.prog.Type(t), x)
|
||||||
|
case *ssa.Convert:
|
||||||
|
t := v.Type()
|
||||||
|
x := p.compileValue(b, v.X)
|
||||||
|
ret = b.Convert(p.prog.Type(t), x)
|
||||||
case *ssa.FieldAddr:
|
case *ssa.FieldAddr:
|
||||||
x := p.compileValue(b, v.X)
|
x := p.compileValue(b, v.X)
|
||||||
ret = b.FieldAddr(x, v.Field)
|
ret = b.FieldAddr(x, v.Field)
|
||||||
|
|||||||
58
ssa/expr.go
58
ssa/expr.go
@@ -110,6 +110,9 @@ func (p Program) Val(v interface{}) Expr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b Builder) Const(v constant.Value, typ Type) Expr {
|
func (b Builder) Const(v constant.Value, typ Type) Expr {
|
||||||
|
if v == nil {
|
||||||
|
return b.prog.Null(typ)
|
||||||
|
}
|
||||||
switch t := typ.t.(type) {
|
switch t := typ.t.(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
kind := t.Kind()
|
kind := t.Kind()
|
||||||
@@ -410,9 +413,6 @@ func (b Builder) Alloc(t Type, heap bool) (ret Expr) {
|
|||||||
// types in the type set of X.Type() have a value-preserving type
|
// types in the type set of X.Type() have a value-preserving type
|
||||||
// change to all types in the type set of Type().
|
// change to all types in the type set of Type().
|
||||||
//
|
//
|
||||||
// Pos() returns the ast.CallExpr.Lparen, if the instruction arose
|
|
||||||
// from an explicit conversion in the source.
|
|
||||||
//
|
|
||||||
// Example printed form:
|
// Example printed form:
|
||||||
//
|
//
|
||||||
// t1 = changetype *int <- IntPtr (t0)
|
// t1 = changetype *int <- IntPtr (t0)
|
||||||
@@ -422,9 +422,58 @@ func (b Builder) ChangeType(t Type, x Expr) (ret Expr) {
|
|||||||
}
|
}
|
||||||
typ := t.t
|
typ := t.t
|
||||||
switch typ.(type) {
|
switch typ.(type) {
|
||||||
|
default:
|
||||||
|
ret.impl = b.impl.CreateBitCast(x.impl, t.ll, "bitCast")
|
||||||
|
ret.Type = b.prog.Type(typ)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Convert instruction yields the conversion of value X to type
|
||||||
|
// Type(). One or both of those types is basic (but possibly named).
|
||||||
|
//
|
||||||
|
// A conversion may change the value and representation of its operand.
|
||||||
|
// Conversions are permitted:
|
||||||
|
// - between real numeric types.
|
||||||
|
// - between complex numeric types.
|
||||||
|
// - between string and []byte or []rune.
|
||||||
|
// - between pointers and unsafe.Pointer.
|
||||||
|
// - between unsafe.Pointer and uintptr.
|
||||||
|
// - from (Unicode) integer to (UTF-8) string.
|
||||||
|
//
|
||||||
|
// A conversion may imply a type name change also.
|
||||||
|
//
|
||||||
|
// Conversions may to be to or from a type parameter. All types in
|
||||||
|
// the type set of X.Type() can be converted to all types in the type
|
||||||
|
// set of Type().
|
||||||
|
//
|
||||||
|
// This operation cannot fail dynamically.
|
||||||
|
//
|
||||||
|
// Conversions of untyped string/number/bool constants to a specific
|
||||||
|
// representation are eliminated during SSA construction.
|
||||||
|
//
|
||||||
|
// Pos() returns the ast.CallExpr.Lparen, if the instruction arose
|
||||||
|
// from an explicit conversion in the source.
|
||||||
|
//
|
||||||
|
// Example printed form:
|
||||||
|
//
|
||||||
|
// t1 = convert []byte <- string (t0)
|
||||||
|
func (b Builder) Convert(t Type, x Expr) (ret Expr) {
|
||||||
|
typ := t.t
|
||||||
|
ret.Type = b.prog.Type(typ)
|
||||||
|
switch und := typ.Underlying().(type) {
|
||||||
|
case *types.Basic:
|
||||||
|
kind := und.Kind()
|
||||||
|
switch {
|
||||||
|
case kind >= types.Int && kind <= types.Uintptr:
|
||||||
|
ret.impl = b.impl.CreateIntCast(x.impl, t.ll, "castInt")
|
||||||
|
return
|
||||||
|
case kind == types.UnsafePointer:
|
||||||
|
ret.impl = b.impl.CreatePointerCast(x.impl, t.ll, "castPtr")
|
||||||
|
return
|
||||||
|
}
|
||||||
case *types.Pointer:
|
case *types.Pointer:
|
||||||
ret.impl = b.impl.CreatePointerCast(x.impl, t.ll, "castPtr")
|
ret.impl = b.impl.CreatePointerCast(x.impl, t.ll, "castPtr")
|
||||||
ret.Type = b.prog.Type(typ)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
panic("todo")
|
panic("todo")
|
||||||
@@ -534,6 +583,7 @@ func (b Builder) TypeAssert(x Expr, assertedTyp Type, commaOk bool) (ret Expr) {
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// TODO(xsw): make inline call
|
||||||
func (b Builder) InlineCall(fn Expr, args ...Expr) (ret Expr) {
|
func (b Builder) InlineCall(fn Expr, args ...Expr) (ret Expr) {
|
||||||
return b.Call(fn, args...)
|
return b.Call(fn, args...)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user