From ba8e48be38c78885b6ba8095afdc129a37e9ecae Mon Sep 17 00:00:00 2001 From: xushiwei Date: Sun, 19 May 2024 07:28:56 +0800 Subject: [PATCH 1/2] README: matplotlib --- README.md | 1 + py/matplotlib/pyplot/llgo_autogen.lla | Bin 0 -> 560 bytes py/matplotlib/pyplot/pyplot.go | 22 ++++++++++++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 py/matplotlib/pyplot/llgo_autogen.lla create mode 100644 py/matplotlib/pyplot/pyplot.go diff --git a/README.md b/README.md index 62dbc435..03ed9f28 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ And you can import any Python library into `llgo` through a program called `llpy * [numpy](https://pkg.go.dev/github.com/goplus/llgo/py/numpy) * [pandas](https://pkg.go.dev/github.com/goplus/llgo/py/pandas) * [pytorch](https://pkg.go.dev/github.com/goplus/llgo/py/torch) +* [matplotlib](https://pkg.go.dev/github.com/goplus/llgo/py/matplotlib) Here is an example using the Python `math` library: diff --git a/py/matplotlib/pyplot/llgo_autogen.lla b/py/matplotlib/pyplot/llgo_autogen.lla new file mode 100644 index 0000000000000000000000000000000000000000..b0fa8f5b49d54c23300c3ffd1fa777b5d31d20fd GIT binary patch literal 560 zcmWIWW@Zs#U|`^2P-5R45h(q4VIm6y13!ZdLrzY5etcqSNq%~2o?cE)Xb2|* z^Mkt{X^()ow1S&~k>x8;HQ0c)Q|@~oHV`;||8uy^QA75nudhwtsQBjKbX$&ntEZTp z%=$2Eiis@W$NKNTl4s{>oVz*wna95SyMI5q#d;?)a&gq%L%cl2Z|A?(5!xp4eA|&- zQp(TDV)Bl&epij^w_3a+k~cCnTRmjgwG}-2A}^bbzc41BEi7B!Wm*mdK4(+w@!WdN?clL2&ga|3WBMQTmi8VgW;4iG<$PN8h35^i zzv*f1N{mMCbt!U8pL`T~c1^jwc*d`n;>AC{ZdRD(6&6zdUMTp`sp#di=G?pbN?uyh zr>y40rtg0f1zZ48cilfwx?8mWTluv~p68ssf9xwtet&kl;)L&Q z_n*scWRhdX6^#(-mGjO<%~cW3Z##MOke;2 DIHu}M literal 0 HcmV?d00001 diff --git a/py/matplotlib/pyplot/pyplot.go b/py/matplotlib/pyplot/pyplot.go new file mode 100644 index 00000000..cd3afeb2 --- /dev/null +++ b/py/matplotlib/pyplot/pyplot.go @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package pyplot + +import "github.com/goplus/llgo/py" + +//llgo:linkname Style py.style +var Style *py.Object From 04428c5aedb7074882dd197f76c450593320a9a1 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Sun, 19 May 2024 07:57:12 +0800 Subject: [PATCH 2/2] llgo/ssa: pkg.PyLoadModSyms (source code stablility) --- cl/_testpy/max/out.ll | 8 ++++---- cl/compile.go | 28 +--------------------------- ssa/decl.go | 43 ++++++++++++++++++++++++++++++++++++++++--- ssa/stmt_builder.go | 4 ++-- 4 files changed, 47 insertions(+), 36 deletions(-) diff --git a/cl/_testpy/max/out.ll b/cl/_testpy/max/out.ll index 15100e26..14e5618c 100644 --- a/cl/_testpy/max/out.ll +++ b/cl/_testpy/max/out.ll @@ -8,9 +8,9 @@ source_filename = "main" @__llgo_py.builtins.print = linkonce global ptr null @__llgo_py.builtins.iter = linkonce global ptr null @__llgo_py.builtins = external global ptr -@0 = private unnamed_addr constant [4 x i8] c"max\00", align 1 -@1 = private unnamed_addr constant [6 x i8] c"print\00", align 1 -@2 = private unnamed_addr constant [5 x i8] c"iter\00", align 1 +@0 = private unnamed_addr constant [5 x i8] c"iter\00", align 1 +@1 = private unnamed_addr constant [4 x i8] c"max\00", align 1 +@2 = private unnamed_addr constant [6 x i8] c"print\00", align 1 define void @main.init() { _llgo_0: @@ -21,7 +21,7 @@ _llgo_1: ; preds = %_llgo_0 store i1 true, ptr @"main.init$guard", align 1 call void @"github.com/goplus/llgo/py/std.init"() %1 = load ptr, ptr @__llgo_py.builtins, align 8 - call void (ptr, ...) @llgoLoadPyModSyms(ptr %1, ptr @0, ptr @__llgo_py.builtins.max, ptr @1, ptr @__llgo_py.builtins.print, ptr @2, ptr @__llgo_py.builtins.iter, ptr null) + call void (ptr, ...) @llgoLoadPyModSyms(ptr %1, ptr @0, ptr @__llgo_py.builtins.iter, ptr @1, ptr @__llgo_py.builtins.max, ptr @2, ptr @__llgo_py.builtins.print, ptr null) br label %_llgo_2 _llgo_2: ; preds = %_llgo_1, %_llgo_0 diff --git a/cl/compile.go b/cl/compile.go index 90840f4d..6974ee81 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -339,13 +339,6 @@ func (p *context) funcOf(fn *ssa.Function) (aFn llssa.Function, pyFn llssa.PyObj return } -func modOf(name string) string { - if pos := strings.LastIndexByte(name, '.'); pos > 0 { - return name[:pos] - } - return "" -} - func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, doMainInit, doModInit bool) llssa.BasicBlock { var last int var pyModInit bool @@ -361,26 +354,7 @@ func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, do } else { // TODO(xsw): confirm pyMod don't need to call LoadPyModSyms p.inits = append(p.inits, func() { - if objs := pkg.PyObjs(); len(objs) > 0 { - mods := make(map[string][]llssa.PyObjRef) - for name, obj := range objs { - modName := modOf(name) - mods[modName] = append(mods[modName], obj) - } - - // sort by module name - modNames := make([]string, 0, len(mods)) - for modName := range mods { - modNames = append(modNames, modName) - } - sort.Strings(modNames) - - b.SetBlockEx(ret, llssa.AfterInit) - for _, modName := range modNames { - objs := mods[modName] - b.PyLoadModSyms(modName, objs...) - } - } + pkg.PyLoadModSyms(b, ret) }) } } else if doMainInit { diff --git a/ssa/decl.go b/ssa/decl.go index 7a30aac3..ee8b3d12 100644 --- a/ssa/decl.go +++ b/ssa/decl.go @@ -19,7 +19,9 @@ package ssa import ( "go/types" "log" + "sort" "strconv" + "strings" "github.com/goplus/llvm" ) @@ -350,9 +352,44 @@ func (p Package) PyObjOf(name string) PyObjRef { return p.pyobjs[name] } -// PyObjs returns all used python objects in this project. -func (p Package) PyObjs() map[string]PyObjRef { - return p.pyobjs +// PyLoadModSyms loads module symbols used in this package. +func (p Package) PyLoadModSyms(b Builder, ret BasicBlock) { + objs := p.pyobjs + n := len(objs) + if n == 0 { + return + } + + names := make([]string, 0, n) + for name := range objs { + names = append(names, name) + } + sort.Strings(names) + + mods := make(map[string][]PyObjRef) + modNames := make([]string, 0, 8) + lastMod := "" + for _, name := range names { + modName := modOf(name) + mods[modName] = append(mods[modName], objs[name]) + if modName != lastMod { + modNames = append(modNames, modName) + lastMod = modName + } + } + + b.SetBlockEx(ret, afterInit) + for _, modName := range modNames { + objs := mods[modName] + b.PyLoadModSyms(modName, objs...) + } +} + +func modOf(name string) string { + if pos := strings.LastIndexByte(name, '.'); pos > 0 { + return name[:pos] + } + panic("unreachable") } // ----------------------------------------------------------------------------- diff --git a/ssa/stmt_builder.go b/ssa/stmt_builder.go index 579e744b..ae91fee6 100644 --- a/ssa/stmt_builder.go +++ b/ssa/stmt_builder.go @@ -77,7 +77,7 @@ type InsertPoint int const ( AtEnd InsertPoint = iota AtStart - AfterInit + afterInit ) // SetBlockEx sets blk as current basic block and pos as its insert point. @@ -90,7 +90,7 @@ func (b Builder) SetBlockEx(blk BasicBlock, pos InsertPoint) Builder { b.impl.SetInsertPointAtEnd(blk.impl) case AtStart: b.impl.SetInsertPointBefore(blk.impl.FirstInstruction()) - case AfterInit: + case afterInit: b.impl.SetInsertPointBefore(instrAfterInit(blk.impl)) default: panic("SetBlockEx: invalid pos")