llgo/ssa: support string/cstring; panic

This commit is contained in:
xushiwei
2024-04-28 09:55:54 +08:00
parent 510f2f4769
commit 7039cb3bc2
7 changed files with 109 additions and 7 deletions

View File

@@ -82,6 +82,20 @@ func (p Program) Null(t Type) Expr {
return Expr{llvm.ConstNull(t.ll), t}
}
// CStringVal returns a c-style string constant expression.
func (p Program) CStringVal(v string) Expr {
t := p.CString()
return Expr{llvm.ConstString(v, true), t}
}
// StringVal returns string constant expression.
func (p Program) StringVal(v string) Expr {
t := p.String()
cstr := llvm.ConstString(v, true)
// TODO(xsw): cstr => gostring
return Expr{cstr, t}
}
// BoolVal returns a boolean constant expression.
func (p Program) BoolVal(v bool) Expr {
t := p.Bool()
@@ -118,19 +132,22 @@ func (p Program) Val(v interface{}) Expr {
// Const returns a constant expression.
func (b Builder) Const(v constant.Value, typ Type) Expr {
prog := b.prog
if v == nil {
return b.prog.Null(typ)
return prog.Null(typ)
}
switch t := typ.t.(type) {
case *types.Basic:
kind := t.Kind()
switch {
case kind == types.Bool:
return b.prog.BoolVal(constant.BoolVal(v))
return prog.BoolVal(constant.BoolVal(v))
case kind >= types.Int && kind <= types.Uintptr:
if v, exact := constant.Uint64Val(v); exact {
return b.prog.IntVal(v, typ)
return prog.IntVal(v, typ)
}
case kind == types.String:
return prog.StringVal(constant.StringVal(v))
}
}
panic("todo")

View File

@@ -110,12 +110,15 @@ type aProgram struct {
voidType llvm.Type
voidPtrTy llvm.Type
rtIfaceTy llvm.Type
rtSliceTy llvm.Type
rtStringTy llvm.Type
rtIfaceTy llvm.Type
rtSliceTy llvm.Type
anyTy Type
voidTy Type
boolTy Type
cstrTy Type
stringTy Type
uintptrTy Type
intTy Type
f64Ty Type
@@ -170,6 +173,13 @@ func (p Program) rtSlice() llvm.Type {
return p.rtSliceTy
}
func (p Program) rtString() llvm.Type {
if p.rtStringTy.IsNil() {
p.rtStringTy = p.rtType("String").ll
}
return p.rtStringTy
}
// NewPackage creates a new package.
func (p Program) NewPackage(name, pkgPath string) Package {
mod := p.ctx.NewModule(pkgPath)
@@ -177,7 +187,7 @@ func (p Program) NewPackage(name, pkgPath string) Package {
// mod.Finalize()
fns := make(map[string]Function)
gbls := make(map[string]Global)
return &aPackage{mod, fns, gbls, p}
return &aPackage{mod, fns, gbls, p, nil}
}
// Void returns void type.
@@ -196,6 +206,20 @@ func (p Program) Bool() Type {
return p.boolTy
}
func (p Program) CString() Type {
if p.cstrTy == nil { // *int8
p.cstrTy = p.Type(types.NewPointer(types.Typ[types.Int8]))
}
return p.cstrTy
}
func (p Program) String() Type {
if p.stringTy == nil {
p.stringTy = p.Type(types.Typ[types.String])
}
return p.stringTy
}
// Any returns any type.
func (p Program) Any() Type {
if p.anyTy == nil {
@@ -243,6 +267,8 @@ type aPackage struct {
fns map[string]Function
vars map[string]Global
prog Program
abort Function
}
type Package = *aPackage
@@ -280,6 +306,13 @@ func (p Package) FuncOf(name string) Function {
return p.fns[name]
}
func (p Package) rtAbort() Function {
if p.abort == nil {
p.abort = p.NewFunc("abort", types.NewSignatureType(nil, nil, nil, nil, nil, false))
}
return p.abort
}
func (p Package) rtFunc(fnName string) Expr {
fn := p.prog.runtime().Lookup(fnName).(*types.Func)
name := FullName(fn.Pkg(), fnName)

View File

@@ -68,6 +68,15 @@ func (b Builder) SetBlock(blk BasicBlock) Builder {
return b
}
// Panic emits a panic instruction.
func (b Builder) Panic(v Expr) {
if debugInstr {
log.Printf("Panic %v\n", v.impl)
}
pkg := b.fn.pkg
b.Call(pkg.rtAbort().Expr)
}
// Return emits a return instruction.
func (b Builder) Return(results ...Expr) {
if debugInstr {

View File

@@ -237,6 +237,7 @@ func (p Program) toLLVMType(typ types.Type) Type {
case types.Complex64:
case types.Complex128:
case types.String:
return &aType{p.rtString(), typ, vkString}
case types.UnsafePointer:
return &aType{p.tyVoidPtr(), typ, vkPtr}
}