diff --git a/c/c.go b/c/c.go index 4c5f4e13..a38958ed 100644 --- a/c/c.go +++ b/c/c.go @@ -46,7 +46,7 @@ type integer interface { func Str(string) *Char // llgo:link Advance llgo.advance -func Advance[PtrT any](ptr PtrT, offset int) PtrT { return ptr } +func Advance[PtrT any, I integer](ptr PtrT, offset I) PtrT { return ptr } // llgo:link Index llgo.index func Index[T any, I integer](ptr *T, offset I) T { return *ptr } @@ -66,6 +66,9 @@ func Free(ptr Pointer) //go:linkname Memcpy C.memcpy func Memcpy(dst, src Pointer, n uintptr) Pointer +//go:linkname Memmove C.memmove +func Memmove(dst, src Pointer, n uintptr) Pointer + //go:linkname Memset C.memset func Memset(s Pointer, c Int, n uintptr) Pointer diff --git a/internal/abi/type.go b/internal/abi/type.go index c3f0f9ed..3e7250b9 100644 --- a/internal/abi/type.go +++ b/internal/abi/type.go @@ -170,6 +170,24 @@ type MapType struct { Flags uint32 } +// Note: flag values must match those used in the TMAP case +// in ../cmd/compile/internal/reflectdata/reflect.go:writeType. +func (mt *MapType) IndirectKey() bool { // store ptr to key instead of key itself + return mt.Flags&1 != 0 +} +func (mt *MapType) IndirectElem() bool { // store ptr to elem instead of elem itself + return mt.Flags&2 != 0 +} +func (mt *MapType) ReflexiveKey() bool { // true if k==k for all keys + return mt.Flags&4 != 0 +} +func (mt *MapType) NeedKeyUpdate() bool { // true if we need to update key on an overwrite + return mt.Flags&8 != 0 +} +func (mt *MapType) HashMightPanic() bool { // true if hash function might panic + return mt.Flags&16 != 0 +} + type PtrType struct { Type Elem *Type // pointer element (pointed at) type diff --git a/py/README.md b/py/README.md index 16d3bbc3..32479857 100644 --- a/py/README.md +++ b/py/README.md @@ -19,10 +19,10 @@ To run the demos in directory `_demo`, you need to set the `LLGO_LIB_PYTHON` env export LLGO_LIB_PYTHON=/foo/bar/python3.12 ``` -For example, `/opt/homebrew/Frameworks/Python.framework/Versions/3.12/libpython3.12.dylib` is a typical python lib location under macOS. So we should set it like this: +For example, `/opt/homebrew/Frameworks/Python.framework/Versions/3.12/lib/libpython3.12.dylib` is a typical python lib location under macOS. So we should set it like this: ```sh -export LLGO_LIB_PYTHON=/opt/homebrew/Frameworks/Python.framework/Versions/3.12/python3.12 +export LLGO_LIB_PYTHON=/opt/homebrew/Frameworks/Python.framework/Versions/3.12/lib/python3.12 ``` Then you can run the demos in directory `_demo`: diff --git a/ssa/abi/abi.go b/ssa/abi/abi.go index 4841b895..28e065b3 100644 --- a/ssa/abi/abi.go +++ b/ssa/abi/abi.go @@ -159,6 +159,10 @@ func (b *Builder) TypeName(t types.Type) (ret string, pub bool) { return "_llgo_any", true } return b.InterfaceName(t) + case *types.Map: + key, pub1 := b.TypeName(t.Key()) + elem, pub2 := b.TypeName(t.Elem()) + return fmt.Sprintf("map[%s]%s", key, elem), pub1 && pub2 } log.Panicf("todo: %T\n", t) return diff --git a/ssa/datastruct.go b/ssa/datastruct.go index aa09b8c0..819e6d21 100644 --- a/ssa/datastruct.go +++ b/ssa/datastruct.go @@ -365,3 +365,50 @@ func (b Builder) MapUpdate(m, k, v Expr) { } // ----------------------------------------------------------------------------- + +// The Range instruction yields an iterator over the domain and range +// of X, which must be a string or map. +// +// Elements are accessed via Next. +// +// Type() returns an opaque and degenerate "rangeIter" type. +// +// Pos() returns the ast.RangeStmt.For. +// +// Example printed form: +// +// t0 = range "hello":string +func (b Builder) Range(x Expr) Expr { + switch x.kind { + case vkString: + return b.InlineCall(b.Pkg.rtFunc("NewStringIter"), x) + } + panic("todo") +} + +// The Next instruction reads and advances the (map or string) +// iterator Iter and returns a 3-tuple value (ok, k, v). If the +// iterator is not exhausted, ok is true and k and v are the next +// elements of the domain and range, respectively. Otherwise ok is +// false and k and v are undefined. +// +// Components of the tuple are accessed using Extract. +// +// The IsString field distinguishes iterators over strings from those +// over maps, as the Type() alone is insufficient: consider +// map[int]rune. +// +// Type() returns a *types.Tuple for the triple (ok, k, v). +// The types of k and/or v may be types.Invalid. +// +// Example printed form: +// +// t1 = next t0 +func (b Builder) Next(iter Expr, isString bool) (ret Expr) { + if isString { + return b.InlineCall(b.Pkg.rtFunc("StringIterNext"), iter) + } + panic("todo") +} + +// ----------------------------------------------------------------------------- diff --git a/ssa/expr.go b/ssa/expr.go index 7c0c3155..6b58f08a 100644 --- a/ssa/expr.go +++ b/ssa/expr.go @@ -742,53 +742,6 @@ func castPtr(b llvm.Builder, x llvm.Value, t llvm.Type) llvm.Value { // ----------------------------------------------------------------------------- -// The Range instruction yields an iterator over the domain and range -// of X, which must be a string or map. -// -// Elements are accessed via Next. -// -// Type() returns an opaque and degenerate "rangeIter" type. -// -// Pos() returns the ast.RangeStmt.For. -// -// Example printed form: -// -// t0 = range "hello":string -func (b Builder) Range(x Expr) Expr { - switch x.kind { - case vkString: - return b.InlineCall(b.Pkg.rtFunc("NewStringIter"), x) - } - panic("todo") -} - -// The Next instruction reads and advances the (map or string) -// iterator Iter and returns a 3-tuple value (ok, k, v). If the -// iterator is not exhausted, ok is true and k and v are the next -// elements of the domain and range, respectively. Otherwise ok is -// false and k and v are undefined. -// -// Components of the tuple are accessed using Extract. -// -// The IsString field distinguishes iterators over strings from those -// over maps, as the Type() alone is insufficient: consider -// map[int]rune. -// -// Type() returns a *types.Tuple for the triple (ok, k, v). -// The types of k and/or v may be types.Invalid. -// -// Example printed form: -// -// t1 = next t0 -func (b Builder) Next(iter Expr, isString bool) (ret Expr) { - if isString { - return b.InlineCall(b.Pkg.rtFunc("StringIterNext"), iter) - } - panic("todo") -} - -// ----------------------------------------------------------------------------- - // The MakeClosure instruction yields a closure value whose code is // Fn and whose free variables' values are supplied by Bindings. //