llgo/ssa,runtime: Slice
This commit is contained in:
@@ -7,8 +7,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
s := c.String("Hi\n")
|
s := c.Str("Hi\n")
|
||||||
s2 := c.Alloca(4)
|
s2 := c.Alloca(4)
|
||||||
c.Memcpy(s2, unsafe.Pointer(s), 4)
|
c.Memcpy(s2, unsafe.Pointer(s), 4)
|
||||||
c.Printf(c.String("%s"), s2)
|
c.Printf(c.Str("%s"), s2)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,5 +9,5 @@ func incVal(a any) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
c.Printf(c.String("Hello %d\n"), incVal(100))
|
c.Printf(c.Str("Hello %d\n"), incVal(100))
|
||||||
}
|
}
|
||||||
|
|||||||
16
cl/_testcgo/sum/in.go
Normal file
16
cl/_testcgo/sum/in.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
func sum(args ...int) (ret int) {
|
||||||
|
for _, v := range args {
|
||||||
|
ret += v
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
c.Printf(c.Str("Hello %d\n"), sum(1, 2, 3, 4))
|
||||||
|
}
|
||||||
0
cl/_testcgo/sum/out.ll
Normal file
0
cl/_testcgo/sum/out.ll
Normal file
@@ -10,5 +10,5 @@ func foo() {
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
foo()
|
foo()
|
||||||
c.Printf(c.String("Hello\n"))
|
c.Printf(c.Str("Hello\n"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -275,7 +275,7 @@ func cstr(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
|
|||||||
if c, ok := args[0].(*ssa.Const); ok {
|
if c, ok := args[0].(*ssa.Const); ok {
|
||||||
if v := c.Value; v.Kind() == constant.String {
|
if v := c.Value; v.Kind() == constant.String {
|
||||||
sv := constant.StringVal(v)
|
sv := constant.StringVal(v)
|
||||||
return b.CString(sv)
|
return b.CStr(sv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -373,7 +373,18 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
|||||||
if _, ok := p.isVArgs(vx); ok { // varargs: this is a varargs slice
|
if _, ok := p.isVArgs(vx); ok { // varargs: this is a varargs slice
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
panic("todo")
|
var low, high, max llssa.Expr
|
||||||
|
x := p.compileValue(b, vx)
|
||||||
|
if v.Low != nil {
|
||||||
|
low = p.compileValue(b, v.Low)
|
||||||
|
}
|
||||||
|
if v.High != nil {
|
||||||
|
high = p.compileValue(b, v.High)
|
||||||
|
}
|
||||||
|
if v.Max != nil {
|
||||||
|
max = p.compileValue(b, v.Max)
|
||||||
|
}
|
||||||
|
ret = b.Slice(x, low, high, max)
|
||||||
case *ssa.Alloc:
|
case *ssa.Alloc:
|
||||||
t := v.Type().(*types.Pointer)
|
t := v.Type().(*types.Pointer)
|
||||||
if p.checkVArgs(v, t) { // varargs: this is a varargs allocation
|
if p.checkVArgs(v, t) { // varargs: this is a varargs allocation
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ func testCompile(t *testing.T, src, expected string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFromTestcgo(t *testing.T) {
|
func TestFromTestcgo(t *testing.T) {
|
||||||
cltest.FromDir(t, "", "./_testcgo", true)
|
cltest.FromDir(t, "sum", "./_testcgo", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFromTestdata(t *testing.T) {
|
func TestFromTestdata(t *testing.T) {
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ const (
|
|||||||
LLGoPackage = "decl"
|
LLGoPackage = "decl"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:linkname String llgo.cstr
|
//go:linkname Str llgo.cstr
|
||||||
func String(string) *int8
|
func Str(string) *int8
|
||||||
|
|
||||||
//go:linkname Alloca llgo.alloca
|
//go:linkname Alloca llgo.alloca
|
||||||
func Alloca(size uintptr) unsafe.Pointer
|
func Alloca(size uintptr) unsafe.Pointer
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ import (
|
|||||||
|
|
||||||
// Slice is the runtime representation of a slice.
|
// Slice is the runtime representation of a slice.
|
||||||
type Slice struct {
|
type Slice struct {
|
||||||
array unsafe.Pointer
|
data unsafe.Pointer
|
||||||
len int
|
len int
|
||||||
cap int
|
cap int
|
||||||
}
|
}
|
||||||
|
|
||||||
// NilSlice returns a nil slice.
|
// NilSlice returns a nil slice.
|
||||||
@@ -34,4 +34,14 @@ func NilSlice() Slice {
|
|||||||
return Slice{nil, 0, 0}
|
return Slice{nil, 0, 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewSlice creates a new slice.
|
||||||
|
func NewSlice(data unsafe.Pointer, len, cap int) Slice {
|
||||||
|
return Slice{data, len, cap}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SliceLen returns the length of a slice.
|
||||||
|
func SliceLen(s Slice) int {
|
||||||
|
return s.len
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
58
ssa/expr.go
58
ssa/expr.go
@@ -35,6 +35,11 @@ type Expr struct {
|
|||||||
Type
|
Type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsNil checks if the expression is nil or not.
|
||||||
|
func (v Expr) IsNil() bool {
|
||||||
|
return v.Type == nil
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// TypeOf returns the type of the expression.
|
// TypeOf returns the type of the expression.
|
||||||
func (v Expr) TypeOf() types.Type {
|
func (v Expr) TypeOf() types.Type {
|
||||||
@@ -156,9 +161,9 @@ func (b Builder) Const(v constant.Value, typ Type) Expr {
|
|||||||
panic("todo")
|
panic("todo")
|
||||||
}
|
}
|
||||||
|
|
||||||
// CString returns a c-style string constant expression.
|
// CStr returns a c-style string constant expression.
|
||||||
func (b Builder) CString(v string) Expr {
|
func (b Builder) CStr(v string) Expr {
|
||||||
return Expr{llvm.CreateGlobalStringPtr(b.impl, v), b.Prog.CString()}
|
return Expr{llvm.CreateGlobalStringPtr(b.impl, v), b.Prog.CStr()}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -392,6 +397,43 @@ func (b Builder) IndexAddr(x, idx Expr) Expr {
|
|||||||
return Expr{llvm.CreateInBoundsGEP(b.impl, telem.ll, x.impl, indices), pt}
|
return Expr{llvm.CreateInBoundsGEP(b.impl, telem.ll, x.impl, indices), pt}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The Slice instruction yields a slice of an existing string, slice
|
||||||
|
// or *array X between optional integer bounds Low and High.
|
||||||
|
//
|
||||||
|
// Dynamically, this instruction panics if X evaluates to a nil *array
|
||||||
|
// pointer.
|
||||||
|
//
|
||||||
|
// Type() returns string if the type of X was string, otherwise a
|
||||||
|
// *types.Slice with the same element type as X.
|
||||||
|
//
|
||||||
|
// Pos() returns the ast.SliceExpr.Lbrack if created by a x[:] slice
|
||||||
|
// operation, the ast.CompositeLit.Lbrace if created by a literal, or
|
||||||
|
// NoPos if not explicit in the source (e.g. a variadic argument slice).
|
||||||
|
//
|
||||||
|
// Example printed form:
|
||||||
|
//
|
||||||
|
// t1 = slice t0[1:]
|
||||||
|
func (b Builder) Slice(x, low, high, max Expr) (ret Expr) {
|
||||||
|
if debugInstr {
|
||||||
|
log.Printf("Slice %v, %v, %v\n", x.impl, low.impl, high.impl)
|
||||||
|
}
|
||||||
|
prog := b.Prog
|
||||||
|
pkg := b.fn.pkg
|
||||||
|
switch t := x.t.Underlying().(type) {
|
||||||
|
case *types.Pointer:
|
||||||
|
telem := t.Elem()
|
||||||
|
switch te := telem.Underlying().(type) {
|
||||||
|
case *types.Array:
|
||||||
|
ret.Type = prog.Type(types.NewSlice(te.Elem()))
|
||||||
|
if low.IsNil() && high.IsNil() && max.IsNil() {
|
||||||
|
n := prog.Val(int(te.Len()))
|
||||||
|
return b.InlineCall(pkg.rtFunc("NewSlice"), n, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
// The Alloc instruction reserves space for a variable of the given type,
|
// The Alloc instruction reserves space for a variable of the given type,
|
||||||
// zero-initializes it, and yields its address.
|
// zero-initializes it, and yields its address.
|
||||||
//
|
//
|
||||||
@@ -713,6 +755,16 @@ func (b Builder) Call(fn Expr, args ...Expr) (ret Expr) {
|
|||||||
// `fn` indicates the function: one of the built-in functions from the
|
// `fn` indicates the function: one of the built-in functions from the
|
||||||
// Go spec (excluding "make" and "new").
|
// Go spec (excluding "make" and "new").
|
||||||
func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
|
func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
|
||||||
|
switch fn {
|
||||||
|
case "len":
|
||||||
|
if len(args) == 1 {
|
||||||
|
arg := args[0]
|
||||||
|
switch arg.t.Underlying().(type) {
|
||||||
|
case *types.Slice:
|
||||||
|
return b.InlineCall(b.fn.pkg.rtFunc("SliceLen"), arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
panic("todo")
|
panic("todo")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -225,7 +225,7 @@ func (p Program) Bool() Type {
|
|||||||
return p.boolTy
|
return p.boolTy
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) CString() Type {
|
func (p Program) CStr() Type {
|
||||||
if p.cstrTy == nil { // *int8
|
if p.cstrTy == nil { // *int8
|
||||||
p.cstrTy = p.Type(types.NewPointer(types.Typ[types.Int8]))
|
p.cstrTy = p.Type(types.NewPointer(types.Typ[types.Int8]))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,6 +104,10 @@ type aType struct {
|
|||||||
|
|
||||||
type Type = *aType
|
type Type = *aType
|
||||||
|
|
||||||
|
func (p Program) Slice(typ Type) Type {
|
||||||
|
return p.Type(types.NewSlice(typ.t))
|
||||||
|
}
|
||||||
|
|
||||||
func (p Program) Pointer(typ Type) Type {
|
func (p Program) Pointer(typ Type) Type {
|
||||||
return p.Type(types.NewPointer(typ.t))
|
return p.Type(types.NewPointer(typ.t))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user