merge Field/Extract; prog.Tuple/Zero; TypeAssert refactor

This commit is contained in:
xushiwei
2024-05-23 01:10:13 +08:00
parent 6442ab2f20
commit a4c4324ba3
5 changed files with 174 additions and 68 deletions

View File

@@ -93,6 +93,40 @@ func phisExpr(t Type, phis []llvm.Value) Expr {
// -----------------------------------------------------------------------------
func (p Program) Zero(t Type) Expr {
var ret llvm.Value
switch u := t.raw.Type.Underlying().(type) {
case *types.Basic:
kind := u.Kind()
switch {
case kind >= types.Bool && kind <= types.Uintptr:
ret = llvm.ConstInt(p.rawType(u).ll, 0, false)
case kind == types.String:
ret = p.Zero(p.rtType("String")).impl
case kind == types.UnsafePointer:
ret = llvm.ConstPointerNull(p.tyVoidPtr())
case kind <= types.Float64:
ret = llvm.ConstFloat(p.Float64().ll, 0)
case kind == types.Float32:
ret = llvm.ConstFloat(p.Float32().ll, 0)
default:
panic("todo")
}
case *types.Pointer:
return Expr{llvm.ConstNull(t.ll), t}
case *types.Struct:
n := u.NumFields()
flds := make([]llvm.Value, n)
for i := 0; i < n; i++ {
flds[i] = p.Zero(p.rawType(u.Field(i).Type())).impl
}
ret = llvm.ConstStruct(flds, false)
default:
log.Panicln("todo:", u)
}
return Expr{ret, t}
}
// Null returns a null constant expression.
func (p Program) Null(t Type) Expr {
return Expr{llvm.ConstNull(t.ll), t}
@@ -125,12 +159,6 @@ func (p Program) FloatVal(v float64, t Type) Expr {
return Expr{ret, t}
}
func (p Program) ByteVal(v byte) Expr {
t := p.Byte()
ret := llvm.ConstInt(t.ll, uint64(v), false)
return Expr{ret, t}
}
// Val returns a constant expression.
func (p Program) Val(v interface{}) Expr {
switch v := v.(type) {
@@ -941,21 +969,6 @@ func (b Builder) Call(fn Expr, args ...Expr) (ret Expr) {
return
}
// The Extract instruction yields component Index of Tuple.
//
// This is used to access the results of instructions with multiple
// return values, such as Call, TypeAssert, Next, UnOp(ARROW) and
// IndexExpr(Map).
//
// Example printed form:
//
// t1 = extract t0 #1
func (b Builder) Extract(x Expr, index int) (ret Expr) {
ret.Type = b.Prog.toType(x.Type.raw.Type.(*types.Tuple).At(index).Type())
ret.impl = llvm.CreateExtractValue(b.impl, x.impl, index)
return
}
// A Builtin represents a specific use of a built-in function, e.g. len.
//
// Builtins are immutable values. Builtins do not have addresses.
@@ -1009,7 +1022,7 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
ret.Type = prog.Void()
for i, arg := range args {
if ln && i > 0 {
b.InlineCall(b.Pkg.rtFunc("PrintByte"), prog.ByteVal(' '))
b.InlineCall(b.Pkg.rtFunc("PrintByte"), prog.IntVal(' ', prog.Byte()))
}
var fn string
typ := arg.Type
@@ -1049,7 +1062,7 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
b.InlineCall(b.Pkg.rtFunc(fn), arg)
}
if ln {
b.InlineCall(b.Pkg.rtFunc("PrintByte"), prog.ByteVal('\n'))
b.InlineCall(b.Pkg.rtFunc("PrintByte"), prog.IntVal('\n', prog.Byte()))
}
return
case "copy":