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()
|
||||
x := p.compileValue(b, v.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:
|
||||
x := p.compileValue(b, v.X)
|
||||
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 {
|
||||
if v == nil {
|
||||
return b.prog.Null(typ)
|
||||
}
|
||||
switch t := typ.t.(type) {
|
||||
case *types.Basic:
|
||||
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
|
||||
// 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:
|
||||
//
|
||||
// t1 = changetype *int <- IntPtr (t0)
|
||||
@@ -422,9 +422,58 @@ func (b Builder) ChangeType(t Type, x Expr) (ret Expr) {
|
||||
}
|
||||
typ := t.t
|
||||
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:
|
||||
ret.impl = b.impl.CreatePointerCast(x.impl, t.ll, "castPtr")
|
||||
ret.Type = b.prog.Type(typ)
|
||||
return
|
||||
}
|
||||
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) {
|
||||
return b.Call(fn, args...)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user