Compare commits

..

236 Commits

Author SHA1 Message Date
xushiwei
92f56a2f90 Merge pull request #106 from xushiwei/mod
llvm v0.7.5
2024-05-05 12:15:08 +08:00
xushiwei
926e2d4a2e llvm v0.7.5 2024-05-05 12:12:57 +08:00
xushiwei
e9153defee Merge pull request #105 from xushiwei/q
cl: compile ssa.Function bugfix
2024-05-04 18:00:56 +08:00
xushiwei
889fc8b6a9 TestErrCompileValue 2024-05-04 17:59:28 +08:00
xushiwei
9b9da3133d cl: compile ssa.Function bugfix 2024-05-04 17:46:33 +08:00
xushiwei
1c8edb0387 Merge pull request #104 from xushiwei/q
llgo/ssa: checkExpr to auto convert funcPtr into closure
2024-05-04 17:28:35 +08:00
xushiwei
c0ef1598c9 llgo/ssa: checkExpr to auto convert funcPtr into closure 2024-05-04 17:25:13 +08:00
xushiwei
bc1acee6f5 Merge pull request #103 from xushiwei/q
closure
2024-05-04 07:57:00 +08:00
xushiwei
9f25d73826 intgen: todo 2024-05-04 07:53:53 +08:00
xushiwei
f07a62d136 toLLVMFunc: closure 2024-05-04 07:47:18 +08:00
xushiwei
06d6b447e4 ClosureF, ClosureData 2024-05-04 07:21:40 +08:00
xushiwei
1cff02e4cc closure 2024-05-04 07:21:07 +08:00
xushiwei
809a400f57 llgo/ssa: Call to support closure 2024-05-03 23:49:52 +08:00
xushiwei
f1bb42f554 llgo/ssa: SizeOf, MakeSlice, VoidPtr 2024-05-03 23:10:02 +08:00
xushiwei
4fd8f84536 Merge pull request #102 from xushiwei/q
cl: qsort example
2024-05-03 20:04:48 +08:00
xushiwei
223c24450e NewClosure 2024-05-03 20:02:33 +08:00
xushiwei
8a7ddf4dc2 cl: qsort example 2024-05-03 19:59:56 +08:00
xushiwei
08217e5a5a Merge pull request #101 from xushiwei/q
TestTypes
2024-05-03 19:23:02 +08:00
xushiwei
424dbd9261 TestTypes 2024-05-03 19:20:30 +08:00
xushiwei
b615ada2c3 Merge pull request #99 from visualfc/slice3
update ssa.Slice
2024-05-03 19:09:29 +08:00
xushiwei
20a47873d0 Merge pull request #100 from xushiwei/q
llgo/ssa: vkFuncDecl/vkFuncPtr/vkClosure
2024-05-03 19:08:12 +08:00
xushiwei
d87ce1a124 cl: qsort 2024-05-03 19:05:49 +08:00
xushiwei
91d012d33d TestCvtCType 2024-05-03 19:02:17 +08:00
xushiwei
330cb22351 TestErrCompileInstrOrValue 2024-05-03 18:35:14 +08:00
xushiwei
236debab33 CFuncPtr.Hash 2024-05-03 18:02:09 +08:00
xushiwei
13a1c8ac4b github.com/goplus/llgo/internal/typeutil.Map 2024-05-03 17:39:37 +08:00
xushiwei
29fad7b397 TestCFuncPtr 2024-05-03 17:08:44 +08:00
xushiwei
8eeac8a26d cvtCType bugfix 2024-05-03 17:03:12 +08:00
xushiwei
133d41d748 llgo/ssa: CType, CFuncDecl 2024-05-03 16:51:01 +08:00
visualfc
d444123062 update ssa.Slice 2024-05-03 16:30:33 +08:00
xushiwei
4a5c8d3fbb cl: call llgo/ssa.CType/CFuncDecl 2024-05-03 16:00:31 +08:00
xushiwei
afd3d40348 llgo/ssa: vkFuncDecl/vkFuncPtr/vkClosure 2024-05-03 15:40:24 +08:00
xushiwei
85da86a4f1 Merge pull request #98 from xushiwei/q
cl: link go name
2024-05-03 00:00:42 +08:00
xushiwei
72d4f0f7f8 Merge pull request #97 from visualfc/cap
ssa: builtin len&cap
2024-05-02 23:58:12 +08:00
xushiwei
192b479f18 cl: link go name 2024-05-02 23:14:12 +08:00
visualfc
3e6dfa3c05 ssa: builtin len&cap 2024-05-02 16:26:45 +08:00
xushiwei
5bd28a1e9e Merge pull request #96 from xushiwei/q
runtime: stringTracef
2024-05-02 13:17:02 +08:00
xushiwei
a23a2601e4 runtime: stringTracef 2024-05-02 13:10:41 +08:00
xushiwei
3220b629c7 Merge pull request #95 from xushiwei/q
runtime: StringCat; llgo/ssa: aggregateValue
2024-05-02 12:41:37 +08:00
xushiwei
9cf122c31a runtime: StringCat; llgo/ssa: aggregateValue 2024-05-02 12:39:25 +08:00
xushiwei
75d513a78a Merge pull request #94 from xushiwei/q
cl: compilePhis; llgo/ssa: phi.AddIncoming
2024-05-02 11:51:49 +08:00
xushiwei
3cbe4aac87 TestUserdefExpr 2024-05-02 11:38:05 +08:00
xushiwei
3e47a977e4 update llvm 2024-05-02 11:31:33 +08:00
xushiwei
40855c2d2a cl: compilePhis; llgo/ssa: phi.AddIncoming 2024-05-02 11:27:02 +08:00
xushiwei
b2319eda66 Merge pull request #92 from visualfc/index
implement ssa.index
2024-05-02 10:35:32 +08:00
visualfc
5c5b8e62e5 implement ssa.index 2024-05-02 09:26:56 +08:00
xushiwei
fbb1f89ab3 phisExpr as an AggregateVal 2024-05-02 07:56:52 +08:00
xushiwei
25b104cf13 llgo/ssa: PhisExpr 2024-05-02 07:37:31 +08:00
xushiwei
be1599b418 Merge pull request #93 from xushiwei/q
runtime: StringCat; builtin: llgo.advance
2024-05-02 00:08:04 +08:00
xushiwei
d462e548b1 TestErrAdvance 2024-05-02 00:04:37 +08:00
xushiwei
df1e4708f5 builtin: llgo.advance 2024-05-01 23:57:19 +08:00
xushiwei
cf02f4a34f runtime: StringCat 2024-05-01 22:00:34 +08:00
xushiwei
480cf09177 Merge pull request #91 from xushiwei/q
cl: support stdin/stdout/stderr
2024-05-01 21:26:20 +08:00
xushiwei
52a64a7770 cl: initLinknameByDoc 2024-05-01 21:18:28 +08:00
xushiwei
8d3cb246c2 cl: linkname of varName 2024-05-01 20:56:51 +08:00
xushiwei
8f15fd45f2 initLinkname: support var 2024-05-01 20:33:46 +08:00
xushiwei
afd02b3d78 cl: to support stdin/stdout/stderr 2024-05-01 20:05:28 +08:00
xushiwei
aa1d0b307b Merge pull request #90 from xushiwei/q
llvm v0.7.3
2024-05-01 18:15:05 +08:00
xushiwei
8a09d8b442 update llvm 2024-05-01 18:12:42 +08:00
xushiwei
7b99470bfa llvm v0.7.3 2024-05-01 18:11:58 +08:00
xushiwei
30192da7cf Merge pull request #89 from xushiwei/q
build: make empty runtime.init if no runtime needed
2024-05-01 17:45:55 +08:00
xushiwei
66337e0975 build: make empty runtime.init if no runtime needed 2024-05-01 17:44:12 +08:00
xushiwei
6e4a44438b Merge pull request #88 from xushiwei/q
llgo/ssa: builder.Alloc sizeof(t) bugfix
2024-05-01 17:01:51 +08:00
xushiwei
3cc3b864af fix Alloc size 2024-05-01 16:59:42 +08:00
xushiwei
62f6542ca9 llgo/ssa: builder.Alloc sizeof(t) bugfix 2024-05-01 16:56:26 +08:00
xushiwei
8c25848e1b Merge pull request #87 from xushiwei/q
cl: callRuntimeInit; runtime: TracePanic; cl: _testrt/gblarray (todo)
2024-05-01 16:10:09 +08:00
xushiwei
e112d8277f cl: _testrt/gblarray 2024-05-01 16:06:49 +08:00
xushiwei
014d0262da build: fix link runtime multiple times 2024-05-01 13:30:13 +08:00
xushiwei
8ae97f73d0 debug why runtime.Basic doesn't work 2024-05-01 12:32:09 +08:00
xushiwei
666808b427 cl: callRuntimeInit; runtime: TracePanic 2024-05-01 11:03:52 +08:00
xushiwei
f208db48a1 Merge pull request #86 from xushiwei/q
runtime: MakeSmallMap
2024-05-01 07:40:24 +08:00
xushiwei
673b9d9a5c runtime.MakeSmallMap 2024-05-01 07:37:38 +08:00
xushiwei
ed8ffb228b runtime: MakeMap 2024-05-01 07:26:51 +08:00
xushiwei
d5a3ff6fb9 Merge pull request #85 from xushiwei/q
llgo/ssa: allocaCStr; runtime: String
2024-04-30 23:21:49 +08:00
xushiwei
d3fddfb634 mv _testcgo => _testrt 2024-04-30 23:18:18 +08:00
xushiwei
f7a54e3377 llgo/ssa: builder.Str bugfix; runtime: NewString 2024-04-30 18:42:40 +08:00
xushiwei
d62bf858dd llgo/ssa: Go const string 2024-04-30 18:37:31 +08:00
xushiwei
ae0906d322 llgo/ssa: allocaCStr; runtime: String 2024-04-30 18:22:56 +08:00
xushiwei
c6cb2931e1 Merge pull request #84 from xushiwei/q
llgo/ssa: Slice, IndexAddr bugfix
2024-04-30 16:22:01 +08:00
xushiwei
0eac576171 Merge pull request #83 from visualfc/error
build: buildAllPkgs dump error
2024-04-30 16:21:09 +08:00
xushiwei
0ee96db260 IndexAddr: default as ptr 2024-04-30 16:19:25 +08:00
xushiwei
40a9e00d4c llgo/ssa: Slice, IndexAddr bugfix 2024-04-30 16:15:36 +08:00
visualfc
d8615330ad build: buildAllPkgs dump error 2024-04-30 15:58:01 +08:00
xushiwei
02afd1d73a Merge pull request #82 from visualfc/slice
ssa: fix newSlice.type & const
2024-04-30 14:33:12 +08:00
visualfc
4eedb4fb69 cltest: SetRuntime 2024-04-30 14:16:46 +08:00
visualfc
2d6869bdbd ssa: fix newSlice.type & const 2024-04-30 14:14:28 +08:00
xushiwei
c0a9848cfb Merge pull request #81 from xushiwei/q
llgo/ssa,runtime: Slice; llgo/ssa: phi node
2024-04-30 11:36:11 +08:00
xushiwei
40cc7b2a85 llgen runtime 2024-04-30 11:31:39 +08:00
xushiwei
dfaae24fea update llvm 2024-04-30 11:26:40 +08:00
xushiwei
839ad8ba2b cl: _testcgo/sum 2024-04-30 11:19:42 +08:00
xushiwei
e757c66354 llgo/ssa: phi node 2024-04-30 10:34:10 +08:00
xushiwei
3ec6da002a Merge remote-tracking branch 'gop/main' into q 2024-04-30 08:27:57 +08:00
xushiwei
190b029154 Merge pull request #80 from visualfc/const
cl: compileValue check types.Default for const
2024-04-30 08:26:23 +08:00
xushiwei
0bfc269652 llgo/ssa,runtime: Slice 2024-04-30 08:23:55 +08:00
visualfc
b5961f0807 cl/_testdata: add untyped test 2024-04-30 08:14:08 +08:00
visualfc
a792e312db cl: compileValue check types.Default for const 2024-04-30 08:13:39 +08:00
xushiwei
04f81f3dbb Merge pull request #79 from xushiwei/q
ignore .DS_Store
2024-04-29 23:43:03 +08:00
xushiwei
91401c4571 ignore .DS_Store 2024-04-29 23:42:37 +08:00
xushiwei
18fe26e853 Merge pull request #77 from visualfc/float
ssa: builder.const add float
2024-04-29 23:09:22 +08:00
xushiwei
f895ca1fe6 Merge pull request #78 from xushiwei/q
llgo/ssa: MakeInterface
2024-04-29 23:04:59 +08:00
xushiwei
ad28ed3154 cl: _testcgo/any 2024-04-29 22:58:25 +08:00
xushiwei
f64abf37ab llgo/ssa: MakeInterface 2024-04-29 22:57:40 +08:00
visualfc
acc5de8d14 ssa: builder.const add float 2024-04-29 22:19:08 +08:00
xushiwei
85bb1302ca Merge pull request #76 from xushiwei/q
llgen bugfix
2024-04-29 20:52:58 +08:00
xushiwei
fc893ba498 llgen bugfix 2024-04-29 20:51:27 +08:00
xushiwei
7527b326d7 Merge pull request #75 from xushiwei/q
cl: support llgo.cstr
2024-04-29 19:01:01 +08:00
xushiwei
a6d31ad8b8 TestErrAlloca 2024-04-29 18:55:09 +08:00
xushiwei
664c3fcce3 compileInstrOrValue 2024-04-29 18:46:13 +08:00
xushiwei
e1d1d6a2d9 llgo/ssa: unreachable 2024-04-29 18:33:02 +08:00
xushiwei
8c1b8ad945 update llvm 2024-04-29 18:12:15 +08:00
xushiwei
ae5efdf16c disable ArrayAlloca 2024-04-29 18:01:03 +08:00
xushiwei
2b82af519c llgo/ssa: Alloca, ArrayAlloca 2024-04-29 17:58:10 +08:00
xushiwei
7a347d4563 update llvm 2024-04-29 14:39:37 +08:00
xushiwei
1610894a80 llgo/ssa: b.CString 2024-04-29 14:34:26 +08:00
xushiwei
4eb2ddaf15 cl: support llgo.cstr 2024-04-29 13:59:06 +08:00
xushiwei
99a86d8d4e Merge pull request #74 from xushiwei/q
build: skip PkgDeclOnly; cl: skip init if PkgNoInit
2024-04-29 12:04:07 +08:00
xushiwei
637db665c3 TestPkgKindOf 2024-04-29 11:58:48 +08:00
xushiwei
bb1da81a01 build: skip PkgDeclOnly 2024-04-29 11:34:59 +08:00
xushiwei
d4ddc61a9f cl: TestPkgNoInit/TestPkgKind 2024-04-29 10:06:47 +08:00
xushiwei
6ebbc92c4f runtime.ll 2024-04-29 09:53:48 +08:00
xushiwei
b45172bef1 cl: pkgKind = normal/noinit/decl 2024-04-29 09:51:32 +08:00
xushiwei
695d3f3327 Merge pull request #73 from xushiwei/q
llvm v0.7.2
2024-04-29 03:50:05 +08:00
xushiwei
7979cfcb06 update llgo_autogen.ll 2024-04-29 03:45:52 +08:00
xushiwei
2986cb0c5f llvm v0.7.2 2024-04-29 03:43:38 +08:00
xushiwei
5a175955a9 Merge pull request #72 from xushiwei/q
llgo/ssa: use b.CreateUnreachable to panic
2024-04-29 03:40:05 +08:00
xushiwei
cb507f43a7 llgo/ssa: use b.CreateUnreachable to panic 2024-04-29 03:36:19 +08:00
xushiwei
8b148d72c2 Merge pull request #71 from xushiwei/q
cl: don't need to compile alias type
2024-04-29 02:58:22 +08:00
xushiwei
616596e571 cl: don't need to compile alias type 2024-04-29 02:56:21 +08:00
xushiwei
2849fe4841 Merge pull request #70 from xushiwei/q
llgo/ssa: llvmSignature/castPtr/castInt bugfix; link: runtime
2024-04-29 01:44:01 +08:00
xushiwei
98065e80d0 TestRuntime 2024-04-29 01:42:00 +08:00
xushiwei
286b520d83 build: better error messages 2024-04-29 01:34:21 +08:00
xushiwei
769b93a277 build: mark need runtime 2024-04-29 00:49:17 +08:00
xushiwei
c30ed1b3c8 llgo/ssa: llvmSignature/castPtr/castInt bugfix; link: runtime 2024-04-29 00:16:00 +08:00
xushiwei
78d7f984d1 Merge pull request #69 from xushiwei/q
llgen: smart fname of outFile (llgo_autogen.ll or out.ll)
2024-04-28 23:12:15 +08:00
xushiwei
e88f7e6659 llgen: smart fname of outFile (llgo_autogen.ll or out.ll) 2024-04-28 23:07:59 +08:00
xushiwei
e8ff879943 Merge pull request #68 from xushiwei/q
cl: compileInstrOrValue bugfix
2024-04-28 22:40:36 +08:00
xushiwei
f09d5bd155 TestIsAny, TestIntVal 2024-04-28 22:38:04 +08:00
xushiwei
53e73fc622 x 2024-04-28 22:24:03 +08:00
xushiwei
ba94d6f04e cl: compileInstrOrValue bugfix 2024-04-28 22:20:46 +08:00
xushiwei
449f91ab14 Merge pull request #67 from xushiwei/q
llgo/ssa.SetRuntime: prevent multiple loading of runtime
2024-04-28 14:02:54 +08:00
xushiwei
70623dd554 llgo/ssa.SetRuntime: prevent multiple loading of runtime 2024-04-28 14:00:29 +08:00
xushiwei
35dc6dcd85 Merge pull request #66 from xushiwei/q
runtime
2024-04-28 12:24:59 +08:00
xushiwei
41dfafe957 TestRuntime 2024-04-28 12:22:56 +08:00
xushiwei
2cc1bdee19 llgo/ssa: pkg.NewFunc bugfix 2024-04-28 12:09:47 +08:00
xushiwei
eb4146d80d llgo/ssa: Alloc bugfix (heap) 2024-04-28 10:39:19 +08:00
xushiwei
0d68066086 runtime: MakeAnyString 2024-04-28 10:29:06 +08:00
xushiwei
7039cb3bc2 llgo/ssa: support string/cstring; panic 2024-04-28 09:55:54 +08:00
xushiwei
510f2f4769 runtime: Alloc 2024-04-28 07:08:33 +08:00
xushiwei
5415f68c1b llgo/ssa: Alloc, BinOp(vkPtr) 2024-04-28 07:08:01 +08:00
xushiwei
475f0fa2ff llgo/ssa: ChangeType, Convert 2024-04-28 06:23:21 +08:00
xushiwei
c58b1140d8 Merge pull request #65 from xushiwei/q
llgo build/install/run: link runtime
2024-04-28 06:21:57 +08:00
xushiwei
c97c1e97b9 llgo build/install/run: link runtime 2024-04-27 22:13:40 +08:00
xushiwei
ba3d82e5e5 Merge pull request #64 from xushiwei/q
cl: _testcgo/any
2024-04-27 21:35:17 +08:00
xushiwei
d432899b42 TestAny, TestDelayExpr 2024-04-27 21:32:48 +08:00
xushiwei
08da38a609 cl: _testcgo/any 2024-04-27 20:45:55 +08:00
xushiwei
6a3eb2f2f9 ssa: rtIface, rtSlice 2024-04-27 18:13:16 +08:00
xushiwei
6a02c3ac4c llgo/ssa: rtType, rtFunc 2024-04-27 17:39:25 +08:00
xushiwei
f1761c0c9c llgo/internal/runtime 2024-04-27 13:57:21 +08:00
xushiwei
39076c75cf Merge pull request #63 from xushiwei/q
cl: _testcgo/typalias
2024-04-27 10:10:16 +08:00
xushiwei
3be8cacc24 cl: _testcgo/typalias 2024-04-27 10:06:59 +08:00
xushiwei
46a9df47e4 cl: _testcgo/typalias 2024-04-27 08:33:49 +08:00
xushiwei
d44a31cc62 Merge pull request #62 from xushiwei/q
cl: _testcgo/struct
2024-04-27 08:21:00 +08:00
xushiwei
00b2fd1479 fix TestNamedStruct 2024-04-27 08:17:46 +08:00
xushiwei
5f08e7a612 cl: _testcgo/struct 2024-04-27 07:47:10 +08:00
xushiwei
5c8725373a Merge pull request #61 from xushiwei/q
llgo build/install/run: ParseArgs bugfix
2024-04-27 06:43:11 +08:00
xushiwei
c455f6e730 SkipFlagArgs 2024-04-27 06:41:24 +08:00
xushiwei
3cc83b8ec4 llgo build/install/run: SkipArgs bugfix 2024-04-27 06:39:09 +08:00
xushiwei
f74de76d70 Merge pull request #60 from xushiwei/q
llgo build bugfix: when len(initial)==1
2024-04-26 20:30:22 +08:00
xushiwei
ea8ddc6451 llgo build bugfix: when len(initial)==1 2024-04-26 20:28:06 +08:00
xushiwei
5f36c37cf2 Merge pull request #59 from xushiwei/q
llgo clean
2024-04-26 20:10:15 +08:00
xushiwei
2ad2873278 llgo clean 2024-04-26 20:06:54 +08:00
xushiwei
3855895808 Merge pull request #58 from xushiwei/q
cl: go:linkname specifies call convention by C.xxx
2024-04-26 13:27:55 +08:00
xushiwei
f86cd74a98 cl: go:linkname specifies call convention by C.xxx 2024-04-26 13:09:24 +08:00
xushiwei
1e6ecbadcd Merge pull request #57 from xushiwei/q
cl: fake libc
2024-04-26 05:53:19 +08:00
xushiwei
33716a3385 cl: fake libc 2024-04-26 05:51:30 +08:00
xushiwei
252f0bf967 Merge pull request #56 from xushiwei/q
cl: TestImport/TestVarOf
2024-04-26 05:40:50 +08:00
xushiwei
2c3e1d1055 cl: TestImport/TestVarOf 2024-04-26 05:39:15 +08:00
xushiwei
aafa639bf1 Merge pull request #55 from xushiwei/q
llgo: use -Wno-override-module to disable clang warning
2024-04-26 05:09:25 +08:00
xushiwei
815a8a74fc llgo: use -Wno-override-module to disable clang warning 2024-04-26 05:05:59 +08:00
xushiwei
840ea80e20 Merge pull request #54 from xushiwei/q
llgo run: strlen
2024-04-26 04:47:24 +08:00
xushiwei
773ae2c8c6 llgo run: strlen 2024-04-26 04:44:49 +08:00
xushiwei
4aadb4b86f Merge pull request #53 from xushiwei/q
cl: _testcgo/strlen
2024-04-26 03:28:08 +08:00
xushiwei
91d1d71f6d ssa: temp disable Finalize; cl: decls sort by name 2024-04-26 03:25:11 +08:00
xushiwei
a3d6a94600 cl: _testcgo/strlen 2024-04-26 02:40:36 +08:00
xushiwei
43ae7a23b2 cl: _testcgo/strlen - todo 2024-04-26 02:05:49 +08:00
xushiwei
b6005886fa Merge pull request #52 from xushiwei/q
cl: _testdata/ptrmthd
2024-04-26 00:34:59 +08:00
xushiwei
28dd34a136 cl: _testdata/ptrmthd 2024-04-26 00:31:02 +08:00
xushiwei
3a3c263203 Merge pull request #51 from xushiwei/q
cl: _testdata/method
2024-04-25 21:47:36 +08:00
xushiwei
87b7ecd1d6 cl: _testdata/method 2024-04-25 21:44:23 +08:00
xushiwei
f5a309b5ad Merge pull request #50 from xushiwei/q
cl: _testdata/printval
2024-04-25 14:50:30 +08:00
xushiwei
0f00add402 cl: pathOf(pkg) 2024-04-25 14:30:02 +08:00
xushiwei
1014fa53dd cl: _testdata/printval 2024-04-25 14:25:14 +08:00
xushiwei
04568835bd Merge pull request #49 from xushiwei/q
codecov
2024-04-25 07:39:44 +08:00
xushiwei
e4f8edc07c codecov 2024-04-25 07:37:04 +08:00
xushiwei
a8533d1677 Merge pull request #48 from xushiwei/q
llgo/cl/cltest
2024-04-25 07:31:31 +08:00
xushiwei
edcb66afb7 llgo/cl/cltest 2024-04-25 07:29:45 +08:00
xushiwei
bc1821e7a5 Merge pull request #47 from xushiwei/q
llgo run
2024-04-25 01:43:04 +08:00
xushiwei
3f49fe9e98 llgo run 2024-04-25 01:41:44 +08:00
xushiwei
6aee76be72 Merge pull request #46 from xushiwei/q
llgo build/install: a.out generated; verbose
2024-04-25 00:55:53 +08:00
xushiwei
a2c6e5d7fc llgo install: /appName 2024-04-25 00:53:42 +08:00
xushiwei
cbaf9e21b2 llgo build/install: a.out generated 2024-04-25 00:14:02 +08:00
xushiwei
81b3add443 build.Do: verbose 2024-04-24 14:27:14 +08:00
xushiwei
c3e681a7b3 Merge pull request #45 from xushiwei/q
llgo build/install
2024-04-24 12:01:06 +08:00
xushiwei
1567989142 llgo install: use clang to link 2024-04-24 11:55:20 +08:00
xushiwei
5b73480540 disable debug info 2024-04-24 11:20:31 +08:00
xushiwei
b1342d8d97 build.Do 2024-04-24 11:13:17 +08:00
xushiwei
2cbcc53c54 llgo build/install 2024-04-24 07:55:51 +08:00
xushiwei
b4da61df86 Merge pull request #44 from xushiwei/q
ssadump
2024-04-23 19:23:25 +08:00
xushiwei
edb7a4e1a5 ssadump 2024-04-23 18:57:46 +08:00
xushiwei
0387a35112 Merge pull request #43 from xushiwei/q
cl: varOf
2024-04-23 01:18:16 +08:00
xushiwei
aafe5a8600 cl: varOf 2024-04-23 01:16:31 +08:00
xushiwei
67af68ae10 llgo gen: todo 2024-04-23 00:47:38 +08:00
xushiwei
bc472a4fac Merge pull request #42 from xushiwei/q
remove dep of goplus/gop
2024-04-22 21:18:35 +08:00
xushiwei
2d8f5dbc51 remove dep of goplus/gop 2024-04-22 21:16:43 +08:00
xushiwei
9b7d5e2c57 Merge pull request #41 from xushiwei/q
llgen: support go.mod
2024-04-22 21:07:00 +08:00
xushiwei
f1e676a14f go mod tidy 2024-04-22 21:05:01 +08:00
xushiwei
34d83813ec merge 2024-04-22 21:04:26 +08:00
xushiwei
92b7d61b55 llgen: support go.mod 2024-04-22 21:03:06 +08:00
xushiwei
5d48e42069 Merge pull request #40 from xushiwei/q
cl.NewPackage: rm fset *token.FileSet
2024-04-22 20:25:50 +08:00
xushiwei
ead09d94aa cl.NewPackage: rm fset *token.FileSet 2024-04-22 20:23:01 +08:00
xushiwei
7240da07b4 Merge pull request #39 from xushiwei/q
cl: funcOf; use gogen/packages.Importer
2024-04-22 20:11:59 +08:00
xushiwei
72084b5648 cl: _testdata/importpkg 2024-04-22 20:09:23 +08:00
xushiwei
2d75c55d36 cl: funcOf; use gogen/packages.Importer 2024-04-22 17:49:21 +08:00
xushiwei
da71e7c01b Merge pull request #38 from xushiwei/q
cl: support go:linkname
2024-04-22 15:11:10 +08:00
xushiwei
5343a55395 cl: support go:linkname 2024-04-22 15:09:08 +08:00
xushiwei
bbfe2a051c Merge pull request #37 from goplus/dependabot/go_modules/github.com/goplus/llvm-0.7.1
Bump github.com/goplus/llvm from 0.7.1-0.20240420180312-6230a4ea7a47 to 0.7.1
2024-04-22 01:41:33 +08:00
dependabot[bot]
c1b0751ea5 Bump github.com/goplus/llvm
Bumps [github.com/goplus/llvm](https://github.com/goplus/llvm) from 0.7.1-0.20240420180312-6230a4ea7a47 to 0.7.1.
- [Release notes](https://github.com/goplus/llvm/releases)
- [Commits](https://github.com/goplus/llvm/commits/v0.7.1)

---
updated-dependencies:
- dependency-name: github.com/goplus/llvm
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-21 17:36:57 +00:00
xushiwei
2ee1f3373b Merge pull request #34 from goplus/dependabot/github_actions/actions/checkout-4
Bump actions/checkout from 3 to 4
2024-04-22 01:30:05 +08:00
xushiwei
088995088c Merge pull request #35 from goplus/dependabot/github_actions/actions/setup-go-5
Bump actions/setup-go from 4 to 5
2024-04-22 01:29:50 +08:00
xushiwei
b9ab96c89b Merge pull request #36 from goplus/dependabot/go_modules/golang.org/x/tools-0.20.0
Bump golang.org/x/tools from 0.19.0 to 0.20.0
2024-04-22 01:29:31 +08:00
dependabot[bot]
576c276f33 Bump golang.org/x/tools from 0.19.0 to 0.20.0
Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.19.0 to 0.20.0.
- [Release notes](https://github.com/golang/tools/releases)
- [Commits](https://github.com/golang/tools/compare/v0.19.0...v0.20.0)

---
updated-dependencies:
- dependency-name: golang.org/x/tools
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-21 17:24:13 +00:00
dependabot[bot]
0a879cb0be Bump actions/setup-go from 4 to 5
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 4 to 5.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-21 17:24:12 +00:00
dependabot[bot]
177ba6de48 Bump actions/checkout from 3 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-21 17:24:09 +00:00
xushiwei
4d1079261b Create dependabot.yml 2024-04-22 01:23:51 +08:00
xushiwei
f6ab8834fa Update README.md 2024-04-22 01:04:38 +08:00
xushiwei
2142e14b6d llgo/internal/llgen 2024-04-22 00:15:40 +08:00
122 changed files with 11026 additions and 615 deletions

19
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,19 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: github-actions
directory: /
labels:
- dependabot
- actions
schedule:
interval: daily
- package-ecosystem: "gomod" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "daily"

View File

@@ -17,7 +17,7 @@ jobs:
matrix:
llvm: [17]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Update Homebrew
if: matrix.llvm == 17 # needed as long as LLVM 17 is still fresh
@@ -26,7 +26,7 @@ jobs:
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install llvm@${{ matrix.llvm }}
- name: Set up Go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: '1.20'
@@ -42,7 +42,7 @@ jobs:
matrix:
llvm: [17]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install LLVM ${{ matrix.llvm }}
run: |
@@ -52,7 +52,7 @@ jobs:
sudo apt-get install --no-install-recommends llvm-${{ matrix.llvm }}-dev
- name: Set up Go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: '1.20'
@@ -60,4 +60,10 @@ jobs:
run: go build -v ./...
- name: Test
run: go test -v ./...
run: go test -v -coverprofile="coverage.txt" -covermode=atomic ./...
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
slug: goplus/llgo

5
.gitignore vendored
View File

@@ -8,6 +8,11 @@
*.so
*.dylib
.DS_Store
err.log
_go/
_runtime/
_tinygo/
# Test binary, built with `go test -c`

View File

@@ -3,8 +3,9 @@ llgo - A Go compiler based on LLVM
[![Build Status](https://github.com/goplus/llgo/actions/workflows/go.yml/badge.svg)](https://github.com/goplus/llgo/actions/workflows/go.yml)
[![Go Report Card](https://goreportcard.com/badge/github.com/goplus/llgo)](https://goreportcard.com/report/github.com/goplus/llgo)
[![GoDoc](https://pkg.go.dev/badge/github.com/goplus/llgo.svg)](https://pkg.go.dev/github.com/goplus/llgo)
<!--
[![GitHub release](https://img.shields.io/github/v/tag/goplus/llgo.svg?label=release)](https://github.com/goplus/llgo/releases)
[![Coverage Status](https://codecov.io/gh/goplus/llgo/branch/main/graph/badge.svg)](https://codecov.io/gh/goplus/llgo)
-->
[![GoDoc](https://pkg.go.dev/badge/github.com/goplus/llgo.svg)](https://pkg.go.dev/github.com/goplus/llgo)
[![Language](https://img.shields.io/badge/language-Go+-blue.svg)](https://github.com/goplus/gop)
This is a Go compiler based on LLVM in order to better integrate Go with the C ecosystem. It's a subproject of [the Go+ project](https://github.com/goplus/gop).

View File

@@ -1,57 +0,0 @@
/*
* Copyright (c) 2023 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 build
import (
"go/build"
)
// An ImportMode controls the behavior of the Import method.
type ImportMode = build.ImportMode
// A Package describes the Go package found in a directory.
type Package struct {
*build.Package
}
// A Context specifies the supporting context for a build.
type Context struct {
*build.Context
}
// Import returns details about the Go package named by the import path,
// interpreting local import paths relative to the srcDir directory.
// If the path is a local import path naming a package that can be imported
// using a standard import path, the returned package will set p.ImportPath
// to that path.
//
// If an error occurs, Import returns a non-nil error and a non-nil
// *Package containing partial information.
func (ctxt Context) Import(path string, srcDir string, mode ImportMode) (ret Package, err error) {
pkg, err := build.Import(path, srcDir, mode)
if err != nil {
return
}
ret = Package{pkg}
return
}
// ImportDir is like Import but processes the Go package found in
// the named directory.
func (ctxt *Context) ImportDir(dir string, mode ImportMode) (Package, error) {
return ctxt.Import(".", dir, mode)
}

View File

@@ -0,0 +1,57 @@
/*
* 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 main
import (
"fmt"
"os"
"strings"
"github.com/goplus/llgo/internal/llgen"
"github.com/goplus/mod"
)
func main() {
dir, _, err := mod.FindGoMod(".")
check(err)
llgen.Verbose = false
llgenDir(dir + "/cl/_testrt")
llgenDir(dir+"/cl/_testdata", "")
}
func llgenDir(dir string, pkgPath ...string) {
fis, err := os.ReadDir(dir)
check(err)
for _, fi := range fis {
name := fi.Name()
if !fi.IsDir() || strings.HasPrefix(name, "_") {
continue
}
testDir := dir + "/" + name
fmt.Fprintln(os.Stderr, "llgen", testDir)
os.Chdir(testDir)
llgen.SmartDoFile("in.go", pkgPath...)
}
}
func check(err error) {
if err != nil {
panic(err)
}
}

View File

@@ -19,22 +19,16 @@ package main
import (
"fmt"
"os"
"path/filepath"
"github.com/goplus/llgo/x/llgen"
"github.com/goplus/llgo/internal/llgen"
)
func main() {
if len(os.Args) != 2 {
fmt.Fprintln(os.Stderr, "Usage: llgen xxx.go")
if len(os.Args) < 2 {
fmt.Fprintln(os.Stderr, "Usage: llgen <pkg> [pkgPath]")
return
}
inFile := os.Args[1]
dir, _ := filepath.Split(inFile)
outFile := dir + "out.ll"
llgen.Init()
llgen.Do(inFile, outFile)
llgen.SmartDoFile(os.Args[1], os.Args[2:]...)
}

201
chore/ssadump/ssadump.go Normal file
View File

@@ -0,0 +1,201 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// ssadump: a tool for displaying and interpreting the SSA form of Go programs.
package main // import "golang.org/x/tools/cmd/ssadump"
import (
"flag"
"fmt"
"go/build"
"go/types"
"os"
"runtime"
"runtime/pprof"
"golang.org/x/tools/go/buildutil"
"golang.org/x/tools/go/packages"
"golang.org/x/tools/go/ssa"
"golang.org/x/tools/go/ssa/interp"
"golang.org/x/tools/go/ssa/ssautil"
)
const (
loadFiles = packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles
loadImports = loadFiles | packages.NeedImports
loadTypes = loadImports | packages.NeedTypes | packages.NeedTypesSizes
loadSyntax = loadTypes | packages.NeedSyntax | packages.NeedTypesInfo
)
// flags
var (
mode = ssa.BuilderMode(0)
testFlag = flag.Bool("test", false, "include implicit test packages and executables")
runFlag = flag.Bool("run", false, "interpret the SSA program")
interpFlag = flag.String("interp", "", `Options controlling the SSA test interpreter.
The value is a sequence of zero or more more of these letters:
R disable [R]ecover() from panic; show interpreter crash instead.
T [T]race execution of the program. Best for single-threaded programs!
`)
cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
args stringListValue
)
func init() {
flag.Var(&mode, "build", ssa.BuilderModeDoc)
flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
flag.Var(&args, "arg", "add argument to interpreted program")
}
const usage = `SSA builder and interpreter.
Usage: ssadump [-build=[DBCSNFLG]] [-test] [-run] [-interp=[TR]] [-arg=...] package...
Use -help flag to display options.
Examples:
% ssadump -build=F hello.go # dump SSA form of a single package
% ssadump -build=F -test fmt # dump SSA form of a package and its tests
% ssadump -run -interp=T hello.go # interpret a program, with tracing
The -run flag causes ssadump to build the code in a runnable form and run the first
package named main.
Interpretation of the standard "testing" package is no longer supported.
`
func main() {
if err := doMain(); err != nil {
fmt.Fprintf(os.Stderr, "ssadump: %s\n", err)
os.Exit(1)
}
}
func doMain() error {
flag.Parse()
if len(flag.Args()) == 0 {
fmt.Fprint(os.Stderr, usage)
os.Exit(1)
}
cfg := &packages.Config{
Mode: loadSyntax,
Tests: *testFlag,
}
// Choose types.Sizes from conf.Build.
// TODO(adonovan): remove this when go/packages provides a better way.
var wordSize int64 = 8
switch build.Default.GOARCH {
case "386", "arm":
wordSize = 4
}
sizes := &types.StdSizes{
MaxAlign: 8,
WordSize: wordSize,
}
var interpMode interp.Mode
for _, c := range *interpFlag {
switch c {
case 'T':
interpMode |= interp.EnableTracing
case 'R':
interpMode |= interp.DisableRecover
default:
return fmt.Errorf("unknown -interp option: '%c'", c)
}
}
// Profiling support.
if *cpuprofile != "" {
f, err := os.Create(*cpuprofile)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
}
// Load, parse and type-check the initial packages,
// and, if -run, their dependencies.
if *runFlag {
cfg.Mode = loadSyntax | packages.NeedDeps
}
initial, err := packages.Load(cfg, flag.Args()...)
if err != nil {
return err
}
if len(initial) == 0 {
return fmt.Errorf("no packages")
}
if packages.PrintErrors(initial) > 0 {
return fmt.Errorf("packages contain errors")
}
// Turn on instantiating generics during build if the program will be run.
if *runFlag {
mode |= ssa.InstantiateGenerics
}
// Create SSA-form program representation.
prog, pkgs := ssautil.AllPackages(initial, mode)
for i, p := range pkgs {
if p == nil {
return fmt.Errorf("cannot build SSA for package %s", initial[i])
}
}
if !*runFlag {
// Build and display only the initial packages
// (and synthetic wrappers).
for _, p := range pkgs {
p.Build()
}
} else {
// Run the interpreter.
// Build SSA for all packages.
prog.Build()
// Earlier versions of the interpreter needed the runtime
// package; however, interp cannot handle unsafe constructs
// used during runtime's package initialization at the moment.
// The key construct blocking support is:
// *((*T)(unsafe.Pointer(p)))
// Unfortunately, this means only trivial programs can be
// interpreted by ssadump.
if prog.ImportedPackage("runtime") != nil {
return fmt.Errorf("-run: program depends on runtime package (interpreter can run only trivial programs)")
}
if runtime.GOARCH != build.Default.GOARCH {
return fmt.Errorf("cross-interpretation is not supported (target has GOARCH %s, interpreter has %s)",
build.Default.GOARCH, runtime.GOARCH)
}
// Run first main package.
for _, main := range ssautil.MainPackages(pkgs) {
fmt.Fprintf(os.Stderr, "Running: %s\n", main.Pkg.Path())
os.Exit(interp.Interpret(main, interpMode, sizes, main.Pkg.Path(), args))
}
return fmt.Errorf("no main package")
}
return nil
}
// stringListValue is a flag.Value that accumulates strings.
// e.g. --flag=one --flag=two would produce []string{"one", "two"}.
type stringListValue []string
func (ss *stringListValue) Get() interface{} { return []string(*ss) }
func (ss *stringListValue) String() string { return fmt.Sprintf("%q", *ss) }
func (ss *stringListValue) Set(s string) error { *ss = append(*ss, s); return nil }

8
cl/_testdata/apkg/in.go Normal file
View File

@@ -0,0 +1,8 @@
package apkg
func Max(a, b float64) float64 {
if a > b {
return a
}
return b
}

29
cl/_testdata/apkg/out.ll Normal file
View File

@@ -0,0 +1,29 @@
; ModuleID = 'apkg'
source_filename = "apkg"
@"apkg.init$guard" = global ptr null
define double @apkg.Max(double %0, double %1) {
_llgo_0:
%2 = fcmp ogt double %0, %1
br i1 %2, label %_llgo_1, label %_llgo_2
_llgo_1: ; preds = %_llgo_0
ret double %0
_llgo_2: ; preds = %_llgo_0
ret double %1
}
define void @apkg.init() {
_llgo_0:
%0 = load i1, ptr @"apkg.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"apkg.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}

View File

@@ -1,22 +1,30 @@
; ModuleID = 'main'
source_filename = "main"
@"init$guard" = global ptr null
@"main.init$guard" = global ptr null
define void @init() {
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"init$guard", align 1
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"init$guard", align 1
store i1 true, ptr @"main.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define i64 @max(i64 %0, i64 %1) {
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%0 = call i64 @main.max(i64 1, i64 2)
ret void
}
define i64 @main.max(i64 %0, i64 %1) {
_llgo_0:
%2 = icmp sgt i64 %0, %1
br i1 %2, label %_llgo_1, label %_llgo_2
@@ -28,9 +36,4 @@ _llgo_2: ; preds = %_llgo_0
ret i64 %1
}
define void @main() {
_llgo_0:
call void @init()
%0 = call i64 @max(i64 1, i64 2)
ret void
}
declare void @"github.com/goplus/llgo/internal/runtime.init"()

View File

@@ -0,0 +1,10 @@
package main
import "github.com/goplus/llgo/cl/internal/stdio"
var hello = [...]int8{'H', 'e', 'l', 'l', 'o', '\n', 0}
func main() {
_ = stdio.Max(2, 100)
stdio.Printf(&hello[0])
}

View File

@@ -0,0 +1,43 @@
; ModuleID = 'main'
source_filename = "main"
@main.hello = global ptr null
@"main.init$guard" = global ptr null
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
call void @"github.com/goplus/llgo/cl/internal/stdio.init"()
store i8 72, ptr @main.hello, align 1
store i8 101, ptr getelementptr inbounds (i8, ptr @main.hello, i64 1), align 1
store i8 108, ptr getelementptr inbounds (i8, ptr @main.hello, i64 2), align 1
store i8 108, ptr getelementptr inbounds (i8, ptr @main.hello, i64 3), align 1
store i8 111, ptr getelementptr inbounds (i8, ptr @main.hello, i64 4), align 1
store i8 10, ptr getelementptr inbounds (i8, ptr @main.hello, i64 5), align 1
store i8 0, ptr getelementptr inbounds (i8, ptr @main.hello, i64 6), align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%0 = call i64 @"github.com/goplus/llgo/cl/internal/stdio.Max"(i64 2, i64 100)
call void (ptr, ...) @printf(ptr @main.hello)
ret void
}
declare void @"github.com/goplus/llgo/cl/internal/stdio.init"()
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare i64 @"github.com/goplus/llgo/cl/internal/stdio.Max"(i64, i64)
declare void @printf(ptr, ...)

19
cl/_testdata/method/in.go Normal file
View File

@@ -0,0 +1,19 @@
package main
import _ "unsafe"
type T int
func (a T) Add(b T) T {
return a + b
}
//go:linkname printf C.printf
func printf(format *int8, __llgo_va_list ...any)
var format = [...]int8{'H', 'e', 'l', 'l', 'o', ' ', '%', 'd', '\n', 0}
func main() {
a := T(1)
printf(&format[0], a.Add(2))
}

View File

@@ -0,0 +1,54 @@
; ModuleID = 'main'
source_filename = "main"
@main.format = global ptr null
@"main.init$guard" = global ptr null
define i64 @"(main.T).Add"(i64 %0, i64 %1) {
_llgo_0:
%2 = add i64 %0, %1
ret i64 %2
}
define i64 @"(*main.T).Add"(ptr %0, i64 %1) {
_llgo_0:
%2 = load i64, ptr %0, align 4
%3 = call i64 @"(main.T).Add"(i64 %2, i64 %1)
ret i64 %3
}
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
store i8 72, ptr @main.format, align 1
store i8 101, ptr getelementptr inbounds (i8, ptr @main.format, i64 1), align 1
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 2), align 1
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 3), align 1
store i8 111, ptr getelementptr inbounds (i8, ptr @main.format, i64 4), align 1
store i8 32, ptr getelementptr inbounds (i8, ptr @main.format, i64 5), align 1
store i8 37, ptr getelementptr inbounds (i8, ptr @main.format, i64 6), align 1
store i8 100, ptr getelementptr inbounds (i8, ptr @main.format, i64 7), align 1
store i8 10, ptr getelementptr inbounds (i8, ptr @main.format, i64 8), align 1
store i8 0, ptr getelementptr inbounds (i8, ptr @main.format, i64 9), align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%0 = call i64 @"(main.T).Add"(i64 1, i64 2)
call void (ptr, ...) @printf(ptr @main.format, i64 %0)
ret void
}
declare void @printf(ptr, ...)
declare void @"github.com/goplus/llgo/internal/runtime.init"()

View File

@@ -2,7 +2,7 @@ package main
import _ "unsafe"
//go:linkname printf _printf
//go:linkname printf C.printf
func printf(format *int8, __llgo_va_list ...any)
var hello = [...]int8{'H', 'e', 'l', 'l', 'o', '\n', 0}

View File

@@ -1,34 +1,37 @@
; ModuleID = 'main'
source_filename = "main"
@"init$guard" = global ptr null
@hello = global ptr null
@main.hello = global ptr null
@"main.init$guard" = global ptr null
define void @init() {
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"init$guard", align 1
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"init$guard", align 1
store i8 72, ptr @hello, align 1
store i8 101, ptr getelementptr inbounds (i8, ptr @hello, i64 1), align 1
store i8 108, ptr getelementptr inbounds (i8, ptr @hello, i64 2), align 1
store i8 108, ptr getelementptr inbounds (i8, ptr @hello, i64 3), align 1
store i8 111, ptr getelementptr inbounds (i8, ptr @hello, i64 4), align 1
store i8 10, ptr getelementptr inbounds (i8, ptr @hello, i64 5), align 1
store i8 0, ptr getelementptr inbounds (i8, ptr @hello, i64 6), align 1
store i1 true, ptr @"main.init$guard", align 1
store i8 72, ptr @main.hello, align 1
store i8 101, ptr getelementptr inbounds (i8, ptr @main.hello, i64 1), align 1
store i8 108, ptr getelementptr inbounds (i8, ptr @main.hello, i64 2), align 1
store i8 108, ptr getelementptr inbounds (i8, ptr @main.hello, i64 3), align 1
store i8 111, ptr getelementptr inbounds (i8, ptr @main.hello, i64 4), align 1
store i8 10, ptr getelementptr inbounds (i8, ptr @main.hello, i64 5), align 1
store i8 0, ptr getelementptr inbounds (i8, ptr @main.hello, i64 6), align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
declare void @printf(ptr, ...)
define void @main() {
_llgo_0:
call void @init()
call void (ptr, ...) @printf(ptr @hello)
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
call void (ptr, ...) @printf(ptr @main.hello)
ret void
}
declare void @printf(ptr, ...)
declare void @"github.com/goplus/llgo/internal/runtime.init"()

View File

@@ -0,0 +1,12 @@
package main
import _ "unsafe"
//go:linkname printf C.printf
func printf(format *int8, __llgo_va_list ...any)
var format = [...]int8{'H', 'e', 'l', 'l', 'o', ' ', '%', 'd', '\n', 0}
func main() {
printf(&format[0], 100)
}

View File

@@ -0,0 +1,40 @@
; ModuleID = 'main'
source_filename = "main"
@main.format = global ptr null
@"main.init$guard" = global ptr null
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
store i8 72, ptr @main.format, align 1
store i8 101, ptr getelementptr inbounds (i8, ptr @main.format, i64 1), align 1
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 2), align 1
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 3), align 1
store i8 111, ptr getelementptr inbounds (i8, ptr @main.format, i64 4), align 1
store i8 32, ptr getelementptr inbounds (i8, ptr @main.format, i64 5), align 1
store i8 37, ptr getelementptr inbounds (i8, ptr @main.format, i64 6), align 1
store i8 100, ptr getelementptr inbounds (i8, ptr @main.format, i64 7), align 1
store i8 10, ptr getelementptr inbounds (i8, ptr @main.format, i64 8), align 1
store i8 0, ptr getelementptr inbounds (i8, ptr @main.format, i64 9), align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
call void (ptr, ...) @printf(ptr @main.format, i64 100)
ret void
}
declare void @printf(ptr, ...)
declare void @"github.com/goplus/llgo/internal/runtime.init"()

View File

@@ -0,0 +1,19 @@
package main
import _ "unsafe"
//go:linkname printf C.printf
func printf(format *int8, __llgo_va_list ...any)
type T int8
func (f *T) Print(v int) {
printf((*int8)(f), v)
}
var format = [...]T{'H', 'e', 'l', 'l', 'o', ' ', '%', 'd', '\n', 0}
func main() {
f := &format[0]
f.Print(100)
}

View File

@@ -0,0 +1,46 @@
; ModuleID = 'main'
source_filename = "main"
@main.format = global ptr null
@"main.init$guard" = global ptr null
define void @"(*main.T).Print"(ptr %0, i64 %1) {
_llgo_0:
call void (ptr, ...) @printf(ptr %0, i64 %1)
ret void
}
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
store i8 72, ptr @main.format, align 1
store i8 101, ptr getelementptr inbounds (i8, ptr @main.format, i64 1), align 1
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 2), align 1
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 3), align 1
store i8 111, ptr getelementptr inbounds (i8, ptr @main.format, i64 4), align 1
store i8 32, ptr getelementptr inbounds (i8, ptr @main.format, i64 5), align 1
store i8 37, ptr getelementptr inbounds (i8, ptr @main.format, i64 6), align 1
store i8 100, ptr getelementptr inbounds (i8, ptr @main.format, i64 7), align 1
store i8 10, ptr getelementptr inbounds (i8, ptr @main.format, i64 8), align 1
store i8 0, ptr getelementptr inbounds (i8, ptr @main.format, i64 9), align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
call void @"(*main.T).Print"(ptr @main.format, i64 100)
ret void
}
declare void @printf(ptr, ...)
declare void @"github.com/goplus/llgo/internal/runtime.init"()

View File

@@ -0,0 +1,11 @@
package main
const c = 100
var a float64 = 1
func main() {
if c > 100 {
a = 0
}
}

View File

@@ -0,0 +1,35 @@
; ModuleID = 'main'
source_filename = "main"
@main.a = global ptr null
@"main.init$guard" = global ptr null
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
store double 1.000000e+00, ptr @main.a, align 8
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
br i1 false, label %_llgo_1, label %_llgo_2
_llgo_1: ; preds = %_llgo_0
store double 0.000000e+00, ptr @main.a, align 8
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
declare void @"github.com/goplus/llgo/internal/runtime.init"()

View File

@@ -1,17 +1,17 @@
; ModuleID = 'main'
source_filename = "main"
@"init$guard" = global ptr null
@a = global ptr null
@main.a = global ptr null
@"main.init$guard" = global ptr null
define void @init() {
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"init$guard", align 1
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"init$guard", align 1
store i64 100, ptr @a, align 4
store i1 true, ptr @"main.init$guard", align 1
store i64 100, ptr @main.a, align 4
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
@@ -20,10 +20,13 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
define void @main() {
_llgo_0:
call void @init()
%0 = load i64, ptr @a, align 4
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%0 = load i64, ptr @main.a, align 4
%1 = add i64 %0, 1
store i64 %1, ptr @a, align 4
%2 = load i64, ptr @a, align 4
store i64 %1, ptr @main.a, align 4
%2 = load i64, ptr @main.a, align 4
ret void
}
declare void @"github.com/goplus/llgo/internal/runtime.init"()

12
cl/_testrt/alloca/in.go Normal file
View File

@@ -0,0 +1,12 @@
package main
import (
"github.com/goplus/llgo/internal/runtime/c"
)
func main() {
s := c.Str("Hi\n")
s2 := c.Alloca(4)
c.Memcpy(s2, c.Pointer(s), 4)
c.Printf(c.Str("%s"), s2)
}

35
cl/_testrt/alloca/out.ll Normal file
View File

@@ -0,0 +1,35 @@
; ModuleID = 'main'
source_filename = "main"
@"main.init$guard" = global ptr null
@0 = private unnamed_addr constant [4 x i8] c"Hi\0A\00", align 1
@1 = private unnamed_addr constant [3 x i8] c"%s\00", align 1
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%0 = alloca i8, i64 4, align 1
%1 = call ptr @memcpy(ptr %0, ptr @0, i64 4)
%2 = call i32 (ptr, ...) @printf(ptr @1, ptr %0)
ret void
}
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare ptr @memcpy(ptr, ptr, i64)
declare i32 @printf(ptr, ...)

13
cl/_testrt/allocstr/in.go Normal file
View File

@@ -0,0 +1,13 @@
package main
import (
"github.com/goplus/llgo/internal/runtime/c"
)
func hello() string {
return "Hello world\n"
}
func main() {
c.Printf(c.AllocaCStr(hello()))
}

View File

@@ -0,0 +1,49 @@
; ModuleID = 'main'
source_filename = "main"
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
@"main.init$guard" = global ptr null
@0 = private unnamed_addr constant [13 x i8] c"Hello world\0A\00", align 1
define %"github.com/goplus/llgo/internal/runtime.String" @main.hello() {
_llgo_0:
%0 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @0, i64 12)
ret %"github.com/goplus/llgo/internal/runtime.String" %0
}
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%0 = call %"github.com/goplus/llgo/internal/runtime.String" @main.hello()
%1 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %0)
%2 = add i64 %1, 1
%3 = alloca i8, i64 %2, align 1
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr %3, %"github.com/goplus/llgo/internal/runtime.String" %0)
%5 = call i32 (ptr, ...) @printf(ptr %4)
ret void
}
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64)
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String")
declare ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr, %"github.com/goplus/llgo/internal/runtime.String")
declare i32 @printf(ptr, ...)

13
cl/_testrt/any/in.go Normal file
View File

@@ -0,0 +1,13 @@
package main
import (
"github.com/goplus/llgo/internal/runtime/c"
)
func incVal(a any) int {
return a.(int) + 1
}
func main() {
c.Printf(c.Str("Hello %d\n"), incVal(100))
}

49
cl/_testrt/any/out.ll Normal file
View File

@@ -0,0 +1,49 @@
; ModuleID = 'main'
source_filename = "main"
%"github.com/goplus/llgo/internal/runtime.iface" = type { ptr, ptr }
@"main.init$guard" = global ptr null
@0 = private unnamed_addr constant [10 x i8] c"Hello %d\0A\00", align 1
define i64 @main.incVal(%"github.com/goplus/llgo/internal/runtime.iface" %0) {
_llgo_0:
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2)
%2 = call i64 @"github.com/goplus/llgo/internal/runtime.I2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %1)
%3 = add i64 %2, 1
ret i64 %3
}
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2)
%1 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %0, i64 100)
%2 = call i64 @main.incVal(%"github.com/goplus/llgo/internal/runtime.iface" %1)
%3 = call i32 (ptr, ...) @printf(ptr @0, i64 %2)
ret void
}
declare i64 @"github.com/goplus/llgo/internal/runtime.I2Int"(%"github.com/goplus/llgo/internal/runtime.iface", ptr)
declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64)
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr, i64)
declare i32 @printf(ptr, ...)

51
cl/_testrt/builtin/in.go Normal file
View File

@@ -0,0 +1,51 @@
package main
import (
"github.com/goplus/llgo/internal/runtime/c"
)
var a int64 = 1<<63 - 1
var b int64 = -1 << 63
var n uint64 = 1<<64 - 1
func main() {
var s = []int{1, 2, 3, 4}
var a = [...]int{1, 2, 3, 4}
out(len(s))
out(len([]int{1, 2, 3, 4}))
out(len(a))
out(len(&a))
out(len([4]int{1, 2, 3, 4}))
out(cap(s))
out(cap(a))
out(cap(&a))
out(len(s[1:]))
out(cap(s[1:]))
out(len(s[1:2]))
out(cap(s[1:2]))
out(len(s[1:2:2]))
out(cap(s[1:2:2]))
out(len(a[1:]))
out(cap(a[1:]))
out(len(a[1:2]))
out(cap(a[1:2]))
out(len(a[1:2:2]))
out(cap(a[1:2:2]))
string_len("hello")
string_len("hello"[1:])
string_len("hello"[1:2])
string_len("hello"[5:])
}
func string_len(s string) {
out(len(s))
}
func out(n int) {
c.Printf(c.Str("%d\n"), n)
}

174
cl/_testrt/builtin/out.ll Normal file
View File

@@ -0,0 +1,174 @@
; ModuleID = 'main'
source_filename = "main"
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 }
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
@main.a = global ptr null
@main.b = global ptr null
@"main.init$guard" = global ptr null
@main.n = global ptr null
@0 = private unnamed_addr constant [6 x i8] c"hello\00", align 1
@1 = private unnamed_addr constant [6 x i8] c"hello\00", align 1
@2 = private unnamed_addr constant [6 x i8] c"hello\00", align 1
@3 = private unnamed_addr constant [6 x i8] c"hello\00", align 1
@4 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
store i64 9223372036854775807, ptr @main.a, align 4
store i64 -9223372036854775808, ptr @main.b, align 4
store i64 -1, ptr @main.n, align 4
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
%1 = getelementptr inbounds i64, ptr %0, i64 0
store i64 1, ptr %1, align 4
%2 = getelementptr inbounds i64, ptr %0, i64 1
store i64 2, ptr %2, align 4
%3 = getelementptr inbounds i64, ptr %0, i64 2
store i64 3, ptr %3, align 4
%4 = getelementptr inbounds i64, ptr %0, i64 3
store i64 4, ptr %4, align 4
%5 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %0, i64 8, i64 4, i64 0, i64 4, i64 4)
%6 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
%7 = getelementptr inbounds i64, ptr %6, i64 0
%8 = getelementptr inbounds i64, ptr %6, i64 1
%9 = getelementptr inbounds i64, ptr %6, i64 2
%10 = getelementptr inbounds i64, ptr %6, i64 3
store i64 1, ptr %7, align 4
store i64 2, ptr %8, align 4
store i64 3, ptr %9, align 4
store i64 4, ptr %10, align 4
%11 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
call void @main.out(i64 %11)
%12 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
%13 = getelementptr inbounds i64, ptr %12, i64 0
store i64 1, ptr %13, align 4
%14 = getelementptr inbounds i64, ptr %12, i64 1
store i64 2, ptr %14, align 4
%15 = getelementptr inbounds i64, ptr %12, i64 2
store i64 3, ptr %15, align 4
%16 = getelementptr inbounds i64, ptr %12, i64 3
store i64 4, ptr %16, align 4
%17 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %12, i64 8, i64 4, i64 0, i64 4, i64 4)
%18 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %17)
call void @main.out(i64 %18)
call void @main.out(i64 4)
call void @main.out(i64 4)
call void @main.out(i64 4)
%19 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
call void @main.out(i64 %19)
call void @main.out(i64 4)
call void @main.out(i64 4)
%20 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
%21 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
%22 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
%23 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %22, i64 8, i64 %20, i64 1, i64 %21, i64 %20)
%24 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %23)
call void @main.out(i64 %24)
%25 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
%26 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
%27 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
%28 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %27, i64 8, i64 %25, i64 1, i64 %26, i64 %25)
%29 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %28)
call void @main.out(i64 %29)
%30 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
%31 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
%32 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %31, i64 8, i64 %30, i64 1, i64 2, i64 %30)
%33 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %32)
call void @main.out(i64 %33)
%34 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
%35 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
%36 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %35, i64 8, i64 %34, i64 1, i64 2, i64 %34)
%37 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %36)
call void @main.out(i64 %37)
%38 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
%39 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
%40 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %39, i64 8, i64 %38, i64 1, i64 2, i64 2)
%41 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %40)
call void @main.out(i64 %41)
%42 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
%43 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
%44 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %43, i64 8, i64 %42, i64 1, i64 2, i64 2)
%45 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %44)
call void @main.out(i64 %45)
%46 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %6, i64 8, i64 4, i64 1, i64 4, i64 4)
%47 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %46)
call void @main.out(i64 %47)
%48 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %6, i64 8, i64 4, i64 1, i64 4, i64 4)
%49 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %48)
call void @main.out(i64 %49)
%50 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %6, i64 8, i64 4, i64 1, i64 2, i64 4)
%51 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %50)
call void @main.out(i64 %51)
%52 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %6, i64 8, i64 4, i64 1, i64 2, i64 4)
%53 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %52)
call void @main.out(i64 %53)
%54 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %6, i64 8, i64 4, i64 1, i64 2, i64 2)
%55 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %54)
call void @main.out(i64 %55)
%56 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %6, i64 8, i64 4, i64 1, i64 2, i64 2)
%57 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %56)
call void @main.out(i64 %57)
%58 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @0, i64 5)
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %58)
%59 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @1, i64 5)
%60 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %59)
%61 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %59, i64 1, i64 %60)
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %61)
%62 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @2, i64 5)
%63 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %62, i64 1, i64 2)
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %63)
%64 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @3, i64 5)
%65 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %64)
%66 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %64, i64 5, i64 %65)
call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %66)
ret void
}
define void @main.out(i64 %0) {
_llgo_0:
%1 = call i32 (ptr, ...) @printf(ptr @4, i64 %0)
ret void
}
define void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %0) {
_llgo_0:
%1 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %0)
call void @main.out(i64 %1)
ret void
}
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64)
declare i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice")
declare i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice")
declare ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice")
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64)
declare i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String")
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String", i64, i64)
declare i32 @printf(ptr, ...)

17
cl/_testrt/concat/in.go Normal file
View File

@@ -0,0 +1,17 @@
package main
import (
"github.com/goplus/llgo/internal/runtime/c"
)
func concat(args ...string) (ret string) {
for _, v := range args {
ret += v
}
return
}
func main() {
result := concat("Hello", " ", "World")
c.Fprintf(c.Stderr, c.Str("Hi, %s\n"), c.AllocaCStr(result))
}

106
cl/_testrt/concat/out.ll Normal file
View File

@@ -0,0 +1,106 @@
; ModuleID = 'main'
source_filename = "main"
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 }
@"main.init$guard" = global ptr null
@0 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
@1 = private unnamed_addr constant [6 x i8] c"Hello\00", align 1
@2 = private unnamed_addr constant [2 x i8] c" \00", align 1
@3 = private unnamed_addr constant [6 x i8] c"World\00", align 1
@__stderrp = external global ptr
@4 = private unnamed_addr constant [8 x i8] c"Hi, %s\0A\00", align 1
define %"github.com/goplus/llgo/internal/runtime.String" @main.concat(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
_llgo_0:
%1 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %0)
%2 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @0, i64 0)
%3 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %2, 0
%4 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %2, 1
br label %_llgo_1
_llgo_1: ; preds = %_llgo_2, %_llgo_0
%5 = phi ptr [ %3, %_llgo_0 ], [ %18, %_llgo_2 ]
%6 = phi i64 [ %4, %_llgo_0 ], [ %19, %_llgo_2 ]
%7 = phi i64 [ -1, %_llgo_0 ], [ %12, %_llgo_2 ]
%8 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %8, i32 0, i32 0
store ptr %5, ptr %9, align 8
%10 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %8, i32 0, i32 1
store i64 %6, ptr %10, align 4
%11 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %8, align 8
%12 = add i64 %7, 1
%13 = icmp slt i64 %12, %1
br i1 %13, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1
%14 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %0)
%15 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %14, i64 %12
%16 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %15, align 8
%17 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringCat"(%"github.com/goplus/llgo/internal/runtime.String" %11, %"github.com/goplus/llgo/internal/runtime.String" %16)
%18 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %17, 0
%19 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %17, 1
br label %_llgo_1
_llgo_3: ; preds = %_llgo_1
ret %"github.com/goplus/llgo/internal/runtime.String" %11
}
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 48)
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i64 0
%2 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @1, i64 5)
store %"github.com/goplus/llgo/internal/runtime.String" %2, ptr %1, align 8
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i64 1
%4 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @2, i64 1)
store %"github.com/goplus/llgo/internal/runtime.String" %4, ptr %3, align 8
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i64 2
%6 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @3, i64 5)
store %"github.com/goplus/llgo/internal/runtime.String" %6, ptr %5, align 8
%7 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %0, i64 16, i64 3, i64 0, i64 3, i64 3)
%8 = call %"github.com/goplus/llgo/internal/runtime.String" @main.concat(%"github.com/goplus/llgo/internal/runtime.Slice" %7)
%9 = load ptr, ptr @__stderrp, align 8
%10 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %8)
%11 = add i64 %10, 1
%12 = alloca i8, i64 %11, align 1
%13 = call ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr %12, %"github.com/goplus/llgo/internal/runtime.String" %8)
%14 = call i32 (ptr, ptr, ...) @fprintf(ptr %9, ptr @4, ptr %13)
ret void
}
declare i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice")
declare ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice")
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringCat"(%"github.com/goplus/llgo/internal/runtime.String", %"github.com/goplus/llgo/internal/runtime.String")
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64)
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64)
declare i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String")
declare ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr, %"github.com/goplus/llgo/internal/runtime.String")
declare i32 @fprintf(ptr, ptr, ...)

13
cl/_testrt/cstr/in.go Normal file
View File

@@ -0,0 +1,13 @@
package main
import _ "unsafe"
//go:linkname cstr llgo.cstr
func cstr(string) *int8
//go:linkname printf C.printf
func printf(format *int8, __llgo_va_list ...any)
func main() {
printf(cstr("Hello, world\n"))
}

30
cl/_testrt/cstr/out.ll Normal file
View File

@@ -0,0 +1,30 @@
; ModuleID = 'main'
source_filename = "main"
@"main.init$guard" = global ptr null
@0 = private unnamed_addr constant [14 x i8] c"Hello, world\0A\00", align 1
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
call void (ptr, ...) @printf(ptr @0)
ret void
}
declare void @printf(ptr, ...)
declare void @"github.com/goplus/llgo/internal/runtime.init"()

19
cl/_testrt/cvar/in.go Normal file
View File

@@ -0,0 +1,19 @@
package main
import _ "unsafe"
//go:linkname barX _bar_x
var barX struct {
Arr [16]int8
Callbacks [2]func()
}
//go:linkname barY _bar_y
var barY struct {
Arr [16]int8
}
func main() {
_ = barX
_ = barY
}

30
cl/_testrt/cvar/out.ll Normal file
View File

@@ -0,0 +1,30 @@
; ModuleID = 'main'
source_filename = "main"
@_bar_x = external global ptr
@_bar_y = external global ptr
@"main.init$guard" = global ptr null
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%0 = load { [16 x i8], [2 x ptr] }, ptr @_bar_x, align 8
%1 = load { [16 x i8] }, ptr @_bar_y, align 1
ret void
}
declare void @"github.com/goplus/llgo/internal/runtime.init"()

16
cl/_testrt/fprintf/in.go Normal file
View File

@@ -0,0 +1,16 @@
package main
import "unsafe"
//go:linkname cstr llgo.cstr
func cstr(string) *int8
//go:linkname stderr __stderrp
var stderr unsafe.Pointer
//go:linkname fprintf C.fprintf
func fprintf(fp unsafe.Pointer, format *int8, __llgo_va_list ...any)
func main() {
fprintf(stderr, cstr("Hello %d\n"), 100)
}

32
cl/_testrt/fprintf/out.ll Normal file
View File

@@ -0,0 +1,32 @@
; ModuleID = 'main'
source_filename = "main"
@"main.init$guard" = global ptr null
@__stderrp = external global ptr
@0 = private unnamed_addr constant [10 x i8] c"Hello %d\0A\00", align 1
declare void @fprintf(ptr, ptr, ...)
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%0 = load ptr, ptr @__stderrp, align 8
call void (ptr, ptr, ...) @fprintf(ptr %0, ptr @0, i64 100)
ret void
}
declare void @"github.com/goplus/llgo/internal/runtime.init"()

32
cl/_testrt/gblarray/in.go Normal file
View File

@@ -0,0 +1,32 @@
package main
import (
"github.com/goplus/llgo/internal/abi"
"github.com/goplus/llgo/internal/runtime/c"
)
func Basic(kind abi.Kind) *abi.Type {
return basicTypes[kind]
}
var (
basicTypes = [...]*abi.Type{
abi.String: basicType(abi.String),
}
sizeBasicTypes = [...]uintptr{
abi.String: 16,
}
)
func basicType(kind abi.Kind) *abi.Type {
return &abi.Type{
Size_: sizeBasicTypes[kind],
Hash: uint32(kind),
Kind_: uint8(kind),
}
}
func main() {
t := Basic(abi.String)
c.Printf(c.Str("Kind: %d, Size: %d\n"), int(t.Kind_), t.Size_)
}

View File

@@ -0,0 +1,71 @@
; ModuleID = 'main'
source_filename = "main"
%"github.com/goplus/llgo/internal/abi.Type" = type { i64, i64, i32, i8, i8, i8, i8, { ptr, ptr }, ptr, i32, i32 }
@main.basicTypes = global ptr null
@"main.init$guard" = global ptr null
@main.sizeBasicTypes = global ptr null
@0 = private unnamed_addr constant [20 x i8] c"Kind: %d, Size: %d\0A\00", align 1
define ptr @main.Basic(i64 %0) {
_llgo_0:
%1 = getelementptr inbounds ptr, ptr @main.basicTypes, i64 %0
%2 = load ptr, ptr %1, align 8
ret ptr %2
}
define ptr @main.basicType(i64 %0) {
_llgo_0:
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 56)
%2 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %1, i32 0, i32 0
%3 = getelementptr inbounds i64, ptr @main.sizeBasicTypes, i64 %0
%4 = load i64, ptr %3, align 4
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %1, i32 0, i32 2
%6 = trunc i64 %0 to i32
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %1, i32 0, i32 6
%8 = trunc i64 %0 to i8
store i64 %4, ptr %2, align 4
store i32 %6, ptr %5, align 4
store i8 %8, ptr %7, align 1
ret ptr %1
}
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
call void @"github.com/goplus/llgo/internal/abi.init"()
store i64 16, ptr getelementptr inbounds (i64, ptr @main.sizeBasicTypes, i64 24), align 4
%1 = call ptr @main.basicType(i64 24)
store ptr %1, ptr getelementptr inbounds (ptr, ptr @main.basicTypes, i64 24), align 8
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%0 = call ptr @main.Basic(i64 24)
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %0, i32 0, i32 6
%2 = load i8, ptr %1, align 1
%3 = sext i8 %2 to i64
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %0, i32 0, i32 0
%5 = load i64, ptr %4, align 4
%6 = call i32 (ptr, ...) @printf(ptr @0, i64 %3, i64 %5)
ret void
}
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
declare void @"github.com/goplus/llgo/internal/abi.init"()
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare i32 @printf(ptr, ...)

10
cl/_testrt/hello/in.go Normal file
View File

@@ -0,0 +1,10 @@
package main
import "github.com/goplus/llgo/cl/internal/libc"
var format = [...]int8{'H', 'e', 'l', 'l', 'o', ' ', '%', 'd', '\n', 0}
func main() {
sfmt := &format[0]
libc.Printf(sfmt, libc.Strlen(sfmt))
}

43
cl/_testrt/hello/out.ll Normal file
View File

@@ -0,0 +1,43 @@
; ModuleID = 'main'
source_filename = "main"
@main.format = global ptr null
@"main.init$guard" = global ptr null
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
store i8 72, ptr @main.format, align 1
store i8 101, ptr getelementptr inbounds (i8, ptr @main.format, i64 1), align 1
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 2), align 1
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 3), align 1
store i8 111, ptr getelementptr inbounds (i8, ptr @main.format, i64 4), align 1
store i8 32, ptr getelementptr inbounds (i8, ptr @main.format, i64 5), align 1
store i8 37, ptr getelementptr inbounds (i8, ptr @main.format, i64 6), align 1
store i8 100, ptr getelementptr inbounds (i8, ptr @main.format, i64 7), align 1
store i8 10, ptr getelementptr inbounds (i8, ptr @main.format, i64 8), align 1
store i8 0, ptr getelementptr inbounds (i8, ptr @main.format, i64 9), align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%0 = call i32 @strlen(ptr @main.format)
call void (ptr, ...) @printf(ptr @main.format, i32 %0)
ret void
}
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare i32 @strlen(ptr)
declare void @printf(ptr, ...)

25
cl/_testrt/index/in.go Normal file
View File

@@ -0,0 +1,25 @@
package main
import "github.com/goplus/llgo/internal/runtime/c"
type point struct {
x int
y int
}
func main() {
a := [...]point{{1, 2}, {3, 4}, {5, 6}}[2]
c.Printf(c.Str("%d %d\n"), a.x, a.y)
b := [...][2]int{[2]int{1, 2}, [2]int{3, 4}}[1]
c.Printf(c.Str("%d %d\n"), b[0], b[1])
var i int = 2
n := [...]int{1, 2, 3, 4, 5}[i]
c.Printf(c.Str("%d\n"), n)
c.Printf(c.Str("%d\n"), [...]int{1, 2, 3, 4, 5}[i])
s := "123456"
c.Printf(c.Str("%c\n"), s[i])
c.Printf(c.Str("%c\n"), "123456"[1])
}

138
cl/_testrt/index/out.ll Normal file
View File

@@ -0,0 +1,138 @@
; ModuleID = 'main'
source_filename = "main"
%main.point = type { i64, i64 }
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
@"main.init$guard" = global ptr null
@0 = private unnamed_addr constant [7 x i8] c"%d %d\0A\00", align 1
@1 = private unnamed_addr constant [7 x i8] c"%d %d\0A\00", align 1
@2 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
@3 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
@4 = private unnamed_addr constant [4 x i8] c"%c\0A\00", align 1
@5 = private unnamed_addr constant [7 x i8] c"123456\00", align 1
@6 = private unnamed_addr constant [4 x i8] c"%c\0A\00", align 1
@7 = private unnamed_addr constant [7 x i8] c"123456\00", align 1
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%0 = alloca %main.point, align 8
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %0, i64 16)
%2 = alloca [3 x %main.point], align 8
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %2, i64 48)
%4 = getelementptr inbounds %main.point, ptr %3, i64 0
%5 = getelementptr inbounds %main.point, ptr %4, i32 0, i32 0
%6 = getelementptr inbounds %main.point, ptr %4, i32 0, i32 1
%7 = getelementptr inbounds %main.point, ptr %3, i64 1
%8 = getelementptr inbounds %main.point, ptr %7, i32 0, i32 0
%9 = getelementptr inbounds %main.point, ptr %7, i32 0, i32 1
%10 = getelementptr inbounds %main.point, ptr %3, i64 2
%11 = getelementptr inbounds %main.point, ptr %10, i32 0, i32 0
%12 = getelementptr inbounds %main.point, ptr %10, i32 0, i32 1
store i64 1, ptr %5, align 4
store i64 2, ptr %6, align 4
store i64 3, ptr %8, align 4
store i64 4, ptr %9, align 4
store i64 5, ptr %11, align 4
store i64 6, ptr %12, align 4
%13 = load [3 x %main.point], ptr %3, align 4
%14 = getelementptr inbounds %main.point, ptr %3, i64 2
%15 = load %main.point, ptr %14, align 4
store %main.point %15, ptr %1, align 4
%16 = getelementptr inbounds %main.point, ptr %1, i32 0, i32 0
%17 = load i64, ptr %16, align 4
%18 = getelementptr inbounds %main.point, ptr %1, i32 0, i32 1
%19 = load i64, ptr %18, align 4
%20 = call i32 (ptr, ...) @printf(ptr @0, i64 %17, i64 %19)
%21 = alloca [2 x i64], align 8
%22 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %21, i64 16)
%23 = alloca [2 x [2 x i64]], align 8
%24 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %23, i64 32)
%25 = getelementptr inbounds [2 x i64], ptr %24, i64 0
%26 = getelementptr inbounds i64, ptr %25, i64 0
%27 = getelementptr inbounds i64, ptr %25, i64 1
%28 = getelementptr inbounds [2 x i64], ptr %24, i64 1
%29 = getelementptr inbounds i64, ptr %28, i64 0
%30 = getelementptr inbounds i64, ptr %28, i64 1
store i64 1, ptr %26, align 4
store i64 2, ptr %27, align 4
store i64 3, ptr %29, align 4
store i64 4, ptr %30, align 4
%31 = load [2 x [2 x i64]], ptr %24, align 4
%32 = getelementptr inbounds [2 x i64], ptr %24, i64 1
%33 = load [2 x i64], ptr %32, align 4
store [2 x i64] %33, ptr %22, align 4
%34 = getelementptr inbounds i64, ptr %22, i64 0
%35 = load i64, ptr %34, align 4
%36 = getelementptr inbounds i64, ptr %22, i64 1
%37 = load i64, ptr %36, align 4
%38 = call i32 (ptr, ...) @printf(ptr @1, i64 %35, i64 %37)
%39 = alloca [5 x i64], align 8
%40 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %39, i64 40)
%41 = getelementptr inbounds i64, ptr %40, i64 0
%42 = getelementptr inbounds i64, ptr %40, i64 1
%43 = getelementptr inbounds i64, ptr %40, i64 2
%44 = getelementptr inbounds i64, ptr %40, i64 3
%45 = getelementptr inbounds i64, ptr %40, i64 4
store i64 1, ptr %41, align 4
store i64 2, ptr %42, align 4
store i64 3, ptr %43, align 4
store i64 4, ptr %44, align 4
store i64 5, ptr %45, align 4
%46 = load [5 x i64], ptr %40, align 4
%47 = getelementptr inbounds i64, ptr %40, i64 2
%48 = load i64, ptr %47, align 4
%49 = call i32 (ptr, ...) @printf(ptr @2, i64 %48)
%50 = alloca [5 x i64], align 8
%51 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %50, i64 40)
%52 = getelementptr inbounds i64, ptr %51, i64 0
%53 = getelementptr inbounds i64, ptr %51, i64 1
%54 = getelementptr inbounds i64, ptr %51, i64 2
%55 = getelementptr inbounds i64, ptr %51, i64 3
%56 = getelementptr inbounds i64, ptr %51, i64 4
store i64 1, ptr %52, align 4
store i64 2, ptr %53, align 4
store i64 3, ptr %54, align 4
store i64 4, ptr %55, align 4
store i64 5, ptr %56, align 4
%57 = load [5 x i64], ptr %51, align 4
%58 = getelementptr inbounds i64, ptr %51, i64 2
%59 = load i64, ptr %58, align 4
%60 = call i32 (ptr, ...) @printf(ptr @3, i64 %59)
%61 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @5, i64 6)
%62 = call ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String" %61)
%63 = getelementptr inbounds i8, ptr %62, i64 2
%64 = load i8, ptr %63, align 1
%65 = call i32 (ptr, ...) @printf(ptr @4, i8 %64)
%66 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @7, i64 6)
%67 = call ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String" %66)
%68 = getelementptr inbounds i8, ptr %67, i64 1
%69 = load i8, ptr %68, align 1
%70 = call i32 (ptr, ...) @printf(ptr @6, i8 %69)
ret void
}
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr, i64)
declare i32 @printf(ptr, ...)
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64)
declare ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String")

20
cl/_testrt/intgen/in.go Normal file
View File

@@ -0,0 +1,20 @@
package main
import (
"github.com/goplus/llgo/internal/runtime/c"
)
func genInts(n int, gen func() c.Int) []c.Int {
a := make([]c.Int, n)
for i := range a {
a[i] = gen()
}
return a
}
func main() {
a := genInts(5, c.Rand)
for _, v := range a {
c.Printf(c.Str("%d\n"), v)
}
}

90
cl/_testrt/intgen/out.ll Normal file
View File

@@ -0,0 +1,90 @@
; ModuleID = 'main'
source_filename = "main"
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 }
@"main.init$guard" = global ptr null
@0 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
define %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 %0, { ptr, ptr } %1) {
_llgo_0:
%2 = mul i64 %0, 4
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 %2)
%4 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice"(ptr %3, i64 %0, i64 %0)
%5 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %4)
br label %_llgo_1
_llgo_1: ; preds = %_llgo_2, %_llgo_0
%6 = phi i64 [ -1, %_llgo_0 ], [ %7, %_llgo_2 ]
%7 = add i64 %6, 1
%8 = icmp slt i64 %7, %5
br i1 %8, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1
%9 = extractvalue { ptr, ptr } %1, 0
%10 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %4)
%11 = getelementptr inbounds i32, ptr %10, i64 %7
store i32 0, ptr %11, align 4
br label %_llgo_1
_llgo_3: ; preds = %_llgo_1
ret %"github.com/goplus/llgo/internal/runtime.Slice" %4
}
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%0 = alloca { ptr, ptr }, align 8
%1 = getelementptr inbounds { ptr, ptr }, ptr %0, i32 0, i32 0
store ptr @rand, ptr %1, align 8
%2 = getelementptr inbounds { ptr, ptr }, ptr %0, i32 0, i32 1
store ptr null, ptr %2, align 8
%3 = load { ptr, ptr }, ptr %0, align 8
%4 = call %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 5, { ptr, ptr } %3)
%5 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %4)
br label %_llgo_1
_llgo_1: ; preds = %_llgo_2, %_llgo_0
%6 = phi i64 [ -1, %_llgo_0 ], [ %7, %_llgo_2 ]
%7 = add i64 %6, 1
%8 = icmp slt i64 %7, %5
br i1 %8, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1
%9 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %4)
%10 = getelementptr inbounds i32, ptr %9, i64 %7
%11 = load i32, ptr %10, align 4
%12 = call i32 (ptr, ...) @printf(ptr @0, i32 %11)
br label %_llgo_1
_llgo_3: ; preds = %_llgo_1
ret void
}
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice"(ptr, i64, i64)
declare i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice")
declare ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice")
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare i32 @rand()
declare i32 @printf(ptr, ...)

15
cl/_testrt/linkname/in.go Normal file
View File

@@ -0,0 +1,15 @@
package main
import (
_ "unsafe"
"github.com/goplus/llgo/internal/runtime/c"
)
//go:linkname print github.com/goplus/llgo/cl/internal/linktarget.F
func print(a, b, c, d *c.Char)
func main() {
print(c.Str("a"), c.Str("b"), c.Str("c"), c.Str("d"))
print(c.Str("1"), c.Str("2"), c.Str("3"), c.Str("4"))
}

View File

@@ -0,0 +1,38 @@
; ModuleID = 'main'
source_filename = "main"
@"main.init$guard" = global ptr null
@0 = private unnamed_addr constant [2 x i8] c"a\00", align 1
@1 = private unnamed_addr constant [2 x i8] c"b\00", align 1
@2 = private unnamed_addr constant [2 x i8] c"c\00", align 1
@3 = private unnamed_addr constant [2 x i8] c"d\00", align 1
@4 = private unnamed_addr constant [2 x i8] c"1\00", align 1
@5 = private unnamed_addr constant [2 x i8] c"2\00", align 1
@6 = private unnamed_addr constant [2 x i8] c"3\00", align 1
@7 = private unnamed_addr constant [2 x i8] c"4\00", align 1
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
call void @"github.com/goplus/llgo/cl/internal/linktarget.F"(ptr @0, ptr @1, ptr @2, ptr @3)
call void @"github.com/goplus/llgo/cl/internal/linktarget.F"(ptr @4, ptr @5, ptr @6, ptr @7)
ret void
}
declare void @"github.com/goplus/llgo/cl/internal/linktarget.F"(ptr, ptr, ptr, ptr)
declare void @"github.com/goplus/llgo/internal/runtime.init"()

13
cl/_testrt/map/in.go Normal file
View File

@@ -0,0 +1,13 @@
package main
/*
import (
"github.com/goplus/llgo/internal/runtime/c"
)
*/
func main() {
a := map[int]int{23: 100, 7: 29}
_ = a
// c.Printf(c.Str("Hello %d\n"), a[23])
}

29
cl/_testrt/map/out.ll Normal file
View File

@@ -0,0 +1,29 @@
; ModuleID = 'main'
source_filename = "main"
@"main.init$guard" = global ptr null
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.MakeSmallMap"()
ret void
}
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare ptr @"github.com/goplus/llgo/internal/runtime.MakeSmallMap"()

5
cl/_testrt/panic/in.go Normal file
View File

@@ -0,0 +1,5 @@
package main
func main() {
panic("panic message")
}

39
cl/_testrt/panic/out.ll Normal file
View File

@@ -0,0 +1,39 @@
; ModuleID = 'main'
source_filename = "main"
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
%"github.com/goplus/llgo/internal/runtime.iface" = type { ptr, ptr }
@"main.init$guard" = global ptr null
@0 = private unnamed_addr constant [14 x i8] c"panic message\00", align 1
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%0 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @0, i64 13)
%1 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %0)
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %1)
unreachable
}
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64)
declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String")
declare void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface")

20
cl/_testrt/qsort/in.go Normal file
View File

@@ -0,0 +1,20 @@
package main
import (
"unsafe"
"github.com/goplus/llgo/internal/runtime/c"
)
//go:linkname qsort C.qsort
func qsort(base c.Pointer, count, elem uintptr, compar func(a, b c.Pointer) c.Int)
func main() {
a := [...]int{100, 8, 23, 2, 7}
qsort(c.Pointer(&a[0]), 5, unsafe.Sizeof(0), func(a, b c.Pointer) c.Int {
return c.Int(*(*int)(a) - *(*int)(b))
})
for _, v := range a {
c.Printf(c.Str("%d\n"), v)
}
}

71
cl/_testrt/qsort/out.ll Normal file
View File

@@ -0,0 +1,71 @@
; ModuleID = 'main'
source_filename = "main"
@"main.init$guard" = global ptr null
@0 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 40)
%1 = getelementptr inbounds i64, ptr %0, i64 0
%2 = getelementptr inbounds i64, ptr %0, i64 1
%3 = getelementptr inbounds i64, ptr %0, i64 2
%4 = getelementptr inbounds i64, ptr %0, i64 3
%5 = getelementptr inbounds i64, ptr %0, i64 4
store i64 100, ptr %1, align 4
store i64 8, ptr %2, align 4
store i64 23, ptr %3, align 4
store i64 2, ptr %4, align 4
store i64 7, ptr %5, align 4
%6 = getelementptr inbounds i64, ptr %0, i64 0
call void @qsort(ptr %6, i64 5, i64 8, ptr @"main.main$1")
%7 = load [5 x i64], ptr %0, align 4
br label %_llgo_1
_llgo_1: ; preds = %_llgo_2, %_llgo_0
%8 = phi i64 [ -1, %_llgo_0 ], [ %9, %_llgo_2 ]
%9 = add i64 %8, 1
%10 = icmp slt i64 %9, 5
br i1 %10, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1
%11 = getelementptr inbounds i64, ptr %0, i64 %9
%12 = load i64, ptr %11, align 4
%13 = call i32 (ptr, ...) @printf(ptr @0, i64 %12)
br label %_llgo_1
_llgo_3: ; preds = %_llgo_1
ret void
}
declare void @qsort(ptr, i64, i64, ptr)
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
define i32 @"main.main$1"(ptr %0, ptr %1) {
_llgo_0:
%2 = load i64, ptr %0, align 4
%3 = load i64, ptr %1, align 4
%4 = sub i64 %2, %3
%5 = trunc i64 %4 to i32
ret i32 %5
}
declare i32 @printf(ptr, ...)

17
cl/_testrt/strlen/in.go Normal file
View File

@@ -0,0 +1,17 @@
package main
import "C"
import _ "unsafe"
//go:linkname printf C.printf
func printf(format *int8, __llgo_va_list ...any)
//go:linkname strlen C.strlen
func strlen(str *int8) C.int
var format = [...]int8{'H', 'e', 'l', 'l', 'o', ' ', '%', 'd', '\n', 0}
func main() {
sfmt := &format[0]
printf(sfmt, strlen(sfmt))
}

43
cl/_testrt/strlen/out.ll Normal file
View File

@@ -0,0 +1,43 @@
; ModuleID = 'main'
source_filename = "main"
@main.format = global ptr null
@"main.init$guard" = global ptr null
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
store i8 72, ptr @main.format, align 1
store i8 101, ptr getelementptr inbounds (i8, ptr @main.format, i64 1), align 1
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 2), align 1
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 3), align 1
store i8 111, ptr getelementptr inbounds (i8, ptr @main.format, i64 4), align 1
store i8 32, ptr getelementptr inbounds (i8, ptr @main.format, i64 5), align 1
store i8 37, ptr getelementptr inbounds (i8, ptr @main.format, i64 6), align 1
store i8 100, ptr getelementptr inbounds (i8, ptr @main.format, i64 7), align 1
store i8 10, ptr getelementptr inbounds (i8, ptr @main.format, i64 8), align 1
store i8 0, ptr getelementptr inbounds (i8, ptr @main.format, i64 9), align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%0 = call i32 @strlen(ptr @main.format)
call void (ptr, ...) @printf(ptr @main.format, i32 %0)
ret void
}
declare void @printf(ptr, ...)
declare i32 @strlen(ptr)
declare void @"github.com/goplus/llgo/internal/runtime.init"()

25
cl/_testrt/struct/in.go Normal file
View File

@@ -0,0 +1,25 @@
package main
import "C"
import _ "unsafe"
//go:linkname printf C.printf
func printf(format *int8, __llgo_va_list ...any)
type Foo struct {
A C.int
ok bool
}
var format = [...]int8{'H', 'e', 'l', 'l', 'o', ' ', '%', 'd', '\n', 0}
func (p Foo) Print() {
if p.ok {
printf(&format[0], p.A)
}
}
func main() {
foo := Foo{100, true}
foo.Print()
}

77
cl/_testrt/struct/out.ll Normal file
View File

@@ -0,0 +1,77 @@
; ModuleID = 'main'
source_filename = "main"
%main.Foo = type { i32, i1 }
@main.format = global ptr null
@"main.init$guard" = global ptr null
define void @"(main.Foo).Print"(%main.Foo %0) {
_llgo_0:
%1 = alloca %main.Foo, align 8
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %1, i64 8)
store %main.Foo %0, ptr %2, align 4
%3 = getelementptr inbounds %main.Foo, ptr %2, i32 0, i32 1
%4 = load i1, ptr %3, align 1
br i1 %4, label %_llgo_1, label %_llgo_2
_llgo_1: ; preds = %_llgo_0
%5 = getelementptr inbounds %main.Foo, ptr %2, i32 0, i32 0
%6 = load i32, ptr %5, align 4
call void (ptr, ...) @printf(ptr @main.format, i32 %6)
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @"(*main.Foo).Print"(ptr %0) {
_llgo_0:
%1 = load %main.Foo, ptr %0, align 4
call void @"(main.Foo).Print"(%main.Foo %1)
ret void
}
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
store i8 72, ptr @main.format, align 1
store i8 101, ptr getelementptr inbounds (i8, ptr @main.format, i64 1), align 1
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 2), align 1
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 3), align 1
store i8 111, ptr getelementptr inbounds (i8, ptr @main.format, i64 4), align 1
store i8 32, ptr getelementptr inbounds (i8, ptr @main.format, i64 5), align 1
store i8 37, ptr getelementptr inbounds (i8, ptr @main.format, i64 6), align 1
store i8 100, ptr getelementptr inbounds (i8, ptr @main.format, i64 7), align 1
store i8 10, ptr getelementptr inbounds (i8, ptr @main.format, i64 8), align 1
store i8 0, ptr getelementptr inbounds (i8, ptr @main.format, i64 9), align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%0 = alloca %main.Foo, align 8
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %0, i64 8)
%2 = getelementptr inbounds %main.Foo, ptr %1, i32 0, i32 0
%3 = getelementptr inbounds %main.Foo, ptr %1, i32 0, i32 1
store i32 100, ptr %2, align 4
store i1 true, ptr %3, align 1
%4 = load %main.Foo, ptr %1, align 4
call void @"(main.Foo).Print"(%main.Foo %4)
ret void
}
declare void @printf(ptr, ...)
declare ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr, i64)
declare void @"github.com/goplus/llgo/internal/runtime.init"()

16
cl/_testrt/sum/in.go Normal file
View 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))
}

74
cl/_testrt/sum/out.ll Normal file
View File

@@ -0,0 +1,74 @@
; ModuleID = 'main'
source_filename = "main"
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 }
@"main.init$guard" = global ptr null
@0 = private unnamed_addr constant [10 x i8] c"Hello %d\0A\00", align 1
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
%1 = getelementptr inbounds i64, ptr %0, i64 0
store i64 1, ptr %1, align 4
%2 = getelementptr inbounds i64, ptr %0, i64 1
store i64 2, ptr %2, align 4
%3 = getelementptr inbounds i64, ptr %0, i64 2
store i64 3, ptr %3, align 4
%4 = getelementptr inbounds i64, ptr %0, i64 3
store i64 4, ptr %4, align 4
%5 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %0, i64 8, i64 4, i64 0, i64 4, i64 4)
%6 = call i64 @main.sum(%"github.com/goplus/llgo/internal/runtime.Slice" %5)
%7 = call i32 (ptr, ...) @printf(ptr @0, i64 %6)
ret void
}
define i64 @main.sum(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
_llgo_0:
%1 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %0)
br label %_llgo_1
_llgo_1: ; preds = %_llgo_2, %_llgo_0
%2 = phi i64 [ 0, %_llgo_0 ], [ %9, %_llgo_2 ]
%3 = phi i64 [ -1, %_llgo_0 ], [ %4, %_llgo_2 ]
%4 = add i64 %3, 1
%5 = icmp slt i64 %4, %1
br i1 %5, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1
%6 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %0)
%7 = getelementptr inbounds i64, ptr %6, i64 %4
%8 = load i64, ptr %7, align 4
%9 = add i64 %2, %8
br label %_llgo_1
_llgo_3: ; preds = %_llgo_1
ret i64 %2
}
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64)
declare i32 @printf(ptr, ...)
declare i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice")
declare ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice")

25
cl/_testrt/typalias/in.go Normal file
View File

@@ -0,0 +1,25 @@
package main
import "C"
import _ "unsafe"
//go:linkname printf C.printf
func printf(format *int8, __llgo_va_list ...any)
type Foo = struct {
A C.int
ok bool
}
var format = [...]int8{'H', 'e', 'l', 'l', 'o', ' ', '%', 'd', '\n', 0}
func Print(p *Foo) {
if p.ok {
printf(&format[0], p.A)
}
}
func main() {
foo := &Foo{100, true}
Print(foo)
}

View File

@@ -0,0 +1,63 @@
; ModuleID = 'main'
source_filename = "main"
@main.format = global ptr null
@"main.init$guard" = global ptr null
define void @main.Print(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds { i32, i1 }, ptr %0, i32 0, i32 1
%2 = load i1, ptr %1, align 1
br i1 %2, label %_llgo_1, label %_llgo_2
_llgo_1: ; preds = %_llgo_0
%3 = getelementptr inbounds { i32, i1 }, ptr %0, i32 0, i32 0
%4 = load i32, ptr %3, align 4
call void (ptr, ...) @printf(ptr @main.format, i32 %4)
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
store i8 72, ptr @main.format, align 1
store i8 101, ptr getelementptr inbounds (i8, ptr @main.format, i64 1), align 1
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 2), align 1
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 3), align 1
store i8 111, ptr getelementptr inbounds (i8, ptr @main.format, i64 4), align 1
store i8 32, ptr getelementptr inbounds (i8, ptr @main.format, i64 5), align 1
store i8 37, ptr getelementptr inbounds (i8, ptr @main.format, i64 6), align 1
store i8 100, ptr getelementptr inbounds (i8, ptr @main.format, i64 7), align 1
store i8 10, ptr getelementptr inbounds (i8, ptr @main.format, i64 8), align 1
store i8 0, ptr getelementptr inbounds (i8, ptr @main.format, i64 9), align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 8)
%1 = getelementptr inbounds { i32, i1 }, ptr %0, i32 0, i32 0
%2 = getelementptr inbounds { i32, i1 }, ptr %0, i32 0, i32 1
store i32 100, ptr %1, align 4
store i1 true, ptr %2, align 1
call void @main.Print(ptr %0)
ret void
}
declare void @printf(ptr, ...)
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)

View File

@@ -0,0 +1,14 @@
package main
import (
"github.com/goplus/llgo/internal/runtime/c"
)
func foo() {
c.Unreachable()
}
func main() {
foo()
c.Printf(c.Str("Hello\n"))
}

View File

@@ -0,0 +1,37 @@
; ModuleID = 'main'
source_filename = "main"
@"main.init$guard" = global ptr null
@0 = private unnamed_addr constant [7 x i8] c"Hello\0A\00", align 1
define void @main.foo() {
_llgo_0:
unreachable
ret void
}
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @main() {
_llgo_0:
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
call void @main.foo()
%0 = call i32 (ptr, ...) @printf(ptr @0)
ret void
}
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare i32 @printf(ptr, ...)

185
cl/builtin_test.go Normal file
View File

@@ -0,0 +1,185 @@
/*
* 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 cl
import (
"go/constant"
"go/types"
"testing"
llssa "github.com/goplus/llgo/ssa"
"golang.org/x/tools/go/ssa"
)
func TestErrCompileValue(t *testing.T) {
defer func() {
if r := recover(); r != "can't use llgo instruction as a value" {
t.Fatal("TestErrCompileValue:", r)
}
}()
pkg := types.NewPackage("foo", "foo")
ctx := &context{
goTyps: pkg,
link: map[string]string{
"foo.": "llgo.unreachable",
},
}
ctx.compileValue(nil, &ssa.Function{
Pkg: &ssa.Package{Pkg: pkg},
Signature: types.NewSignatureType(nil, nil, nil, nil, nil, false),
})
}
func TestErrCompileInstrOrValue(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Fatal("compileInstrOrValue: no error?")
}
}()
ctx := &context{
bvals: make(map[ssa.Value]llssa.Expr),
}
ctx.compileInstrOrValue(nil, &ssa.Call{}, true)
}
func TestErrAdvance(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Fatal("advance: no error?")
}
}()
var ctx context
ctx.advance(nil, nil)
}
func TestErrAlloca(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Fatal("alloca: no error?")
}
}()
var ctx context
ctx.alloca(nil, nil)
}
func TestCStrNoArgs(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Fatal("cstr: no error?")
}
}()
cstr(nil, nil)
}
func TestCStrNonconst(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Fatal("cstr: no error?")
}
}()
cstr(nil, []ssa.Value{&ssa.Parameter{}})
}
func TestPkgNoInit(t *testing.T) {
pkg := types.NewPackage("foo", "foo")
ctx := &context{
goTyps: pkg,
loaded: make(map[*types.Package]*pkgInfo),
}
if ctx.pkgNoInit(pkg) {
t.Fatal("pkgNoInit?")
}
}
func TestPkgKind(t *testing.T) {
if v := pkgKind("noinit"); v != PkgNoInit {
t.Fatal("pkgKind:", v)
}
if v := pkgKind(""); v != PkgLLGo {
t.Fatal("pkgKind:", v)
}
}
func TestPkgKindOf(t *testing.T) {
if v := PkgKindOf(types.Unsafe); v != PkgDeclOnly {
t.Fatal("PkgKindOf unsafe:", v)
}
pkg := types.NewPackage("foo", "foo")
pkg.Scope().Insert(
types.NewConst(
0, pkg, "LLGoPackage", types.Typ[types.String],
constant.MakeString("noinit")),
)
if v := PkgKindOf(pkg); v != PkgNoInit {
t.Fatal("PkgKindOf foo:", v)
}
}
func TestIsAny(t *testing.T) {
if isAny(types.Typ[types.UntypedInt]) {
t.Fatal("isAny?")
}
}
func TestIntVal(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Fatal("intVal: no error?")
}
}()
intVal(&ssa.Parameter{})
}
func TestIgnoreName(t *testing.T) {
if !ignoreName("runtime.foo") || !ignoreName("runtime/foo") || !ignoreName("internal/abi") {
t.Fatal("ignoreName failed")
}
}
func TestErrImport(t *testing.T) {
var ctx context
pkg := types.NewPackage("foo", "foo")
ctx.importPkg(pkg, nil)
}
func TestErrInitLinkname(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Fatal("initLinkname: no error?")
}
}()
var ctx context
ctx.initLinkname("foo", "//go:linkname Printf printf", false)
}
func TestErrVarOf(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Fatal("varOf: no error?")
}
}()
prog := llssa.NewProgram(nil)
pkg := prog.NewPackage("foo", "foo")
pkgTypes := types.NewPackage("foo", "foo")
ctx := &context{
pkg: pkg,
goTyps: pkgTypes,
}
ssaPkg := &ssa.Package{Pkg: pkgTypes}
g := &ssa.Global{Pkg: ssaPkg}
ctx.varOf(g)
}

131
cl/cltest/cltest.go Normal file
View File

@@ -0,0 +1,131 @@
/*
* 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 cltest
import (
"go/ast"
"go/parser"
"go/token"
"go/types"
"log"
"os"
"path"
"strings"
"testing"
"github.com/goplus/gogen/packages"
"github.com/goplus/llgo/cl"
"github.com/goplus/llgo/internal/llgen"
"golang.org/x/tools/go/ssa"
"golang.org/x/tools/go/ssa/ssautil"
llssa "github.com/goplus/llgo/ssa"
)
func init() {
cl.SetDebug(cl.DbgFlagAll)
llssa.Initialize(llssa.InitAll)
llssa.SetDebug(llssa.DbgFlagAll)
}
func FromDir(t *testing.T, sel, relDir string, byLLGen bool) {
dir, err := os.Getwd()
if err != nil {
t.Fatal("Getwd failed:", err)
}
dir = path.Join(dir, relDir)
fis, err := os.ReadDir(dir)
if err != nil {
t.Fatal("ReadDir failed:", err)
}
for _, fi := range fis {
name := fi.Name()
if !fi.IsDir() || strings.HasPrefix(name, "_") {
continue
}
t.Run(name, func(t *testing.T) {
testFrom(t, dir+"/"+name, sel, byLLGen)
})
}
}
func Pkg(t *testing.T, pkgPath, outFile string) {
b, err := os.ReadFile(outFile)
if err != nil {
t.Fatal("ReadFile failed:", err)
}
expected := string(b)
if v := llgen.GenFrom(pkgPath); v != expected {
t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected)
}
}
func testFrom(t *testing.T, pkgDir, sel string, byLLGen bool) {
if sel != "" && !strings.Contains(pkgDir, sel) {
return
}
log.Println("Parsing", pkgDir)
in := pkgDir + "/in.go"
out := pkgDir + "/out.ll"
b, err := os.ReadFile(out)
if err != nil {
t.Fatal("ReadFile failed:", err)
}
expected := string(b)
if byLLGen {
if v := llgen.GenFrom(in); v != expected {
t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected)
}
} else {
TestCompileEx(t, nil, in, expected)
}
}
func TestCompileEx(t *testing.T, src any, fname, expected string) {
t.Helper()
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, fname, src, parser.ParseComments)
if err != nil {
t.Fatal("ParseFile failed:", err)
}
files := []*ast.File{f}
name := f.Name.Name
pkg := types.NewPackage(name, name)
imp := packages.NewImporter(fset)
foo, _, err := ssautil.BuildPackage(
&types.Config{Importer: imp}, fset, pkg, files, ssa.SanityCheckFunctions)
if err != nil {
t.Fatal("BuildPackage failed:", err)
}
foo.WriteTo(os.Stderr)
prog := llssa.NewProgram(nil)
prog.SetRuntime(func() *types.Package {
rt, err := imp.Import(llssa.PkgRuntime)
if err != nil {
t.Fatal("load runtime failed:", err)
}
return rt
})
ret, err := cl.NewPackage(prog, foo, files)
if err != nil {
t.Fatal("cl.NewPackage failed:", err)
}
if v := ret.String(); v != expected {
t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected)
}
}

View File

@@ -18,9 +18,14 @@ package cl
import (
"fmt"
"go/ast"
"go/constant"
"go/token"
"go/types"
"log"
"os"
"sort"
"strings"
llssa "github.com/goplus/llgo/ssa"
"golang.org/x/tools/go/ssa"
@@ -53,18 +58,19 @@ func SetDebug(dbgFlags dbgFlags) {
const (
fnNormal = iota
fnHasVArg
fnUnsafeInit
fnIgnore
)
func funcKind(vfn ssa.Value) int {
if fn, ok := vfn.(*ssa.Function); ok {
n := len(fn.Params)
func (p *context) funcKind(vfn ssa.Value) int {
if fn, ok := vfn.(*ssa.Function); ok && fn.Signature.Recv() == nil {
params := fn.Signature.Params()
n := params.Len()
if n == 0 {
if fn.Name() == "init" && fn.Pkg.Pkg.Path() == "unsafe" {
return fnUnsafeInit
if fn.Name() == "init" && p.pkgNoInit(fn.Pkg.Pkg) {
return fnIgnore
}
} else {
last := fn.Params[n-1]
last := params.At(n - 1)
if last.Name() == llssa.NameValist {
return fnHasVArg
}
@@ -73,51 +79,149 @@ func funcKind(vfn ssa.Value) int {
return fnNormal
}
func isMainFunc(fn *ssa.Function) bool {
return fn.Name() == "main" && fn.Pkg.Pkg.Path() == "main"
func (p *context) pkgNoInit(pkg *types.Package) bool {
p.ensureLoaded(pkg)
if i, ok := p.loaded[pkg]; ok {
return i.kind >= PkgNoInit
}
return false
}
func ignoreName(name string) bool {
/* TODO(xsw): confirm this is not needed more
if name == "unsafe.init" {
return true
}
*/
if strings.HasPrefix(name, "internal/") || strings.HasPrefix(name, "crypto/") ||
strings.HasPrefix(name, "arena.") || strings.HasPrefix(name, "maps.") ||
strings.HasPrefix(name, "time.") || strings.HasPrefix(name, "syscall.") ||
strings.HasPrefix(name, "os.") || strings.HasPrefix(name, "plugin.") ||
strings.HasPrefix(name, "reflect.") || strings.HasPrefix(name, "errors.") {
return true // TODO(xsw)
}
return inPkg(name, "runtime") || inPkg(name, "sync")
}
func inPkg(name, pkg string) bool {
if len(name) > len(pkg) && strings.HasPrefix(name, pkg) {
c := name[len(pkg)]
return c == '.' || c == '/'
}
return false
}
// -----------------------------------------------------------------------------
type instrAndValue interface {
type instrOrValue interface {
ssa.Instruction
ssa.Value
}
const (
PkgNormal = iota
PkgLLGo
PkgNoInit // noinit: a package that don't need to be initialized
PkgDeclOnly // decl: a package that only have declarations
)
type pkgInfo struct {
kind int
}
type context struct {
prog llssa.Program
pkg llssa.Package
fn llssa.Function
fset *token.FileSet
goProg *ssa.Program
goTyps *types.Package
goPkg *ssa.Package
link map[string]string // pkgPath.nameInPkg => linkname
loaded map[*types.Package]*pkgInfo // loaded packages
bvals map[ssa.Value]llssa.Expr // block values
vargs map[*ssa.Alloc][]llssa.Expr // varargs
inits []func()
phis []func()
}
func (p *context) compileType(pkg llssa.Package, member *ssa.Type) {
panic("todo")
func (p *context) compileType(pkg llssa.Package, t *ssa.Type) {
tn := t.Object().(*types.TypeName)
if tn.IsAlias() { // don't need to compile alias type
return
}
tnName := tn.Name()
typ := tn.Type()
name := llssa.FullName(tn.Pkg(), tnName)
if ignoreName(name) {
return
}
if debugInstr {
log.Println("==> NewType", name, typ)
}
p.compileMethods(pkg, typ)
p.compileMethods(pkg, types.NewPointer(typ))
}
func (p *context) compileMethods(pkg llssa.Package, typ types.Type) {
prog := p.goProg
mthds := prog.MethodSets.MethodSet(typ)
for i, n := 0, mthds.Len(); i < n; i++ {
mthd := mthds.At(i)
if ssaMthd := prog.MethodValue(mthd); ssaMthd != nil {
p.compileFunc(pkg, mthd.Obj().Pkg(), ssaMthd, false)
}
}
}
// Global variable.
func (p *context) compileGlobal(pkg llssa.Package, gbl *ssa.Global) {
name, typ := gbl.Name(), gbl.Type()
typ := gbl.Type()
name, vtype := p.varName(gbl.Pkg.Pkg, gbl)
if ignoreName(name) || checkCgo(gbl.Name()) {
return
}
if debugInstr {
log.Println("==> NewVar", name, typ)
}
if vtype == cVar {
typ = llssa.CType(typ)
}
g := pkg.NewVar(name, typ)
if vtype == goVar {
g.Init(p.prog.Null(g.Type))
}
}
func (p *context) compileFunc(pkg llssa.Package, f *ssa.Function) {
name := f.Name()
func (p *context) compileFunc(pkg llssa.Package, pkgTypes *types.Package, f *ssa.Function, closure bool) llssa.Function {
var sig = f.Signature
var name string
if closure {
name = funcName(pkgTypes, f)
if debugInstr {
log.Println("==> NewFunc", name)
log.Println("==> NewClosure", name, "type:", sig)
}
fn := pkg.NewFunc(name, f.Signature)
} else {
var ftype int
name, ftype = p.funcName(pkgTypes, f, true)
switch ftype {
case ignoredFunc, llgoInstr: // llgo extended instructions
return nil
}
if debugInstr {
log.Println("==> NewFunc", name, "type:", sig.Recv(), sig)
}
if ftype == cFunc {
sig = llssa.CFuncDecl(sig)
}
}
fn := pkg.NewFunc(name, sig)
p.inits = append(p.inits, func() {
p.fn = fn
defer func() {
p.fn = nil
}()
p.phis = nil
nblk := len(f.Blocks)
if nblk == 0 { // external function
return
@@ -130,44 +234,213 @@ func (p *context) compileFunc(pkg llssa.Package, f *ssa.Function) {
}
fn.MakeBlocks(nblk)
b := fn.NewBuilder()
isMain := isMainFunc(f)
p.bvals = make(map[ssa.Value]llssa.Expr)
for i, block := range f.Blocks {
p.compileBlock(b, block, isMain && i == 0)
p.compileBlock(b, block, i == 0 && name == "main")
}
for _, phi := range p.phis {
phi()
}
})
return fn
}
func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, doInit bool) llssa.BasicBlock {
ret := p.fn.Block(block.Index)
b.SetBlock(ret)
p.bvals = make(map[ssa.Value]llssa.Expr)
if doInit {
fn := p.pkg.FuncOf("init")
b.Call(fn.Expr)
pkg := p.pkg
callRuntimeInit(b, pkg)
b.Call(pkg.FuncOf("main.init").Expr)
}
for _, instr := range block.Instrs {
instrs := p.compilePhis(b, block.Instrs)
for _, instr := range instrs {
p.compileInstr(b, instr)
}
return ret
}
func (p *context) compileInstrAndValue(b llssa.Builder, iv instrAndValue) (ret llssa.Expr) {
const (
RuntimeInit = llssa.PkgRuntime + ".init"
)
func callRuntimeInit(b llssa.Builder, pkg llssa.Package) {
fn := pkg.NewFunc(RuntimeInit, types.NewSignatureType(nil, nil, nil, nil, nil, false))
b.Call(fn.Expr)
}
func isAny(t types.Type) bool {
if t, ok := t.(*types.Interface); ok {
return t.Empty()
}
return false
}
func intVal(v ssa.Value) int64 {
if c, ok := v.(*ssa.Const); ok {
if iv, exact := constant.Int64Val(c.Value); exact {
return iv
}
}
panic("intVal: ssa.Value is not a const int")
}
func (p *context) isVArgs(vx ssa.Value) (ret []llssa.Expr, ok bool) {
if va, vok := vx.(*ssa.Alloc); vok {
ret, ok = p.vargs[va] // varargs: this is a varargs index
}
return
}
func (p *context) checkVArgs(v *ssa.Alloc, t *types.Pointer) bool {
if v.Comment == "varargs" { // this is a varargs allocation
if arr, ok := t.Elem().(*types.Array); ok {
if isAny(arr.Elem()) {
p.vargs[v] = make([]llssa.Expr, arr.Len())
return true
}
}
}
return false
}
// func cstr(string) *int8
func cstr(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
if len(args) == 1 {
if c, ok := args[0].(*ssa.Const); ok {
if v := c.Value; v.Kind() == constant.String {
sv := constant.StringVal(v)
return b.CStr(sv)
}
}
}
panic("cstr(<string-literal>): invalid arguments")
}
func (p *context) advance(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
if len(args) == 2 {
ptr := p.compileValue(b, args[0])
offset := p.compileValue(b, args[1])
return b.Advance(ptr, offset)
}
panic("advance(p ptr, offset int): invalid arguments")
}
// func alloca(size uintptr) unsafe.Pointer
func (p *context) alloca(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
if len(args) == 1 {
n := p.compileValue(b, args[0])
return b.Alloca(n)
}
panic("alloca(size uintptr): invalid arguments")
}
// func allocaCStr(s string) *int8
func (p *context) allocaCStr(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
if len(args) == 1 {
s := p.compileValue(b, args[0])
return b.AllocaCStr(s)
}
panic("allocaCStr(s string): invalid arguments")
}
func isPhi(i ssa.Instruction) bool {
_, ok := i.(*ssa.Phi)
return ok
}
func (p *context) compilePhis(b llssa.Builder, instrs []ssa.Instruction) []ssa.Instruction {
if ninstr := len(instrs); ninstr > 0 {
if isPhi(instrs[0]) {
n := 1
for n < ninstr && isPhi(instrs[n]) {
n++
}
rets := make([]llssa.Expr, n)
for i := 0; i < n; i++ {
iv := instrs[i].(*ssa.Phi)
rets[i] = p.compilePhi(b, iv)
}
for i := 0; i < n; i++ {
iv := instrs[i].(*ssa.Phi)
p.bvals[iv] = rets[i].Do(b)
}
return instrs[n:]
}
}
return instrs
}
func (p *context) compilePhi(b llssa.Builder, v *ssa.Phi) (ret llssa.Expr) {
phi := b.Phi(p.prog.Type(v.Type()))
ret = phi.Expr
p.phis = append(p.phis, func() {
preds := v.Block().Preds
bblks := make([]llssa.BasicBlock, len(preds))
for i, pred := range preds {
bblks[i] = p.fn.Block(pred.Index)
}
edges := v.Edges
phi.AddIncoming(b, bblks, func(i int) llssa.Expr {
return p.compileValue(b, edges[i])
})
})
return
}
func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue bool) (ret llssa.Expr) {
if asValue {
if v, ok := p.bvals[iv]; ok {
return v
}
log.Panicln("unreachable:", iv)
}
switch v := iv.(type) {
case *ssa.Call:
call := v.Call
kind := funcKind(call.Value)
if kind == fnUnsafeInit {
cv := call.Value
kind := p.funcKind(cv)
if kind == fnIgnore {
return
}
if debugGoSSA {
log.Println(">>> Call", call.Value, call.Args)
log.Println(">>> Call", cv, call.Args)
}
fn := p.compileValue(b, call.Value)
switch cv := cv.(type) {
case *ssa.Builtin:
fn := cv.Name()
if fn == "ssa:wrapnilchk" { // TODO(xsw): check nil ptr
arg := call.Args[0]
ret = p.compileValue(b, arg)
// log.Println("wrapnilchk:", ret.TypeOf())
} else {
args := p.compileValues(b, call.Args, kind)
ret = b.BuiltinCall(fn, args...)
}
case *ssa.Function:
fn, ftype := p.funcOf(cv)
switch ftype {
case goFunc, cFunc:
args := p.compileValues(b, call.Args, kind)
ret = b.Call(fn.Expr, args...)
case llgoCstr:
ret = cstr(b, call.Args)
case llgoAdvance:
ret = p.advance(b, call.Args)
case llgoAlloca:
ret = p.alloca(b, call.Args)
case llgoAllocaCStr:
ret = p.allocaCStr(b, call.Args)
case llgoUnreachable: // func unreachable()
b.Unreachable()
default:
panic("todo")
}
default:
fn := p.compileValue(b, cv)
args := p.compileValues(b, call.Args, kind)
ret = b.Call(fn, args...)
}
case *ssa.BinOp:
x := p.compileValue(b, v.X)
y := p.compileValue(b, v.Y)
@@ -175,13 +448,84 @@ func (p *context) compileInstrAndValue(b llssa.Builder, iv instrAndValue) (ret l
case *ssa.UnOp:
x := p.compileValue(b, v.X)
ret = b.UnOp(v.Op, x)
case *ssa.IndexAddr:
case *ssa.ChangeType:
t := v.Type()
x := p.compileValue(b, v.X)
ret = b.ChangeType(p.prog.Type(t), x)
case *ssa.Convert:
t := v.Type()
x := p.compileValue(b, v.X)
ret = b.Convert(p.prog.Type(t), x)
case *ssa.FieldAddr:
x := p.compileValue(b, v.X)
ret = b.FieldAddr(x, v.Field)
case *ssa.Alloc:
t := v.Type().(*types.Pointer)
if p.checkVArgs(v, t) { // varargs: this is a varargs allocation
return
}
ret = b.Alloc(t, v.Heap)
case *ssa.IndexAddr:
vx := v.X
if _, ok := p.isVArgs(vx); ok { // varargs: this is a varargs index
return
}
x := p.compileValue(b, vx)
idx := p.compileValue(b, v.Index)
ret = b.IndexAddr(x, idx)
case *ssa.Alloc:
case *ssa.Index:
x := p.compileValue(b, v.X)
idx := p.compileValue(b, v.Index)
ret = b.Index(x, idx, func(e llssa.Expr) (ret llssa.Expr) {
if e == x {
if n, ok := v.X.(*ssa.UnOp); ok {
return p.compileValue(b, n.X)
}
}
panic(fmt.Errorf("todo addr of %v", e))
})
case *ssa.Slice:
vx := v.X
if _, ok := p.isVArgs(vx); ok { // varargs: this is a varargs slice
return
}
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.MakeInterface:
const (
delayExpr = true // varargs: don't need to convert an expr to any
)
t := v.Type()
ret = b.Alloc(p.prog.Type(t), v.Heap)
x := p.compileValue(b, v.X)
ret = b.MakeInterface(t, x, delayExpr)
case *ssa.MakeSlice:
var nCap llssa.Expr
t := v.Type()
nLen := p.compileValue(b, v.Len)
if v.Cap != nil {
nCap = p.compileValue(b, v.Cap)
}
ret = b.MakeSlice(p.prog.Type(t), nLen, nCap)
case *ssa.MakeMap:
var nReserve llssa.Expr
t := v.Type()
if v.Reserve != nil {
nReserve = p.compileValue(b, v.Reserve)
}
ret = b.MakeMap(p.prog.Type(t), nReserve)
case *ssa.TypeAssert:
x := p.compileValue(b, v.X)
ret = b.TypeAssert(x, p.prog.Type(v.AssertedType), v.CommaOk)
default:
panic(fmt.Sprintf("compileInstrAndValue: unknown instr - %T\n", iv))
}
@@ -190,13 +534,25 @@ func (p *context) compileInstrAndValue(b llssa.Builder, iv instrAndValue) (ret l
}
func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) {
if iv, ok := instr.(instrAndValue); ok {
p.compileInstrAndValue(b, iv)
if iv, ok := instr.(instrOrValue); ok {
p.compileInstrOrValue(b, iv, false)
return
}
switch v := instr.(type) {
case *ssa.Store:
ptr := p.compileValue(b, v.Addr)
va := v.Addr
if va, ok := va.(*ssa.IndexAddr); ok {
if args, ok := p.isVArgs(va.X); ok { // varargs: this is a varargs store
idx := intVal(va.Index)
val := v.Val
if vi, ok := val.(*ssa.MakeInterface); ok {
val = vi.X
}
args[idx] = p.compileValue(b, val)
return
}
}
ptr := p.compileValue(b, va)
val := p.compileValue(b, v.Val)
b.Store(ptr, val)
case *ssa.Jump:
@@ -220,14 +576,22 @@ func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) {
thenb := fn.Block(succs[0].Index)
elseb := fn.Block(succs[1].Index)
b.If(cond, thenb, elseb)
case *ssa.MapUpdate:
m := p.compileValue(b, v.Map)
key := p.compileValue(b, v.Key)
val := p.compileValue(b, v.Value)
b.MapUpdate(m, key, val)
case *ssa.Panic:
arg := p.compileValue(b, v.X).Do(b)
b.Panic(arg)
default:
panic(fmt.Sprintf("compileInstr: unknown instr - %T\n", instr))
}
}
func (p *context) compileValue(b llssa.Builder, v ssa.Value) llssa.Expr {
if iv, ok := v.(instrAndValue); ok {
return p.compileInstrAndValue(b, iv)
if iv, ok := v.(instrOrValue); ok {
return p.compileInstrOrValue(b, iv, true)
}
switch v := v.(type) {
case *ssa.Parameter:
@@ -238,19 +602,20 @@ func (p *context) compileValue(b llssa.Builder, v ssa.Value) llssa.Expr {
}
}
case *ssa.Function:
if v.Pkg != p.goPkg {
panic("todo")
if v.Blocks != nil {
fn := p.compileFunc(p.pkg, p.goTyps, v, true)
return fn.Expr
}
fn, ftype := p.funcOf(v)
if ftype >= llgoInstrBase {
panic("can't use llgo instruction as a value")
}
fn := p.pkg.FuncOf(v.Name())
return fn.Expr
case *ssa.Global:
if v.Pkg != p.goPkg {
panic("todo")
}
g := p.pkg.VarOf(v.Name())
g := p.varOf(v)
return g.Expr
case *ssa.Const:
t := v.Type()
t := types.Default(v.Type())
return b.Const(v.Value, p.prog.Type(t))
}
panic(fmt.Sprintf("compileValue: unknown value - %T\n", v))
@@ -259,19 +624,23 @@ func (p *context) compileValue(b llssa.Builder, v ssa.Value) llssa.Expr {
func (p *context) compileVArg(ret []llssa.Expr, b llssa.Builder, v ssa.Value) []llssa.Expr {
_ = b
switch v := v.(type) {
case *ssa.Slice: // varargs: this is a varargs slice
if args, ok := p.isVArgs(v.X); ok {
return append(ret, args...)
}
case *ssa.Const:
if v.Value == nil {
return ret
}
}
panic("todo")
panic(fmt.Sprintf("compileVArg: unknown value - %T\n", v))
}
func (p *context) compileValues(b llssa.Builder, vals []ssa.Value, hasVArg int) []llssa.Expr {
n := len(vals) - hasVArg
ret := make([]llssa.Expr, n)
for i := 0; i < n; i++ {
ret[i] = p.compileValue(b, vals[i])
ret[i] = p.compileValue(b, vals[i]).Do(b)
}
if hasVArg > 0 {
ret = p.compileVArg(ret, b, vals[n])
@@ -281,37 +650,43 @@ func (p *context) compileValues(b llssa.Builder, vals []ssa.Value, hasVArg int)
// -----------------------------------------------------------------------------
type Config struct {
}
// NewPackage compiles a Go package to LLVM IR package.
func NewPackage(prog llssa.Program, pkg *ssa.Package, conf *Config) (ret llssa.Package, err error) {
func NewPackage(prog llssa.Program, pkg *ssa.Package, files []*ast.File) (ret llssa.Package, err error) {
type namedMember struct {
name string
val ssa.Member
}
// Sort by position, so that the order of the functions in the IR matches
// the order of functions in the source file. This is useful for testing,
// for example.
var members []*namedMember
members := make([]*namedMember, 0, len(pkg.Members))
for name, v := range pkg.Members {
members = append(members, &namedMember{name, v})
}
sort.Slice(members, func(i, j int) bool {
iPos := members[i].val.Pos()
jPos := members[j].val.Pos()
return iPos < jPos
return members[i].name < members[j].name
})
pkgProg := pkg.Prog
pkgTypes := pkg.Pkg
ret = prog.NewPackage(pkgTypes.Name(), pkgTypes.Path())
pkgName, pkgPath := pkgTypes.Name(), llssa.PathOf(pkgTypes)
if pkgPath == llssa.PkgRuntime {
prog.SetRuntime(pkgTypes)
}
ret = prog.NewPackage(pkgName, pkgPath)
ctx := &context{
prog: prog,
pkg: ret,
fset: pkgProg.Fset,
goProg: pkgProg,
goTyps: pkgTypes,
goPkg: pkg,
link: make(map[string]string),
vargs: make(map[*ssa.Alloc][]llssa.Expr),
loaded: map[*types.Package]*pkgInfo{
types.Unsafe: {kind: PkgDeclOnly}, // TODO(xsw): PkgNoInit or PkgDeclOnly?
},
}
ctx.initFiles(pkgPath, files)
for _, m := range members {
member := m.val
switch member := member.(type) {
@@ -320,16 +695,20 @@ func NewPackage(prog llssa.Program, pkg *ssa.Package, conf *Config) (ret llssa.P
// Do not try to build generic (non-instantiated) functions.
continue
}
ctx.compileFunc(ret, member)
ctx.compileFunc(ret, member.Pkg.Pkg, member, false)
case *ssa.Type:
ctx.compileType(ret, member)
case *ssa.Global:
ctx.compileGlobal(ret, member)
}
}
for _, ini := range ctx.inits {
for len(ctx.inits) > 0 {
inits := ctx.inits
ctx.inits = nil
for _, ini := range inits {
ini()
}
}
return
}

View File

@@ -14,99 +14,30 @@
* limitations under the License.
*/
package cl
package cl_test
import (
"go/ast"
"go/importer"
"go/parser"
"go/token"
"go/types"
"log"
"os"
"path"
"strings"
"testing"
llssa "github.com/goplus/llgo/ssa"
"golang.org/x/tools/go/ssa"
"golang.org/x/tools/go/ssa/ssautil"
"github.com/goplus/llgo/cl/cltest"
"github.com/goplus/llgo/ssa"
)
func TestFromTestdata(t *testing.T) {
testFromDir(t, "", "./_testdata")
}
func init() {
SetDebug(DbgFlagAll)
llssa.Initialize(llssa.InitAll)
llssa.SetDebug(llssa.DbgFlagAll)
}
func testFromDir(t *testing.T, sel, relDir string) {
dir, err := os.Getwd()
if err != nil {
t.Fatal("Getwd failed:", err)
}
dir = path.Join(dir, relDir)
fis, err := os.ReadDir(dir)
if err != nil {
t.Fatal("ReadDir failed:", err)
}
for _, fi := range fis {
name := fi.Name()
if !fi.IsDir() || strings.HasPrefix(name, "_") {
continue
}
t.Run(name, func(t *testing.T) {
testFrom(t, dir+"/"+name, sel)
})
}
}
func testFrom(t *testing.T, pkgDir, sel string) {
if sel != "" && !strings.Contains(pkgDir, sel) {
return
}
log.Println("Parsing", pkgDir)
in := pkgDir + "/in.go"
out := pkgDir + "/out.ll"
expected, err := os.ReadFile(out)
if err != nil {
t.Fatal("ReadFile failed:", err)
}
testCompileEx(t, nil, in, string(expected))
}
func testCompileEx(t *testing.T, src any, fname, expected string) {
t.Helper()
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, fname, src, parser.ParseComments)
if err != nil {
t.Fatal("ParseFile failed:", err)
}
files := []*ast.File{f}
name := f.Name.Name
pkg := types.NewPackage(name, name)
foo, _, err := ssautil.BuildPackage(
&types.Config{Importer: importer.Default()}, fset, pkg, files, ssa.SanityCheckFunctions)
if err != nil {
t.Fatal("BuildPackage failed:", err)
}
foo.WriteTo(os.Stderr)
prog := llssa.NewProgram(nil)
ret, err := NewPackage(prog, foo, nil)
if err != nil {
t.Fatal("cl.NewPackage failed:", err)
}
if v := ret.String(); v != expected {
t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected)
}
}
func testCompile(t *testing.T, src, expected string) {
t.Helper()
testCompileEx(t, src, "foo.go", expected)
cltest.TestCompileEx(t, src, "foo.go", expected)
}
func TestFromTestrt(t *testing.T) {
cltest.FromDir(t, "", "./_testrt", true)
}
func TestFromTestdata(t *testing.T) {
cltest.FromDir(t, "", "./_testdata", false)
}
func TestRuntime(t *testing.T) {
cltest.Pkg(t, ssa.PkgRuntime, "../internal/runtime/llgo_autogen.ll")
}
func TestVar(t *testing.T) {
@@ -116,16 +47,16 @@ var a int
`, `; ModuleID = 'foo'
source_filename = "foo"
@"init$guard" = global ptr null
@a = global ptr null
@foo.a = global ptr null
@"foo.init$guard" = global ptr null
define void @init() {
define void @foo.init() {
_llgo_0:
%0 = load i1, ptr @"init$guard", align 1
%0 = load i1, ptr @"foo.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"init$guard", align 1
store i1 true, ptr @"foo.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
@@ -143,24 +74,24 @@ func fn(a int, b float64) int {
`, `; ModuleID = 'foo'
source_filename = "foo"
@"init$guard" = global ptr null
@"foo.init$guard" = global ptr null
define void @init() {
define i64 @foo.fn(i64 %0, double %1) {
_llgo_0:
%0 = load i1, ptr @"init$guard", align 1
ret i64 1
}
define void @foo.init() {
_llgo_0:
%0 = load i1, ptr @"foo.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"init$guard", align 1
store i1 true, ptr @"foo.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define i64 @fn(i64 %0, double %1) {
_llgo_0:
ret i64 1
}
`)
}

293
cl/import.go Normal file
View File

@@ -0,0 +1,293 @@
/*
* 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 cl
import (
"bytes"
"go/ast"
"go/constant"
"go/token"
"go/types"
"os"
"strings"
llssa "github.com/goplus/llgo/ssa"
"golang.org/x/tools/go/ssa"
)
type contentLines = [][]byte
type contentMap = map[string]contentLines
func contentOf(m contentMap, file string) (lines contentLines, err error) {
if v, ok := m[file]; ok {
return v, nil
}
b, err := os.ReadFile(file)
if err == nil {
lines = bytes.Split(b, []byte{'\n'})
m[file] = lines
}
return
}
// PkgKindOf returns the kind of a package.
func PkgKindOf(pkg *types.Package) int {
scope := pkg.Scope()
kind := pkgKindByScope(scope)
if kind == PkgNormal {
kind = pkgKindByPath(pkg.Path())
}
return kind
}
// decl: a package that only contains declarations
// noinit: a package that does not need to be initialized
func pkgKind(v string) int {
switch v {
case "decl":
return PkgDeclOnly
case "noinit":
return PkgNoInit
}
return PkgLLGo
}
func pkgKindByScope(scope *types.Scope) int {
if v, ok := scope.Lookup("LLGoPackage").(*types.Const); ok {
if v := v.Val(); v.Kind() == constant.String {
return pkgKind(constant.StringVal(v))
}
return PkgLLGo
}
return PkgNormal
}
func (p *context) importPkg(pkg *types.Package, i *pkgInfo) {
scope := pkg.Scope()
kind := pkgKindByScope(scope)
if kind == PkgNormal {
return
}
i.kind = kind
fset := p.fset
names := scope.Names()
contents := make(contentMap)
pkgPath := llssa.PathOf(pkg)
for _, name := range names {
if token.IsExported(name) {
obj := scope.Lookup(name)
switch obj := obj.(type) {
case *types.Func:
if pos := obj.Pos(); pos != token.NoPos {
p.initLinknameByPos(fset, pos, pkgPath, contents, false)
}
case *types.Var:
if pos := obj.Pos(); pos != token.NoPos {
p.initLinknameByPos(fset, pos, pkgPath, contents, true)
}
}
}
}
}
func (p *context) initFiles(pkgPath string, files []*ast.File) {
for _, file := range files {
for _, decl := range file.Decls {
switch decl := decl.(type) {
case *ast.FuncDecl:
if decl.Recv == nil {
p.initLinknameByDoc(decl.Doc, pkgPath, false)
}
case *ast.GenDecl:
if decl.Tok == token.VAR && len(decl.Specs) == 1 {
p.initLinknameByDoc(decl.Doc, pkgPath, true)
}
}
}
}
}
func (p *context) initLinknameByDoc(doc *ast.CommentGroup, pkgPath string, isVar bool) {
if doc != nil {
if n := len(doc.List); n > 0 {
line := doc.List[n-1].Text
p.initLinkname(pkgPath, line, isVar)
}
}
}
func (p *context) initLinknameByPos(fset *token.FileSet, pos token.Pos, pkgPath string, contents contentMap, isVar bool) {
f := fset.File(pos)
if fp := f.Position(pos); fp.Line > 2 {
lines, err := contentOf(contents, fp.Filename)
if err != nil {
panic(err)
}
if i := fp.Line - 2; i < len(lines) {
line := string(lines[i])
p.initLinkname(pkgPath, line, isVar)
}
}
}
func (p *context) initLinkname(pkgPath, line string, isVar bool) {
const (
linkname = "//go:linkname "
)
if strings.HasPrefix(line, linkname) {
text := strings.TrimSpace(line[len(linkname):])
if idx := strings.IndexByte(text, ' '); idx > 0 {
link := strings.TrimLeft(text[idx+1:], " ")
if isVar || strings.Contains(link, ".") { // eg. C.printf, C.strlen, llgo.cstr
name := pkgPath + "." + text[:idx]
p.link[name] = link
} else {
panic(line + ": no specified call convention. eg. //go:linkname Printf C.printf")
}
}
}
}
// func: pkg.name
// method: (pkg.T).name, (*pkg.T).name
func funcName(pkg *types.Package, fn *ssa.Function) string {
sig := fn.Signature
name := fn.Name()
if recv := sig.Recv(); recv != nil {
var tName string
t := recv.Type()
if tp, ok := t.(*types.Pointer); ok {
t, tName = tp.Elem(), "*"
}
tName += llssa.NameOf(t.(*types.Named))
return "(" + tName + ")." + name
}
ret := llssa.FullName(pkg, name)
if ret == "main.main" {
ret = "main"
}
return ret
}
func checkCgo(fnName string) bool {
return len(fnName) > 4 && fnName[0] == '_' && fnName[2] == 'g' && fnName[3] == 'o' &&
(fnName[1] == 'C' || fnName[1] == 'c') &&
(fnName[4] == '_' || strings.HasPrefix(fnName[4:], "Check"))
}
const (
ignoredFunc = iota
goFunc
cFunc
llgoInstr = -1
llgoInstrBase = 0x80
llgoUnreachable = llgoInstrBase + 0
llgoCstr = llgoInstrBase + 1
llgoAlloca = llgoInstrBase + 2
llgoAllocaCStr = llgoInstrBase + 3
llgoAdvance = llgoInstrBase + 4
)
func (p *context) funcName(pkg *types.Package, fn *ssa.Function, ignore bool) (string, int) {
name := funcName(pkg, fn)
if ignore && ignoreName(name) || checkCgo(fn.Name()) {
return name, ignoredFunc
}
if v, ok := p.link[name]; ok {
if strings.HasPrefix(v, "C.") {
return v[2:], cFunc
}
if strings.HasPrefix(v, "llgo.") {
return v[5:], llgoInstr
}
return v, goFunc
}
return name, goFunc
}
const (
ignoredVar = iota
goVar
cVar
)
func (p *context) varName(pkg *types.Package, v *ssa.Global) (vName string, vtype int) {
name := llssa.FullName(pkg, v.Name())
if v, ok := p.link[name]; ok {
return v, cVar
}
return name, goVar
}
// funcOf returns a function by name and set ftype = goFunc, cFunc, etc.
// or returns nil and set ftype = llgoCstr, llgoAlloca, llgoUnreachable, etc.
func (p *context) funcOf(fn *ssa.Function) (ret llssa.Function, ftype int) {
pkgTypes := p.ensureLoaded(fn.Pkg.Pkg)
pkg := p.pkg
name, ftype := p.funcName(pkgTypes, fn, false)
if ftype == llgoInstr {
switch name {
case "cstr":
ftype = llgoCstr
case "advance":
ftype = llgoAdvance
case "alloca":
ftype = llgoAlloca
case "allocaCStr":
ftype = llgoAllocaCStr
case "unreachable":
ftype = llgoUnreachable
default:
panic("unknown llgo instruction: " + name)
}
} else if ret = pkg.FuncOf(name); ret == nil {
ret = pkg.NewFunc(name, fn.Signature)
}
return
}
func (p *context) varOf(v *ssa.Global) (ret llssa.Global) {
pkgTypes := p.ensureLoaded(v.Pkg.Pkg)
pkg := p.pkg
name, _ := p.varName(pkgTypes, v)
if ret = pkg.VarOf(name); ret == nil {
ret = pkg.NewVar(name, v.Type())
}
return
}
func (p *context) ensureLoaded(pkgTypes *types.Package) *types.Package {
if p.goTyps != pkgTypes {
if _, ok := p.loaded[pkgTypes]; !ok {
i := &pkgInfo{
kind: pkgKindByPath(pkgTypes.Path()),
}
p.loaded[pkgTypes] = i
p.importPkg(pkgTypes, i)
}
}
return pkgTypes
}
func pkgKindByPath(pkgPath string) int {
switch pkgPath {
case "syscall", "runtime/cgo", "unsafe":
return PkgDeclOnly
}
return PkgNormal
}

14
cl/internal/libc/libc.go Normal file
View File

@@ -0,0 +1,14 @@
package libc
import "C"
import _ "unsafe"
const (
LLGoPackage = "decl"
)
//go:linkname Printf C.printf
func Printf(format *int8, __llgo_va_list ...any)
//go:linkname Strlen C.strlen
func Strlen(str *int8) C.int

View File

@@ -0,0 +1,9 @@
package linktarget
import (
"github.com/goplus/llgo/internal/runtime/c"
)
func F(a, b *c.Char) {
c.Printf(c.Str("a: %s, b: %s\n"), a, b)
}

View File

@@ -0,0 +1,26 @@
; ModuleID = 'github.com/goplus/llgo/cl/internal/linktarget'
source_filename = "github.com/goplus/llgo/cl/internal/linktarget"
@"github.com/goplus/llgo/cl/internal/linktarget.init$guard" = global ptr null
@0 = private unnamed_addr constant [14 x i8] c"a: %s, b: %s\0A\00", align 1
define void @"github.com/goplus/llgo/cl/internal/linktarget.F"(ptr %0, ptr %1) {
_llgo_0:
%2 = call i32 (ptr, ...) @printf(ptr @0, ptr %0, ptr %1)
ret void
}
define void @"github.com/goplus/llgo/cl/internal/linktarget.init"() {
_llgo_0:
%0 = load i1, ptr @"github.com/goplus/llgo/cl/internal/linktarget.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"github.com/goplus/llgo/cl/internal/linktarget.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
declare i32 @printf(ptr, ...)

View File

@@ -0,0 +1,17 @@
package stdio
import _ "unsafe"
const (
LLGoPackage = true
)
//go:linkname Printf C.printf
func Printf(format *int8, __llgo_va_list ...any)
func Max(a, b int) int {
if a > b {
return a
}
return b
}

View File

@@ -1,62 +0,0 @@
/*
* Copyright (c) 2023 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 cl
/*
// Define unimplemented intrinsic functions.
//
// Some functions are either normally implemented in Go assembly (like
// sync/atomic functions) or intentionally left undefined to be implemented
// directly in the compiler (like runtime/volatile functions). Either way, look
// for these and implement them if this is the case.
func (b *builder) defineIntrinsicFunction() {
panic("todo")
}
var mathToLLVMMapping = map[string]string{
"math.Ceil": "llvm.ceil.f64",
"math.Exp": "llvm.exp.f64",
"math.Exp2": "llvm.exp2.f64",
"math.Floor": "llvm.floor.f64",
"math.Log": "llvm.log.f64",
"math.Sqrt": "llvm.sqrt.f64",
"math.Trunc": "llvm.trunc.f64",
}
// defineMathOp defines a math function body as a call to a LLVM intrinsic,
// instead of the regular Go implementation. This allows LLVM to reason about
// the math operation and (depending on the architecture) allows it to lower the
// operation to very fast floating point instructions. If this is not possible,
// LLVM will emit a call to a libm function that implements the same operation.
//
// One example of an optimization that LLVM can do is to convert
// float32(math.Sqrt(float64(v))) to a 32-bit floating point operation, which is
// beneficial on architectures where 64-bit floating point operations are (much)
// more expensive than 32-bit ones.
func (b *builder) defineMathOp() {
panic("todo")
}
// Implement most math/bits functions.
//
// This implements all the functions that operate on bits. It does not yet
// implement the arithmetic functions (like bits.Add), which also have LLVM
// intrinsics.
func (b *builder) defineMathBitsIntrinsic() bool {
panic("todo")
}
*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 The GoPlus Authors (goplus.org). All rights reserved.
* 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.
@@ -14,93 +14,32 @@
* limitations under the License.
*/
// Package build implements the llgo build command.
// Package build implements the "llgo build" command.
package build
import (
"fmt"
"log"
"os"
"path/filepath"
"reflect"
"github.com/goplus/gop"
"github.com/goplus/gop/x/gopprojs"
"github.com/goplus/llgo"
"github.com/goplus/llgo/cmd/internal/base"
"github.com/goplus/llgo/x/gocmd"
"github.com/goplus/llgo/internal/build"
)
// llgo build
var Cmd = &base.Command{
UsageLine: "llgo build [flags] [packages]",
Short: "Build Go files",
UsageLine: "llgo build [-o output] [build flags] [packages]",
Short: "Compile packages and dependencies",
}
var (
flagOutput = flag.String("o", "", "build output file")
_ = flag.Bool("v", false, "print verbose information")
flag = &Cmd.Flag
)
func init() {
Cmd.Run = runCmd
}
func runCmd(cmd *base.Command, args []string) {
err := flag.Parse(args)
if err != nil {
log.Panicln("parse input arguments failed:", err)
conf := &build.Config{
Mode: build.ModeBuild,
AppExt: build.DefaultAppExt(),
}
args = flag.Args()
if len(args) == 0 {
args = []string{"."}
if len(args) >= 2 && args[0] == "-o" {
conf.OutFile = args[1]
args = args[2:]
}
proj, args, err := gopprojs.ParseOne(args...)
if err != nil {
log.Panicln(err)
}
if len(args) != 0 {
log.Panicln("too many arguments:", args)
}
conf := &llgo.Config{}
confCmd := &gocmd.BuildConfig{}
if *flagOutput != "" {
output, err := filepath.Abs(*flagOutput)
if err != nil {
log.Panicln(err)
}
confCmd.Output = output
}
build(proj, conf, confCmd)
build.Do(args, conf)
}
func build(proj gopprojs.Proj, conf *llgo.Config, build *gocmd.BuildConfig) {
var obj string
var err error
switch v := proj.(type) {
case *gopprojs.DirProj:
obj = v.Dir
err = llgo.BuildDir(obj, conf, build)
case *gopprojs.PkgPathProj:
obj = v.Path
err = llgo.BuildPkgPath("", obj, conf, build)
case *gopprojs.FilesProj:
err = llgo.BuildFiles(v.Files, conf, build)
default:
log.Panicln("`llgo build` doesn't support", reflect.TypeOf(v))
}
if gop.NotFound(err) {
fmt.Fprintf(os.Stderr, "llgo build %v: not found\n", obj)
} else if err != nil {
fmt.Fprintln(os.Stderr, err)
} else {
return
}
os.Exit(1)
}
// -----------------------------------------------------------------------------

View File

@@ -0,0 +1,38 @@
/*
* 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 clean implements the "llgo clean" command.
package clean
import (
"github.com/goplus/llgo/cmd/internal/base"
"github.com/goplus/llgo/internal/build"
)
// llgo build
var Cmd = &base.Command{
UsageLine: "llgo clean [clean flags] [build flags] [packages]",
Short: "Remove object files and cached files",
}
func init() {
Cmd.Run = runCmd
}
func runCmd(cmd *base.Command, args []string) {
conf := build.NewDefaultConf(0)
build.Clean(args, conf)
}

View File

@@ -0,0 +1,38 @@
/*
* 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 install implements the "llgo install" command.
package install
import (
"github.com/goplus/llgo/cmd/internal/base"
"github.com/goplus/llgo/internal/build"
)
// llgo install
var Cmd = &base.Command{
UsageLine: "llgo install [build flags] [packages]",
Short: "Compile and install packages and dependencies",
}
func init() {
Cmd.Run = runCmd
}
func runCmd(cmd *base.Command, args []string) {
conf := build.NewDefaultConf(build.ModeInstall)
build.Do(args, conf)
}

75
cmd/internal/run/run.go Normal file
View File

@@ -0,0 +1,75 @@
/*
* 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 run implements the "llgo run" command.
package run
import (
"errors"
"path/filepath"
"github.com/goplus/llgo/cmd/internal/base"
"github.com/goplus/llgo/internal/build"
)
var (
errNoProj = errors.New("llgo: no go files listed")
)
// llgo run
var Cmd = &base.Command{
UsageLine: "llgo run [build flags] package [arguments...]",
Short: "Compile and run Go program",
}
func init() {
Cmd.Run = runCmd
}
func runCmd(cmd *base.Command, args []string) {
args, runArgs, err := parseRunArgs(args)
check(err)
conf := build.NewDefaultConf(build.ModeRun)
conf.RunArgs = runArgs
build.Do(args, conf)
}
func parseRunArgs(args []string) ([]string, []string, error) {
n := build.SkipFlagArgs(args)
if n < 0 {
return nil, nil, errNoProj
}
arg := args[n]
if isGoFile(arg) {
n++
for n < len(args) && isGoFile(args[n]) {
n++
}
return args[:n], args[n:], nil
}
return args[:n+1], args[n+1:], nil
}
func isGoFile(fname string) bool {
return filepath.Ext(fname) == ".go"
}
func check(err error) {
if err != nil {
panic(err)
}
}

View File

@@ -26,7 +26,10 @@ import (
"github.com/goplus/llgo/cmd/internal/base"
"github.com/goplus/llgo/cmd/internal/build"
"github.com/goplus/llgo/cmd/internal/clean"
"github.com/goplus/llgo/cmd/internal/help"
"github.com/goplus/llgo/cmd/internal/install"
"github.com/goplus/llgo/cmd/internal/run"
)
func mainUsage() {
@@ -38,6 +41,9 @@ func init() {
flag.Usage = mainUsage
base.Llgo.Commands = []*base.Command{
build.Cmd,
install.Cmd,
run.Cmd,
clean.Cmd,
}
}

10
go.mod
View File

@@ -4,14 +4,14 @@ go 1.18
require (
github.com/aykevl/go-wasm v0.0.1
github.com/goplus/gop v1.2.6
github.com/goplus/llvm v0.7.1-0.20240420180312-6230a4ea7a47
github.com/goplus/gogen v1.15.2
github.com/goplus/llvm v0.7.5
github.com/goplus/mod v0.13.10
github.com/qiniu/x v1.13.10
golang.org/x/tools v0.19.0
golang.org/x/tools v0.20.0
)
require (
github.com/goplus/gogen v1.15.2 // indirect
github.com/goplus/mod v0.13.10 // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/sync v0.7.0 // indirect
)

15
go.sum
View File

@@ -2,12 +2,8 @@ github.com/aykevl/go-wasm v0.0.1 h1:lPxy8l48P39W7I0tLrtCrLfZBOUq9IWZ7odGdyJP2AM=
github.com/aykevl/go-wasm v0.0.1/go.mod h1:b4nggwg3lEkNKOU4wzhtLKz2q2sLxSHFnc98aGt6z/Y=
github.com/goplus/gogen v1.15.2 h1:Q6XaSx/Zi5tWnjfAziYsQI6Jv6MgODRpFtOYqNkiiqM=
github.com/goplus/gogen v1.15.2/go.mod h1:92qEzVgv7y8JEFICWG9GvYI5IzfEkxYdsA1DbmnTkqk=
github.com/goplus/gop v1.2.6 h1:kog3c5Js+8EopqmI4+CwueXsqibnBwYVt5q5N7juRVY=
github.com/goplus/gop v1.2.6/go.mod h1:uREWbR1MrFaviZ4Mbx4ZCcAYDoqzO0iv1Qo6Np0Xx4E=
github.com/goplus/llvm v0.7.1-0.20240418160956-6233231cbcc9 h1:E/NBN5tDh6COcJmygdBb9RAJhE4uIHfT51VBlP3tglU=
github.com/goplus/llvm v0.7.1-0.20240418160956-6233231cbcc9/go.mod h1:PeVK8GgzxwAYCiMiUAJb5wJR6xbhj989tu9oulKLLT4=
github.com/goplus/llvm v0.7.1-0.20240420180312-6230a4ea7a47 h1:B3nWTLOQh4+Yqt6NryE/cVQdo/+NLiT8AtD4YaeKScg=
github.com/goplus/llvm v0.7.1-0.20240420180312-6230a4ea7a47/go.mod h1:PeVK8GgzxwAYCiMiUAJb5wJR6xbhj989tu9oulKLLT4=
github.com/goplus/llvm v0.7.5 h1:ges8WcUdu4FBi0mkZUs27p/4qDQlj28N1UpMg3VQUoE=
github.com/goplus/llvm v0.7.5/go.mod h1:PeVK8GgzxwAYCiMiUAJb5wJR6xbhj989tu9oulKLLT4=
github.com/goplus/mod v0.13.10 h1:5Om6KOvo31daN7N30kWU1vC5zhsJPM+uPbcEN/FnlzE=
github.com/goplus/mod v0.13.10/go.mod h1:HDuPZgpWiaTp3PUolFgsiX+Q77cbUWB/mikVHfYND3c=
github.com/qiniu/x v1.13.10 h1:J4Z3XugYzAq85SlyAfqlKVrbf05glMbAOh+QncsDQpE=
@@ -31,7 +27,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -56,6 +53,6 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY=
golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@@ -0,0 +1,636 @@
; ModuleID = 'github.com/goplus/llgo/internal/abi'
source_filename = "github.com/goplus/llgo/internal/abi"
%"github.com/goplus/llgo/internal/abi.ArrayType" = type { %"github.com/goplus/llgo/internal/abi.Type", ptr, ptr, i64 }
%"github.com/goplus/llgo/internal/abi.Type" = type { i64, i64, i32, i8, i8, i8, i8, { ptr, ptr }, ptr, i32, i32 }
%"github.com/goplus/llgo/internal/abi.ChanType" = type { %"github.com/goplus/llgo/internal/abi.Type", ptr, i64 }
%"github.com/goplus/llgo/internal/abi.FuncType" = type { %"github.com/goplus/llgo/internal/abi.Type", i16, i16 }
%"github.com/goplus/llgo/internal/abi.InterfaceType" = type { %"github.com/goplus/llgo/internal/abi.Type", %"github.com/goplus/llgo/internal/abi.Name", %"github.com/goplus/llgo/internal/runtime.Slice" }
%"github.com/goplus/llgo/internal/abi.Name" = type { ptr }
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 }
%"github.com/goplus/llgo/internal/abi.MapType" = type { %"github.com/goplus/llgo/internal/abi.Type", ptr, ptr, ptr, { ptr, ptr }, i8, i8, i16, i32 }
%"github.com/goplus/llgo/internal/abi.PtrType" = type { %"github.com/goplus/llgo/internal/abi.Type", ptr }
%"github.com/goplus/llgo/internal/abi.SliceType" = type { %"github.com/goplus/llgo/internal/abi.Type", ptr }
%"github.com/goplus/llgo/internal/abi.StructType" = type { %"github.com/goplus/llgo/internal/abi.Type", %"github.com/goplus/llgo/internal/abi.Name", %"github.com/goplus/llgo/internal/runtime.Slice" }
@"github.com/goplus/llgo/internal/abi.init$guard" = global ptr null
define ptr @"(*github.com/goplus/llgo/internal/abi.ArrayType).ArrayType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.ArrayType).Common"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.ArrayType).FuncType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.ArrayType).InterfaceType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
ret ptr %2
}
define i64 @"(*github.com/goplus/llgo/internal/abi.ArrayType).Kind"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 0
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
ret i64 %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.ArrayType).MapType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.ArrayType).StructType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.ChanType).ArrayType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.ChanType).Common"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.ChanType).FuncType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.ChanType).InterfaceType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
ret ptr %2
}
define i64 @"(*github.com/goplus/llgo/internal/abi.ChanType).Kind"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 0
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
ret i64 %2
}
define i64 @"(*github.com/goplus/llgo/internal/abi.ChanType).Len"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 0
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %1)
ret i64 %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.ChanType).MapType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.ChanType).StructType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.FuncType).ArrayType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.FuncType).Common"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.FuncType).Elem"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Elem"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.FuncType).FuncType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.FuncType).InterfaceType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
ret ptr %2
}
define i64 @"(*github.com/goplus/llgo/internal/abi.FuncType).Kind"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
ret i64 %2
}
define i64 @"(*github.com/goplus/llgo/internal/abi.FuncType).Len"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %1)
ret i64 %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.FuncType).MapType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.FuncType).StructType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.FuncType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).ArrayType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).Common"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).Elem"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Elem"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).FuncType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).InterfaceType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
ret ptr %2
}
define i64 @"(*github.com/goplus/llgo/internal/abi.InterfaceType).Kind"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
ret i64 %2
}
define i64 @"(*github.com/goplus/llgo/internal/abi.InterfaceType).Len"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %1)
ret i64 %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).MapType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.InterfaceType).StructType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.InterfaceType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.MapType).ArrayType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.MapType).Common"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.MapType).FuncType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.MapType).InterfaceType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
ret ptr %2
}
define i64 @"(*github.com/goplus/llgo/internal/abi.MapType).Kind"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 0
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
ret i64 %2
}
define i64 @"(*github.com/goplus/llgo/internal/abi.MapType).Len"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 0
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %1)
ret i64 %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.MapType).MapType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.MapType).StructType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.PtrType).ArrayType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.PtrType).Common"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.PtrType).FuncType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.PtrType).InterfaceType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
ret ptr %2
}
define i64 @"(*github.com/goplus/llgo/internal/abi.PtrType).Kind"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 0
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
ret i64 %2
}
define i64 @"(*github.com/goplus/llgo/internal/abi.PtrType).Len"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 0
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %1)
ret i64 %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.PtrType).MapType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.PtrType).StructType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.SliceType).ArrayType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.SliceType).Common"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.SliceType).FuncType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.SliceType).InterfaceType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
ret ptr %2
}
define i64 @"(*github.com/goplus/llgo/internal/abi.SliceType).Kind"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 0
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
ret i64 %2
}
define i64 @"(*github.com/goplus/llgo/internal/abi.SliceType).Len"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 0
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %1)
ret i64 %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.SliceType).MapType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.SliceType).StructType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.StructType).ArrayType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.StructType).Common"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.StructType).Elem"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).Elem"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.StructType).FuncType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.StructType).InterfaceType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %1)
ret ptr %2
}
define i64 @"(*github.com/goplus/llgo/internal/abi.StructType).Kind"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %1)
ret i64 %2
}
define i64 @"(*github.com/goplus/llgo/internal/abi.StructType).Len"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
%2 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %1)
ret i64 %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.StructType).MapType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.StructType).StructType"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.StructType", ptr %0, i32 0, i32 0
%2 = call ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %1)
ret ptr %2
}
define ptr @"(*github.com/goplus/llgo/internal/abi.Type).ArrayType"(ptr %0) {
_llgo_0:
%1 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %0)
%2 = icmp ne i64 %1, 17
br i1 %2, label %_llgo_1, label %_llgo_2
_llgo_1: ; preds = %_llgo_0
ret ptr null
_llgo_2: ; preds = %_llgo_0
ret ptr %0
}
define ptr @"(*github.com/goplus/llgo/internal/abi.Type).Common"(ptr %0) {
_llgo_0:
ret ptr %0
}
define ptr @"(*github.com/goplus/llgo/internal/abi.Type).Elem"(ptr %0) {
_llgo_0:
%1 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %0)
%2 = icmp eq i64 %1, 17
br i1 %2, label %_llgo_1, label %_llgo_3
_llgo_1: ; preds = %_llgo_0
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 1
%4 = load ptr, ptr %3, align 8
ret ptr %4
_llgo_2: ; preds = %_llgo_3
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ChanType", ptr %0, i32 0, i32 1
%6 = load ptr, ptr %5, align 8
ret ptr %6
_llgo_3: ; preds = %_llgo_0
%7 = icmp eq i64 %1, 18
br i1 %7, label %_llgo_2, label %_llgo_5
_llgo_4: ; preds = %_llgo_5
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.MapType", ptr %0, i32 0, i32 2
%9 = load ptr, ptr %8, align 8
ret ptr %9
_llgo_5: ; preds = %_llgo_3
%10 = icmp eq i64 %1, 21
br i1 %10, label %_llgo_4, label %_llgo_7
_llgo_6: ; preds = %_llgo_7
%11 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.PtrType", ptr %0, i32 0, i32 1
%12 = load ptr, ptr %11, align 8
ret ptr %12
_llgo_7: ; preds = %_llgo_5
%13 = icmp eq i64 %1, 22
br i1 %13, label %_llgo_6, label %_llgo_9
_llgo_8: ; preds = %_llgo_9
%14 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.SliceType", ptr %0, i32 0, i32 1
%15 = load ptr, ptr %14, align 8
ret ptr %15
_llgo_9: ; preds = %_llgo_7
%16 = icmp eq i64 %1, 23
br i1 %16, label %_llgo_8, label %_llgo_10
_llgo_10: ; preds = %_llgo_9
ret ptr null
}
define ptr @"(*github.com/goplus/llgo/internal/abi.Type).FuncType"(ptr %0) {
_llgo_0:
%1 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %0)
%2 = icmp ne i64 %1, 19
br i1 %2, label %_llgo_1, label %_llgo_2
_llgo_1: ; preds = %_llgo_0
ret ptr null
_llgo_2: ; preds = %_llgo_0
ret ptr %0
}
define ptr @"(*github.com/goplus/llgo/internal/abi.Type).InterfaceType"(ptr %0) {
_llgo_0:
%1 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %0)
%2 = icmp ne i64 %1, 20
br i1 %2, label %_llgo_1, label %_llgo_2
_llgo_1: ; preds = %_llgo_0
ret ptr null
_llgo_2: ; preds = %_llgo_0
ret ptr %0
}
define i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %0, i32 0, i32 6
%2 = load i8, ptr %1, align 1
%3 = and i8 %2, 31
%4 = sext i8 %3 to i64
ret i64 %4
}
define i64 @"(*github.com/goplus/llgo/internal/abi.Type).Len"(ptr %0) {
_llgo_0:
%1 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %0)
%2 = icmp eq i64 %1, 17
br i1 %2, label %_llgo_1, label %_llgo_2
_llgo_1: ; preds = %_llgo_0
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.ArrayType", ptr %0, i32 0, i32 3
%4 = load i64, ptr %3, align 4
ret i64 %4
_llgo_2: ; preds = %_llgo_0
ret i64 0
}
define ptr @"(*github.com/goplus/llgo/internal/abi.Type).MapType"(ptr %0) {
_llgo_0:
%1 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %0)
%2 = icmp ne i64 %1, 21
br i1 %2, label %_llgo_1, label %_llgo_2
_llgo_1: ; preds = %_llgo_0
ret ptr null
_llgo_2: ; preds = %_llgo_0
ret ptr %0
}
define ptr @"(*github.com/goplus/llgo/internal/abi.Type).StructType"(ptr %0) {
_llgo_0:
%1 = call i64 @"(*github.com/goplus/llgo/internal/abi.Type).Kind"(ptr %0)
%2 = icmp ne i64 %1, 25
br i1 %2, label %_llgo_1, label %_llgo_2
_llgo_1: ; preds = %_llgo_0
ret ptr null
_llgo_2: ; preds = %_llgo_0
ret ptr %0
}
define void @"github.com/goplus/llgo/internal/abi.init"() {
_llgo_0:
%0 = load i1, ptr @"github.com/goplus/llgo/internal/abi.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"github.com/goplus/llgo/internal/abi.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}

14
internal/abi/map.go Normal file
View File

@@ -0,0 +1,14 @@
// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package abi
// Map constants common to several packages
// runtime/runtime-gdb.py:MapTypePrinter contains its own copy
const (
MapBucketCountBits = 3 // log2 of number of elements in a bucket.
MapBucketCount = 1 << MapBucketCountBits
MapMaxKeyBytes = 128 // Must fit in a uint8.
MapMaxElemBytes = 128 // Must fit in a uint8.
)

332
internal/abi/type.go Normal file
View File

@@ -0,0 +1,332 @@
/*
* 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 abi
import (
"unsafe"
)
// -----------------------------------------------------------------------------
// Type is the runtime representation of a Go type.
//
// Type is also referenced implicitly
// (in the form of expressions involving constants and arch.PtrSize)
// in cmd/compile/internal/reflectdata/reflect.go
// and cmd/link/internal/ld/decodesym.go
// (e.g. data[2*arch.PtrSize+4] references the TFlag field)
// unsafe.OffsetOf(Type{}.TFlag) cannot be used directly in those
// places because it varies with cross compilation and experiments.
type Type struct {
Size_ uintptr
PtrBytes uintptr // number of (prefix) bytes in the type that can contain pointers
Hash uint32 // hash of type; avoids computation in hash tables
TFlag TFlag // extra type information flags
Align_ uint8 // alignment of variable with this type
FieldAlign_ uint8 // alignment of struct field with this type
Kind_ uint8 // enumeration for C
// function for comparing objects of this type
// (ptr to object A, ptr to object B) -> ==?
Equal func(unsafe.Pointer, unsafe.Pointer) bool
// GCData stores the GC type data for the garbage collector.
// If the KindGCProg bit is set in kind, GCData is a GC program.
// Otherwise it is a ptrmask bitmap. See mbitmap.go for details.
GCData *byte
Str NameOff // string form
PtrToThis TypeOff // type for pointer to this type, may be zero
}
func (t *Type) Kind() Kind { return Kind(t.Kind_ & KindMask) }
// A Kind represents the specific kind of type that a Type represents.
// The zero Kind is not a valid kind.
type Kind uint
const (
Invalid Kind = iota
Bool
Int
Int8
Int16
Int32
Int64
Uint
Uint8
Uint16
Uint32
Uint64
Uintptr
Float32
Float64
Complex64
Complex128
Array
Chan
Func
Interface
Map
Pointer
Slice
String
Struct
UnsafePointer
)
const (
// TODO (khr, drchase) why aren't these in TFlag? Investigate, fix if possible.
KindDirectIface = 1 << 5
KindGCProg = 1 << 6 // Type.gc points to GC program
KindMask = (1 << 5) - 1
)
// TFlag is used by a Type to signal what extra type information is
// available in the memory directly following the Type value.
type TFlag uint8
const (
// TFlagUncommon means that there is a data with a type, UncommonType,
// just beyond the shared-per-type common data. That is, the data
// for struct types will store their UncommonType at one offset, the
// data for interface types will store their UncommonType at a different
// offset. UncommonType is always accessed via a pointer that is computed
// using trust-us-we-are-the-implementors pointer arithmetic.
//
// For example, if t.Kind() == Struct and t.tflag&TFlagUncommon != 0,
// then t has UncommonType data and it can be accessed as:
//
// type structTypeUncommon struct {
// structType
// u UncommonType
// }
// u := &(*structTypeUncommon)(unsafe.Pointer(t)).u
TFlagUncommon TFlag = 1 << 0
// TFlagExtraStar means the name in the str field has an
// extraneous '*' prefix. This is because for most types T in
// a program, the type *T also exists and reusing the str data
// saves binary size.
TFlagExtraStar TFlag = 1 << 1
// TFlagNamed means the type has a name.
TFlagNamed TFlag = 1 << 2
// TFlagRegularMemory means that equal and hash functions can treat
// this type as a single region of t.size bytes.
TFlagRegularMemory TFlag = 1 << 3
)
// NameOff is the offset to a name from moduledata.types. See resolveNameOff in runtime.
type NameOff int32
// TypeOff is the offset to a type from moduledata.types. See resolveTypeOff in runtime.
type TypeOff int32
// -----------------------------------------------------------------------------
// ArrayType represents a fixed array type.
type ArrayType struct {
Type
Elem *Type // array element type
Slice *Type // slice type
Len uintptr
}
type SliceType struct {
Type
Elem *Type // slice element type
}
type MapType struct {
Type
Key *Type
Elem *Type
Bucket *Type // internal type representing a hash bucket
// function for hashing keys (ptr to key, seed) -> hash
Hasher func(unsafe.Pointer, uintptr) uintptr
KeySize uint8 // size of key slot
ValueSize uint8 // size of elem slot
BucketSize uint16 // size of bucket
Flags uint32
}
type PtrType struct {
Type
Elem *Type // pointer element (pointed at) type
}
type ChanDir int
const (
RecvDir ChanDir = 1 << iota // <-chan
SendDir // chan<-
BothDir = RecvDir | SendDir // chan
InvalidDir ChanDir = 0
)
// ChanType represents a channel type
type ChanType struct {
Type
Elem *Type
Dir ChanDir
}
// funcType represents a function type.
//
// A *Type for each in and out parameter is stored in an array that
// directly follows the funcType (and possibly its uncommonType). So
// a function type with one method, one input, and one output is:
//
// struct {
// funcType
// uncommonType
// [2]*rtype // [0] is in, [1] is out
// }
type FuncType struct {
Type
InCount uint16
OutCount uint16 // top bit is set if last input parameter is ...
}
type StructField struct {
Name Name // name is always non-empty
Typ *Type // type of field
Offset uintptr // byte offset of field
}
type StructType struct {
Type
PkgPath Name
Fields []StructField
}
// Name is an encoded type Name with optional extra data.
//
// The first byte is a bit field containing:
//
// 1<<0 the name is exported
// 1<<1 tag data follows the name
// 1<<2 pkgPath nameOff follows the name and tag
// 1<<3 the name is of an embedded (a.k.a. anonymous) field
//
// Following that, there is a varint-encoded length of the name,
// followed by the name itself.
//
// If tag data is present, it also has a varint-encoded length
// followed by the tag itself.
//
// If the import path follows, then 4 bytes at the end of
// the data form a nameOff. The import path is only set for concrete
// methods that are defined in a different package than their type.
//
// If a name starts with "*", then the exported bit represents
// whether the pointed to type is exported.
//
// Note: this encoding must match here and in:
// cmd/compile/internal/reflectdata/reflect.go
// cmd/link/internal/ld/decodesym.go
type Name struct {
Bytes *byte
}
type InterfaceType struct {
Type
PkgPath Name // import path
Methods []Imethod // sorted by hash
}
// Imethod represents a method on an interface type
type Imethod struct {
Name NameOff // name of method
Typ TypeOff // .(*FuncType) underneath
}
func (t *Type) Common() *Type {
return t
}
// Len returns the length of t if t is an array type, otherwise 0
func (t *Type) Len() int {
if t.Kind() == Array {
return int((*ArrayType)(unsafe.Pointer(t)).Len)
}
return 0
}
// Elem returns the element type for t if t is an array, channel, map, pointer, or slice, otherwise nil.
func (t *Type) Elem() *Type {
switch t.Kind() {
case Array:
tt := (*ArrayType)(unsafe.Pointer(t))
return tt.Elem
case Chan:
tt := (*ChanType)(unsafe.Pointer(t))
return tt.Elem
case Map:
tt := (*MapType)(unsafe.Pointer(t))
return tt.Elem
case Pointer:
tt := (*PtrType)(unsafe.Pointer(t))
return tt.Elem
case Slice:
tt := (*SliceType)(unsafe.Pointer(t))
return tt.Elem
}
return nil
}
// StructType returns t cast to a *StructType, or nil if its tag does not match.
func (t *Type) StructType() *StructType {
if t.Kind() != Struct {
return nil
}
return (*StructType)(unsafe.Pointer(t))
}
// MapType returns t cast to a *MapType, or nil if its tag does not match.
func (t *Type) MapType() *MapType {
if t.Kind() != Map {
return nil
}
return (*MapType)(unsafe.Pointer(t))
}
// ArrayType returns t cast to a *ArrayType, or nil if its tag does not match.
func (t *Type) ArrayType() *ArrayType {
if t.Kind() != Array {
return nil
}
return (*ArrayType)(unsafe.Pointer(t))
}
// FuncType returns t cast to a *FuncType, or nil if its tag does not match.
func (t *Type) FuncType() *FuncType {
if t.Kind() != Func {
return nil
}
return (*FuncType)(unsafe.Pointer(t))
}
// InterfaceType returns t cast to a *InterfaceType, or nil if its tag does not match.
func (t *Type) InterfaceType() *InterfaceType {
if t.Kind() != Interface {
return nil
}
return (*InterfaceType)(unsafe.Pointer(t))
}
// -----------------------------------------------------------------------------

View File

@@ -0,0 +1,32 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package aliases
import (
"go/token"
"go/types"
)
// Package aliases defines backward compatible shims
// for the types.Alias type representation added in 1.22.
// This defines placeholders for x/tools until 1.26.
// NewAlias creates a new TypeName in Package pkg that
// is an alias for the type rhs.
//
// The enabled parameter determines whether the resulting [TypeName]'s
// type is an [types.Alias]. Its value must be the result of a call to
// [Enabled], which computes the effective value of
// GODEBUG=gotypesalias=... by invoking the type checker. The Enabled
// function is expensive and should be called once per task (e.g.
// package import), not once per call to NewAlias.
func NewAlias(enabled bool, pos token.Pos, pkg *types.Package, name string, rhs types.Type) *types.TypeName {
if enabled {
tname := types.NewTypeName(pos, pkg, name, nil)
newAlias(tname, rhs)
return tname
}
return types.NewTypeName(pos, pkg, name, rhs)
}

View File

@@ -0,0 +1,31 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !go1.22
// +build !go1.22
package aliases
import (
"go/types"
)
// Alias is a placeholder for a go/types.Alias for <=1.21.
// It will never be created by go/types.
type Alias struct{}
func (*Alias) String() string { panic("unreachable") }
func (*Alias) Underlying() types.Type { panic("unreachable") }
func (*Alias) Obj() *types.TypeName { panic("unreachable") }
func Rhs(alias *Alias) types.Type { panic("unreachable") }
// Unalias returns the type t for go <=1.21.
func Unalias(t types.Type) types.Type { return t }
func newAlias(name *types.TypeName, rhs types.Type) *Alias { panic("unreachable") }
// Enabled reports whether [NewAlias] should create [types.Alias] types.
//
// Before go1.22, this function always returns false.
func Enabled() bool { return false }

View File

@@ -0,0 +1,63 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.22
// +build go1.22
package aliases
import (
"go/ast"
"go/parser"
"go/token"
"go/types"
)
// Alias is an alias of types.Alias.
type Alias = types.Alias
// Rhs returns the type on the right-hand side of the alias declaration.
func Rhs(alias *Alias) types.Type {
if alias, ok := any(alias).(interface{ Rhs() types.Type }); ok {
return alias.Rhs() // go1.23+
}
// go1.22's Alias didn't have the Rhs method,
// so Unalias is the best we can do.
return Unalias(alias)
}
// Unalias is a wrapper of types.Unalias.
func Unalias(t types.Type) types.Type { return types.Unalias(t) }
// newAlias is an internal alias around types.NewAlias.
// Direct usage is discouraged as the moment.
// Try to use NewAlias instead.
func newAlias(tname *types.TypeName, rhs types.Type) *Alias {
a := types.NewAlias(tname, rhs)
// TODO(go.dev/issue/65455): Remove kludgy workaround to set a.actual as a side-effect.
Unalias(a)
return a
}
// Enabled reports whether [NewAlias] should create [types.Alias] types.
//
// This function is expensive! Call it sparingly.
func Enabled() bool {
// The only reliable way to compute the answer is to invoke go/types.
// We don't parse the GODEBUG environment variable, because
// (a) it's tricky to do so in a manner that is consistent
// with the godebug package; in particular, a simple
// substring check is not good enough. The value is a
// rightmost-wins list of options. But more importantly:
// (b) it is impossible to detect changes to the effective
// setting caused by os.Setenv("GODEBUG"), as happens in
// many tests. Therefore any attempt to cache the result
// is just incorrect.
fset := token.NewFileSet()
f, _ := parser.ParseFile(fset, "a.go", "package p; type A = int", 0)
pkg, _ := new(types.Config).Check("p", fset, []*ast.File{f}, nil)
_, enabled := pkg.Scope().Lookup("A").Type().(*types.Alias)
return enabled
}

398
internal/build/build.go Normal file
View File

@@ -0,0 +1,398 @@
/*
* 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 build
import (
"fmt"
"go/token"
"go/types"
"os"
"os/exec"
"path"
"path/filepath"
"runtime"
"strings"
"golang.org/x/tools/go/packages"
"golang.org/x/tools/go/ssa"
"github.com/goplus/llgo/cl"
"github.com/goplus/llgo/x/clang"
llssa "github.com/goplus/llgo/ssa"
)
type Mode int
const (
ModeBuild Mode = iota
ModeInstall
ModeRun
)
func needLLFile(mode Mode) bool {
return mode != ModeBuild
}
type Config struct {
BinPath string
AppExt string // ".exe" on Windows, empty on Unix
OutFile string // only valid for ModeBuild when len(pkgs) == 1
RunArgs []string // only valid for ModeRun
Mode Mode
}
func NewDefaultConf(mode Mode) *Config {
bin := os.Getenv("GOBIN")
if bin == "" {
bin = filepath.Join(runtime.GOROOT(), "bin")
}
conf := &Config{
BinPath: bin,
Mode: mode,
AppExt: DefaultAppExt(),
}
return conf
}
func DefaultAppExt() string {
if runtime.GOOS == "windows" {
return ".exe"
}
return ""
}
// -----------------------------------------------------------------------------
const (
loadFiles = packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles
loadImports = loadFiles | packages.NeedImports
loadTypes = loadImports | packages.NeedTypes | packages.NeedTypesSizes
loadSyntax = loadTypes | packages.NeedSyntax | packages.NeedTypesInfo
)
func Do(args []string, conf *Config) {
flags, patterns, verbose := ParseArgs(args, buildFlags)
cfg := &packages.Config{
Mode: loadSyntax | packages.NeedDeps | packages.NeedModule | packages.NeedExportFile,
BuildFlags: flags,
}
if patterns == nil {
patterns = []string{"."}
}
initial, err := packages.Load(cfg, patterns...)
check(err)
mode := conf.Mode
if len(initial) == 1 && len(initial[0].CompiledGoFiles) > 0 {
if mode == ModeBuild {
mode = ModeInstall
}
} else if mode == ModeRun {
if len(initial) > 1 {
fmt.Fprintln(os.Stderr, "cannot run multiple packages")
} else {
fmt.Fprintln(os.Stderr, "no Go files in matched packages")
}
return
}
llssa.Initialize(llssa.InitAll)
if verbose {
llssa.SetDebug(llssa.DbgFlagAll)
cl.SetDebug(cl.DbgFlagAll)
}
var rt []*packages.Package
prog := llssa.NewProgram(nil)
prog.SetRuntime(func() *types.Package {
rt, err = packages.Load(cfg, llssa.PkgRuntime)
check(err)
return rt[0].Types
})
pkgs := buildAllPkgs(prog, initial, mode, verbose)
var runtimeFiles []string
if rt != nil {
runtimeFiles = allLinkFiles(rt)
}
if mode != ModeBuild {
nErr := 0
for _, pkg := range initial {
if pkg.Name == "main" {
nErr += linkMainPkg(pkg, pkgs, runtimeFiles, conf, mode, verbose)
}
}
if nErr > 0 {
os.Exit(nErr)
}
}
}
func setNeedRuntime(pkg *packages.Package) {
pkg.ID = "" // just use pkg.Module to mark it needs runtime
}
func isNeedRuntime(pkg *packages.Package) bool {
return pkg.ID == ""
}
func buildAllPkgs(prog llssa.Program, initial []*packages.Package, mode Mode, verbose bool) (pkgs []*aPackage) {
// Create SSA-form program representation.
ssaProg, pkgs, errPkgs := allPkgs(initial, ssa.SanityCheckFunctions)
ssaProg.Build()
for _, errPkg := range errPkgs {
for _, err := range errPkg.Errors {
fmt.Fprintln(os.Stderr, err)
}
fmt.Fprintln(os.Stderr, "cannot build SSA for package", errPkg)
}
for _, pkg := range pkgs {
buildPkg(prog, pkg, mode, verbose)
if prog.NeedRuntime() {
setNeedRuntime(pkg.Package)
}
}
return
}
func linkMainPkg(pkg *packages.Package, pkgs []*aPackage, runtimeFiles []string, conf *Config, mode Mode, verbose bool) (nErr int) {
pkgPath := pkg.PkgPath
name := path.Base(pkgPath)
app := conf.OutFile
if app == "" {
app = filepath.Join(conf.BinPath, name+conf.AppExt)
}
const N = 3
args := make([]string, N, len(pkg.Imports)+len(runtimeFiles)+(N+1))
args[0] = "-o"
args[1] = app
args[2] = "-Wno-override-module"
needRuntime := false
packages.Visit([]*packages.Package{pkg}, nil, func(p *packages.Package) {
if p.ExportFile != "" && !isRuntimePkg(p.PkgPath) { // skip packages that only contain declarations
args = append(args, p.ExportFile+".ll")
if !needRuntime {
needRuntime = isNeedRuntime(p)
}
}
})
if needRuntime && runtimeFiles != nil {
args = append(args, runtimeFiles...)
} else {
for _, aPkg := range pkgs {
if aPkg.Package == pkg { // make empty runtime.init if no runtime needed
lpkg := aPkg.LPkg
lpkg.FuncOf(cl.RuntimeInit).MakeBody(1).Return()
if needLLFile(mode) {
file := pkg.ExportFile + ".ll"
os.WriteFile(file, []byte(lpkg.String()), 0644)
}
}
}
}
if verbose || mode != ModeRun {
fmt.Fprintln(os.Stderr, "#", pkgPath)
}
defer func() {
if e := recover(); e != nil {
nErr = 1
}
}()
// TODO(xsw): show work
if verbose {
fmt.Fprintln(os.Stderr, "clang", args)
}
err := clang.New("").Exec(args...)
check(err)
if mode == ModeRun {
cmd := exec.Command(app, conf.RunArgs...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Run()
}
return
}
func buildPkg(prog llssa.Program, aPkg *aPackage, mode Mode, verbose bool) {
pkg := aPkg.Package
if cl.PkgKindOf(pkg.Types) == cl.PkgDeclOnly {
// skip packages that only contain declarations
// and set no export file
pkg.ExportFile = ""
return
}
pkgPath := pkg.PkgPath
if verbose {
fmt.Fprintln(os.Stderr, pkgPath)
}
if pkgPath == "unsafe" { // TODO(xsw): maybe can remove this special case
return
}
ret, err := cl.NewPackage(prog, aPkg.SSA, pkg.Syntax)
check(err)
if needLLFile(mode) {
file := pkg.ExportFile + ".ll"
os.WriteFile(file, []byte(ret.String()), 0644)
}
aPkg.LPkg = ret
}
type aPackage struct {
*packages.Package
SSA *ssa.Package
LPkg llssa.Package
}
func allPkgs(initial []*packages.Package, mode ssa.BuilderMode) (prog *ssa.Program, all []*aPackage, errs []*packages.Package) {
var fset *token.FileSet
if len(initial) > 0 {
fset = initial[0].Fset
}
prog = ssa.NewProgram(fset, mode)
packages.Visit(initial, nil, func(p *packages.Package) {
if p.Types != nil && !p.IllTyped {
ssaPkg := prog.CreatePackage(p.Types, p.Syntax, p.TypesInfo, true)
all = append(all, &aPackage{p, ssaPkg, nil})
} else {
errs = append(errs, p)
}
})
return
}
var (
// TODO(xsw): complete build flags
buildFlags = map[string]bool{
"-C": true, // -C dir: Change to dir before running the command
"-a": false, // -a: force rebuilding of packages that are already up-to-date
"-n": false, // -n: print the commands but do not run them
"-p": true, // -p n: the number of programs to run in parallel
"-race": false, // -race: enable data race detection
"-cover": false, // -cover: enable coverage analysis
"-covermode": true, // -covermode mode: set the mode for coverage analysis
"-v": false, // -v: print the names of packages as they are compiled
"-work": false, // -work: print the name of the temporary work directory and do not delete it when exiting
"-x": false, // -x: print the commands
"-tags": true, // -tags 'tag,list': a space-separated list of build tags to consider satisfied during the build
"-pkgdir": true, // -pkgdir dir: install and load all packages from dir instead of the usual locations
}
)
func ParseArgs(args []string, swflags map[string]bool) (flags, patterns []string, verbose bool) {
n := len(args)
for i := 0; i < n; i++ {
arg := args[i]
if strings.HasPrefix(arg, "-") {
checkFlag(arg, &i, &verbose, swflags)
} else {
flags, patterns = args[:i], args[i:]
return
}
}
flags = args
return
}
func SkipFlagArgs(args []string) int {
n := len(args)
for i := 0; i < n; i++ {
arg := args[i]
if strings.HasPrefix(arg, "-") {
checkFlag(arg, &i, nil, buildFlags)
} else {
return i
}
}
return -1
}
func checkFlag(arg string, i *int, verbose *bool, swflags map[string]bool) {
if hasarg, ok := swflags[arg]; ok {
if hasarg {
*i++
} else if verbose != nil && arg == "-v" {
*verbose = true
}
} else {
panic("unknown flag: " + arg)
}
}
func allLinkFiles(rt []*packages.Package) (outFiles []string) {
outFiles = make([]string, 0, len(rt))
root := rootLLGo(rt[0])
packages.Visit(rt, nil, func(p *packages.Package) {
pkgPath := p.PkgPath
if isRuntimePkg(pkgPath) {
outFile := filepath.Join(root+pkgPath[len(llgoModPath):], "llgo_autogen.ll")
outFiles = append(outFiles, outFile)
}
})
return
}
const (
pkgAbi = llgoModPath + "/internal/abi"
pkgRuntime = llgoModPath + "/internal/runtime"
)
func isRuntimePkg(pkgPath string) bool {
switch pkgPath {
case pkgRuntime, pkgAbi:
return true
}
return false
}
// TODO(xsw): llgo root dir
func rootLLGo(runtime *packages.Package) string {
return runtime.Module.Dir
}
const (
llgoModPath = "github.com/goplus/llgo"
)
/*
func isPkgInLLGo(pkgPath string) bool {
return isPkgInMod(pkgPath, llgoModPath)
}
func isPkgInMod(pkgPath, modPath string) bool {
if strings.HasPrefix(pkgPath, modPath) {
suffix := pkgPath[len(modPath):]
return suffix == "" || suffix[0] == '/'
}
return false
}
*/
func check(err error) {
if err != nil {
panic(err)
}
}
// -----------------------------------------------------------------------------

85
internal/build/clean.go Normal file
View File

@@ -0,0 +1,85 @@
/*
* 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 build
import (
"fmt"
"os"
"path"
"path/filepath"
"golang.org/x/tools/go/packages"
)
var (
// TODO(xsw): complete clean flags
cleanFlags = map[string]bool{
"-v": false, // -v: print the paths of packages as they are clean
}
)
func Clean(args []string, conf *Config) {
flags, patterns, verbose := ParseArgs(args, cleanFlags)
cfg := &packages.Config{
Mode: loadSyntax | packages.NeedExportFile,
BuildFlags: flags,
}
if patterns == nil {
patterns = []string{"."}
}
initial, err := packages.Load(cfg, patterns...)
check(err)
cleanPkgs(initial, verbose)
for _, pkg := range initial {
if pkg.Name == "main" {
cleanMainPkg(pkg, conf, verbose)
}
}
}
func cleanMainPkg(pkg *packages.Package, conf *Config, verbose bool) {
pkgPath := pkg.PkgPath
name := path.Base(pkgPath)
fname := name + conf.AppExt
app := filepath.Join(conf.BinPath, fname)
removeFile(app, verbose)
if len(pkg.CompiledGoFiles) > 0 {
dir := filepath.Dir(pkg.CompiledGoFiles[0])
buildApp := filepath.Join(dir, fname)
removeFile(buildApp, verbose)
}
}
func cleanPkgs(initial []*packages.Package, verbose bool) {
packages.Visit(initial, nil, func(p *packages.Package) {
file := p.ExportFile + ".ll"
removeFile(file, verbose)
})
}
func removeFile(file string, verbose bool) {
if _, err := os.Stat(file); os.IsNotExist(err) {
return
}
if verbose {
fmt.Fprintln(os.Stderr, "Remove", file)
}
os.Remove(file)
}

View File

@@ -18,13 +18,14 @@ package llgen
import (
"go/ast"
"go/importer"
"go/parser"
"go/token"
"go/types"
"os"
"github.com/goplus/gogen/packages"
"github.com/goplus/llgo/cl"
"github.com/goplus/llgo/internal/mod"
"golang.org/x/tools/go/ssa"
"golang.org/x/tools/go/ssa/ssautil"
@@ -37,28 +38,40 @@ func Init() {
cl.SetDebug(cl.DbgFlagAll)
}
func Do(inFile, outFile string) {
ret := Gen(inFile, nil)
func PkgPath(dir string) string {
_, pkgPath, err := mod.Load(dir)
check(err)
return pkgPath
}
func Do(pkgPath, inFile, outFile string) {
ret := Gen(pkgPath, inFile, nil)
err := os.WriteFile(outFile, []byte(ret), 0644)
check(err)
}
func Gen(inFile string, src any) string {
func Gen(pkgPath, inFile string, src any) string {
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, inFile, src, parser.ParseComments)
check(err)
files := []*ast.File{f}
name := f.Name.Name
pkg := types.NewPackage(name, name)
if pkgPath == "" {
pkgPath = name
}
pkg := types.NewPackage(pkgPath, name)
imp := packages.NewImporter(fset)
ssaPkg, _, err := ssautil.BuildPackage(
&types.Config{Importer: importer.Default()}, fset, pkg, files, ssa.SanityCheckFunctions)
&types.Config{Importer: imp}, fset, pkg, files, ssa.SanityCheckFunctions)
check(err)
if Verbose {
ssaPkg.WriteTo(os.Stderr)
}
prog := llssa.NewProgram(nil)
ret, err := cl.NewPackage(prog, ssaPkg, nil)
ret, err := cl.NewPackage(prog, ssaPkg, files)
check(err)
return ret.String()
@@ -69,3 +82,7 @@ func check(err error) {
panic(err)
}
}
var (
Verbose = true
)

94
internal/llgen/llgenf.go Normal file
View File

@@ -0,0 +1,94 @@
/*
* 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 llgen
import (
"go/types"
"os"
"path/filepath"
"strings"
"github.com/goplus/llgo/cl"
"golang.org/x/tools/go/packages"
"golang.org/x/tools/go/ssa"
"golang.org/x/tools/go/ssa/ssautil"
llssa "github.com/goplus/llgo/ssa"
)
const (
loadFiles = packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles
loadImports = loadFiles | packages.NeedImports
loadTypes = loadImports | packages.NeedTypes | packages.NeedTypesSizes
loadSyntax = loadTypes | packages.NeedSyntax | packages.NeedTypesInfo
)
func GenFrom(fileOrPkg string) string {
cfg := &packages.Config{
Mode: loadSyntax | packages.NeedDeps,
}
initial, err := packages.Load(cfg, fileOrPkg)
check(err)
_, pkgs := ssautil.AllPackages(initial, ssa.SanityCheckFunctions)
pkg := initial[0]
ssaPkg := pkgs[0]
ssaPkg.Build()
prog := llssa.NewProgram(nil)
prog.SetRuntime(func() *types.Package {
rt, err := packages.Load(cfg, llssa.PkgRuntime)
check(err)
return rt[0].Types
})
if Verbose {
ssaPkg.WriteTo(os.Stderr)
}
ret, err := cl.NewPackage(prog, ssaPkg, pkg.Syntax)
check(err)
return ret.String()
}
func DoFile(fileOrPkg, outFile string) {
ret := GenFrom(fileOrPkg)
err := os.WriteFile(outFile, []byte(ret), 0644)
check(err)
}
func SmartDoFile(inFile string, pkgPath ...string) {
dir, _ := filepath.Split(inFile)
fname := "llgo_autogen.ll"
if inCompilerDir(dir) {
fname = "out.ll"
}
outFile := dir + fname
if len(pkgPath) > 0 {
Do(pkgPath[0], inFile, outFile)
} else {
DoFile(inFile, outFile)
}
}
func inCompilerDir(dir string) bool {
dir, _ = filepath.Abs(dir)
return strings.Contains(filepath.ToSlash(dir), "/llgo/cl/")
}

48
internal/mod/mod.go Normal file
View File

@@ -0,0 +1,48 @@
/*
* 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 mod
import (
"path"
"path/filepath"
"github.com/goplus/mod"
"github.com/goplus/mod/gopmod"
)
// Module represents a Go module.
type Module = gopmod.Module
// Load loads a Go module from a directory.
func Load(dir string) (ret *Module, pkgPath string, err error) {
if dir, err = filepath.Abs(dir); err != nil {
return
}
_, gomod, err := mod.FindGoMod(dir)
if err != nil {
return
}
if ret, err = gopmod.LoadFrom(gomod, ""); err != nil {
return
}
relPath, err := filepath.Rel(ret.Root(), dir)
if err != nil {
return
}
pkgPath = path.Join(ret.Path(), filepath.ToSlash(relPath))
return
}

110
internal/projs/proj.go Normal file
View File

@@ -0,0 +1,110 @@
/*
* 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 projs
import (
"errors"
"path/filepath"
"syscall"
)
// -----------------------------------------------------------------------------
type Proj = interface {
projObj()
}
type FilesProj struct {
Files []string
}
type PkgPathProj struct {
Path string
}
type DirProj struct {
Dir string
}
func (p *FilesProj) projObj() {}
func (p *PkgPathProj) projObj() {}
func (p *DirProj) projObj() {}
// -----------------------------------------------------------------------------
func ParseOne(args ...string) (proj Proj, next []string, err error) {
if len(args) == 0 {
return nil, nil, syscall.ENOENT
}
arg := args[0]
if isFile(arg) {
n := 1
for n < len(args) && isFile(args[n]) {
n++
}
return &FilesProj{Files: args[:n]}, args[n:], nil
}
if isLocal(arg) {
return &DirProj{Dir: arg}, args[1:], nil
}
return &PkgPathProj{Path: arg}, args[1:], nil
}
func isFile(fname string) bool {
n := len(filepath.Ext(fname))
return n > 1
}
func isLocal(ns string) bool {
if len(ns) > 0 {
switch c := ns[0]; c {
case '/', '\\', '.':
return true
default:
return len(ns) >= 2 && ns[1] == ':' && ('A' <= c && c <= 'Z' || 'a' <= c && c <= 'z')
}
}
return false
}
// -----------------------------------------------------------------------------
func ParseAll(args ...string) (projs []Proj, err error) {
var hasFiles, hasNotFiles bool
for {
proj, next, e := ParseOne(args...)
if e != nil {
if hasFiles && hasNotFiles {
return nil, ErrMixedFilesProj
}
return
}
if _, ok := proj.(*FilesProj); ok {
hasFiles = true
} else {
hasNotFiles = true
}
projs = append(projs, proj)
args = next
}
}
var (
ErrMixedFilesProj = errors.New("mixed files project")
)
// -----------------------------------------------------------------------------

73
internal/runtime/c/c.go Normal file
View File

@@ -0,0 +1,73 @@
/*
* 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 c
import "C"
import "unsafe"
const (
LLGoPackage = "decl"
)
type (
Char = int8
Int = C.int
Pointer = unsafe.Pointer
FilePtr = unsafe.Pointer
)
//go:linkname Stdin __stdinp
var Stdin FilePtr
//go:linkname Stdout __stdoutp
var Stdout FilePtr
//go:linkname Stderr __stderrp
var Stderr FilePtr
//go:linkname Str llgo.cstr
func Str(string) *Char
//go:linkname Advance llgo.advance
func Advance(ptr Pointer, offset int) Pointer
//go:linkname Alloca llgo.alloca
func Alloca(size uintptr) Pointer
//go:linkname AllocaCStr llgo.allocaCStr
func AllocaCStr(s string) *Char
//go:linkname Unreachable llgo.unreachable
func Unreachable()
//go:linkname Rand C.rand
func Rand() Int
//go:linkname Malloc C.malloc
func Malloc(size uintptr) Pointer
//go:linkname Memcpy C.memcpy
func Memcpy(dst, src Pointer, n uintptr) Pointer
//go:linkname Memset C.memset
func Memset(s Pointer, c Int, n uintptr) Pointer
//go:linkname Printf C.printf
func Printf(format *Char, __llgo_va_list ...any) Int
//go:linkname Fprintf C.fprintf
func Fprintf(fp FilePtr, format *Char, __llgo_va_list ...any) Int

View File

@@ -0,0 +1,623 @@
; ModuleID = 'github.com/goplus/llgo/internal/runtime'
source_filename = "github.com/goplus/llgo/internal/runtime"
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
%"github.com/goplus/llgo/internal/runtime.iface" = type { ptr, ptr }
%"github.com/goplus/llgo/internal/runtime.itab" = type { ptr, ptr, i32, [4 x i8], [1 x i64] }
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 }
%"github.com/goplus/llgo/internal/abi.Type" = type { i64, i64, i32, i8, i8, i8, i8, { ptr, ptr }, ptr, i32, i32 }
%"github.com/goplus/llgo/internal/runtime.hmap" = type { i64, i8, i8, i16, i32, ptr, ptr, i64, ptr }
@"github.com/goplus/llgo/internal/runtime.TyAny" = global ptr null
@"github.com/goplus/llgo/internal/runtime.basicTypes" = global ptr null
@"github.com/goplus/llgo/internal/runtime.init$guard" = global ptr null
@"github.com/goplus/llgo/internal/runtime.sizeBasicTypes" = global ptr null
@0 = private unnamed_addr constant [21 x i8] c"I2Int: type mismatch\00", align 1
@1 = private unnamed_addr constant [26 x i8] c"slice index out of bounds\00", align 1
@2 = private unnamed_addr constant [33 x i8] c"string slice index out of bounds\00", align 1
@__stderrp = external global ptr
@3 = private unnamed_addr constant [11 x i8] c"panic: %s\0A\00", align 1
define ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 %0) {
_llgo_0:
%1 = call ptr @malloc(i64 %0)
ret ptr %1
}
define ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 %0) {
_llgo_0:
%1 = call ptr @malloc(i64 %0)
%2 = call ptr @memset(ptr %1, i32 0, i64 %0)
ret ptr %2
}
define ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 %0) {
_llgo_0:
%1 = getelementptr inbounds ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 %0
%2 = load ptr, ptr %1, align 8
ret ptr %2
}
define ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr %0, %"github.com/goplus/llgo/internal/runtime.String" %1) {
_llgo_0:
%2 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %2, i64 16)
store %"github.com/goplus/llgo/internal/runtime.String" %1, ptr %3, align 8
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %3, i32 0, i32 1
%5 = load i64, ptr %4, align 4
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %3, i32 0, i32 0
%7 = load ptr, ptr %6, align 8
%8 = call ptr @memcpy(ptr %0, ptr %7, i64 %5)
%9 = getelementptr inbounds i8, ptr %0, i64 %5
store i8 0, ptr %9, align 1
ret ptr %0
}
define ptr @"github.com/goplus/llgo/internal/runtime.CStrDup"(%"github.com/goplus/llgo/internal/runtime.String" %0) {
_llgo_0:
%1 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %1, i64 16)
store %"github.com/goplus/llgo/internal/runtime.String" %0, ptr %2, align 8
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i32 0, i32 1
%4 = load i64, ptr %3, align 4
%5 = add i64 %4, 1
%6 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 %5)
%7 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %2, align 8
%8 = call ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr %6, %"github.com/goplus/llgo/internal/runtime.String" %7)
ret ptr %8
}
define { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %1) {
_llgo_0:
%2 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %2, i64 16)
store %"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %3, align 8
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %3, i32 0, i32 0
%5 = load ptr, ptr %4, align 8
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %5, i32 0, i32 1
%7 = load ptr, ptr %6, align 8
%8 = icmp eq ptr %7, %1
br i1 %8, label %_llgo_1, label %_llgo_2
_llgo_1: ; preds = %_llgo_0
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %3, i32 0, i32 1
%10 = load ptr, ptr %9, align 8
%11 = ptrtoint ptr %10 to i64
%mrv = insertvalue { i64, i1 } poison, i64 %11, 0
%mrv1 = insertvalue { i64, i1 } %mrv, i1 true, 1
ret { i64, i1 } %mrv1
_llgo_2: ; preds = %_llgo_0
ret { i64, i1 } zeroinitializer
}
define %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.EmptyString"() {
_llgo_0:
%0 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %0, i64 16)
%2 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %1, i32 0, i32 0
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %1, i32 0, i32 1
store ptr null, ptr %2, align 8
store i64 0, ptr %3, align 4
%4 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %1, align 8
ret %"github.com/goplus/llgo/internal/runtime.String" %4
}
define i64 @"github.com/goplus/llgo/internal/runtime.I2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %1) {
_llgo_0:
%2 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %2, i64 16)
store %"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %3, align 8
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %3, i32 0, i32 0
%5 = load ptr, ptr %4, align 8
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %5, i32 0, i32 1
%7 = load ptr, ptr %6, align 8
%8 = icmp eq ptr %7, %1
br i1 %8, label %_llgo_1, label %_llgo_2
_llgo_1: ; preds = %_llgo_0
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %3, i32 0, i32 1
%10 = load ptr, ptr %9, align 8
%11 = ptrtoint ptr %10 to i64
ret i64 %11
_llgo_2: ; preds = %_llgo_0
%12 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @0, i64 20)
%13 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %12)
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %13)
unreachable
}
define %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAny"(ptr %0, ptr %1) {
_llgo_0:
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 0
%4 = load ptr, ptr @"github.com/goplus/llgo/internal/runtime.TyAny", align 8
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 1
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 2
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 4
%8 = getelementptr inbounds i64, ptr %7, i64 0
store ptr %4, ptr %3, align 8
store ptr %0, ptr %5, align 8
store i32 0, ptr %6, align 4
store i64 0, ptr %8, align 4
%9 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
%10 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %9, i64 16)
%11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %10, i32 0, i32 0
%12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %10, i32 0, i32 1
store ptr %2, ptr %11, align 8
store ptr %1, ptr %12, align 8
%13 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %10, align 8
ret %"github.com/goplus/llgo/internal/runtime.iface" %13
}
define %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %0, i64 %1) {
_llgo_0:
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 0
%4 = load ptr, ptr @"github.com/goplus/llgo/internal/runtime.TyAny", align 8
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 1
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 2
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %2, i32 0, i32 4
%8 = getelementptr inbounds i64, ptr %7, i64 0
store ptr %4, ptr %3, align 8
store ptr %0, ptr %5, align 8
store i32 0, ptr %6, align 4
store i64 0, ptr %8, align 4
%9 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
%10 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %9, i64 16)
%11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %10, i32 0, i32 0
%12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %10, i32 0, i32 1
%13 = inttoptr i64 %1 to ptr
store ptr %2, ptr %11, align 8
store ptr %13, ptr %12, align 8
%14 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %10, align 8
ret %"github.com/goplus/llgo/internal/runtime.iface" %14
}
define %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %0) {
_llgo_0:
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 16)
store %"github.com/goplus/llgo/internal/runtime.String" %0, ptr %1, align 8
%2 = load ptr, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 24), align 8
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 0
%5 = load ptr, ptr @"github.com/goplus/llgo/internal/runtime.TyAny", align 8
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 1
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 2
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 4
%9 = getelementptr inbounds i64, ptr %8, i64 0
store ptr %5, ptr %4, align 8
store ptr %2, ptr %6, align 8
store i32 0, ptr %7, align 4
store i64 0, ptr %9, align 4
%10 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
%11 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %10, i64 16)
%12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %11, i32 0, i32 0
%13 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %11, i32 0, i32 1
store ptr %3, ptr %12, align 8
store ptr %1, ptr %13, align 8
%14 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %11, align 8
ret %"github.com/goplus/llgo/internal/runtime.iface" %14
}
define %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeInterface"(ptr %0, ptr %1, ptr %2) {
_llgo_0:
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32)
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 0
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 1
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 2
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %3, i32 0, i32 4
%8 = getelementptr inbounds i64, ptr %7, i64 0
store ptr %0, ptr %4, align 8
store ptr %1, ptr %5, align 8
store i32 0, ptr %6, align 4
store i64 0, ptr %8, align 4
%9 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
%10 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %9, i64 16)
%11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %10, i32 0, i32 0
%12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %10, i32 0, i32 1
store ptr %3, ptr %11, align 8
store ptr %2, ptr %12, align 8
%13 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %10, align 8
ret %"github.com/goplus/llgo/internal/runtime.iface" %13
}
define ptr @"github.com/goplus/llgo/internal/runtime.MakeSmallMap"() {
_llgo_0:
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.makemap_small"()
ret ptr %0
}
define %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice"(ptr %0, i64 %1, i64 %2) {
_llgo_0:
%3 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %3, i64 24)
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %4, i32 0, i32 0
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %4, i32 0, i32 1
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %4, i32 0, i32 2
store ptr %0, ptr %5, align 8
store i64 %1, ptr %6, align 4
store i64 %2, ptr %7, align 4
%8 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %4, align 8
ret %"github.com/goplus/llgo/internal/runtime.Slice" %8
}
define %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5) {
_llgo_0:
%6 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8
%7 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %6, i64 24)
%8 = icmp slt i64 %3, 0
br i1 %8, label %_llgo_1, label %_llgo_5
_llgo_1: ; preds = %_llgo_5, %_llgo_4, %_llgo_3, %_llgo_0
%9 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @1, i64 25)
%10 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %9)
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %10)
unreachable
_llgo_2: ; preds = %_llgo_3
%11 = sub i64 %4, %3
%12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %7, i32 0, i32 1
store i64 %11, ptr %12, align 4
%13 = sub i64 %5, %3
%14 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %7, i32 0, i32 2
store i64 %13, ptr %14, align 4
%15 = sub i64 %5, %3
%16 = icmp sgt i64 %15, 0
br i1 %16, label %_llgo_6, label %_llgo_8
_llgo_3: ; preds = %_llgo_4
%17 = icmp sgt i64 %5, %2
br i1 %17, label %_llgo_1, label %_llgo_2
_llgo_4: ; preds = %_llgo_5
%18 = icmp slt i64 %5, %4
br i1 %18, label %_llgo_1, label %_llgo_3
_llgo_5: ; preds = %_llgo_0
%19 = icmp slt i64 %4, %3
br i1 %19, label %_llgo_1, label %_llgo_4
_llgo_6: ; preds = %_llgo_2
%20 = mul i64 %3, %1
%21 = getelementptr i8, ptr %0, i64 %20
%22 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %7, i32 0, i32 0
store ptr %21, ptr %22, align 8
br label %_llgo_7
_llgo_7: ; preds = %_llgo_8, %_llgo_6
%23 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %7, align 8
ret %"github.com/goplus/llgo/internal/runtime.Slice" %23
_llgo_8: ; preds = %_llgo_2
%24 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %7, i32 0, i32 0
store ptr %0, ptr %24, align 8
br label %_llgo_7
}
define %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr %0, i64 %1) {
_llgo_0:
%2 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %2, i64 16)
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %3, i32 0, i32 0
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %3, i32 0, i32 1
store ptr %0, ptr %4, align 8
store i64 %1, ptr %5, align 4
%6 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %3, align 8
ret %"github.com/goplus/llgo/internal/runtime.String" %6
}
define %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %0, i64 %1, i64 %2) {
_llgo_0:
%3 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %3, i64 16)
store %"github.com/goplus/llgo/internal/runtime.String" %0, ptr %4, align 8
%5 = icmp slt i64 %1, 0
br i1 %5, label %_llgo_1, label %_llgo_4
_llgo_1: ; preds = %_llgo_4, %_llgo_3, %_llgo_0
%6 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @2, i64 32)
%7 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %6)
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %7)
unreachable
_llgo_2: ; preds = %_llgo_3
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %4, i32 0, i32 1
%9 = load i64, ptr %8, align 4
%10 = icmp slt i64 %1, %9
br i1 %10, label %_llgo_5, label %_llgo_6
_llgo_3: ; preds = %_llgo_4
%11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %4, i32 0, i32 1
%12 = load i64, ptr %11, align 4
%13 = icmp sgt i64 %2, %12
br i1 %13, label %_llgo_1, label %_llgo_2
_llgo_4: ; preds = %_llgo_0
%14 = icmp slt i64 %2, %1
br i1 %14, label %_llgo_1, label %_llgo_3
_llgo_5: ; preds = %_llgo_2
%15 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%16 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %15, i64 16)
%17 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %16, i32 0, i32 0
%18 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %4, i32 0, i32 0
%19 = load ptr, ptr %18, align 8
%20 = getelementptr i8, ptr %19, i64 %1
%21 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %16, i32 0, i32 1
%22 = sub i64 %2, %1
store ptr %20, ptr %17, align 8
store i64 %22, ptr %21, align 4
%23 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %16, align 8
ret %"github.com/goplus/llgo/internal/runtime.String" %23
_llgo_6: ; preds = %_llgo_2
%24 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%25 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %24, i64 16)
%26 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %25, i32 0, i32 0
%27 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %25, i32 0, i32 1
store ptr null, ptr %26, align 8
store i64 0, ptr %27, align 4
%28 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %25, align 8
ret %"github.com/goplus/llgo/internal/runtime.String" %28
}
define %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NilSlice"() {
_llgo_0:
%0 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %0, i64 24)
%2 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %1, i32 0, i32 0
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %1, i32 0, i32 1
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %1, i32 0, i32 2
store ptr null, ptr %2, align 8
store i64 0, ptr %3, align 4
store i64 0, ptr %4, align 4
%5 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %1, align 8
ret %"github.com/goplus/llgo/internal/runtime.Slice" %5
}
define i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
_llgo_0:
%1 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %1, i64 24)
store %"github.com/goplus/llgo/internal/runtime.Slice" %0, ptr %2, align 8
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %2, i32 0, i32 2
%4 = load i64, ptr %3, align 4
ret i64 %4
}
define ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
_llgo_0:
%1 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %1, i64 24)
store %"github.com/goplus/llgo/internal/runtime.Slice" %0, ptr %2, align 8
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %2, i32 0, i32 0
%4 = load ptr, ptr %3, align 8
ret ptr %4
}
define i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %0) {
_llgo_0:
%1 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %1, i64 24)
store %"github.com/goplus/llgo/internal/runtime.Slice" %0, ptr %2, align 8
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %2, i32 0, i32 1
%4 = load i64, ptr %3, align 4
ret i64 %4
}
define %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringCat"(%"github.com/goplus/llgo/internal/runtime.String" %0, %"github.com/goplus/llgo/internal/runtime.String" %1) {
_llgo_0:
%2 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %2, i64 16)
store %"github.com/goplus/llgo/internal/runtime.String" %0, ptr %3, align 8
%4 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %4, i64 16)
store %"github.com/goplus/llgo/internal/runtime.String" %1, ptr %5, align 8
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %3, i32 0, i32 1
%7 = load i64, ptr %6, align 4
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %5, i32 0, i32 1
%9 = load i64, ptr %8, align 4
%10 = add i64 %7, %9
%11 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 %10)
%12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %3, i32 0, i32 0
%13 = load ptr, ptr %12, align 8
%14 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %3, i32 0, i32 1
%15 = load i64, ptr %14, align 4
%16 = call ptr @memcpy(ptr %11, ptr %13, i64 %15)
%17 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %3, i32 0, i32 1
%18 = load i64, ptr %17, align 4
%19 = getelementptr i8, ptr %11, i64 %18
%20 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %5, i32 0, i32 0
%21 = load ptr, ptr %20, align 8
%22 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %5, i32 0, i32 1
%23 = load i64, ptr %22, align 4
%24 = call ptr @memcpy(ptr %19, ptr %21, i64 %23)
%25 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%26 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %25, i64 16)
%27 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %26, i32 0, i32 0
%28 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %26, i32 0, i32 1
store ptr %11, ptr %27, align 8
store i64 %10, ptr %28, align 4
%29 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %26, align 8
ret %"github.com/goplus/llgo/internal/runtime.String" %29
}
define ptr @"github.com/goplus/llgo/internal/runtime.StringData"(%"github.com/goplus/llgo/internal/runtime.String" %0) {
_llgo_0:
%1 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %1, i64 16)
store %"github.com/goplus/llgo/internal/runtime.String" %0, ptr %2, align 8
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i32 0, i32 0
%4 = load ptr, ptr %3, align 8
ret ptr %4
}
define i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %0) {
_llgo_0:
%1 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %1, i64 16)
store %"github.com/goplus/llgo/internal/runtime.String" %0, ptr %2, align 8
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i32 0, i32 1
%4 = load i64, ptr %3, align 4
ret i64 %4
}
define void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %0) {
_llgo_0:
%1 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %1, i64 16)
store %"github.com/goplus/llgo/internal/runtime.iface" %0, ptr %2, align 8
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i32 0, i32 0
%4 = load ptr, ptr %3, align 8
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.itab", ptr %4, i32 0, i32 1
%6 = load ptr, ptr %5, align 8
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %6, i32 0, i32 6
%8 = load i8, ptr %7, align 1
%9 = sext i8 %8 to i64
%10 = icmp eq i64 %9, 24
br i1 %10, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_2, %_llgo_0
ret void
_llgo_2: ; preds = %_llgo_0
%11 = load ptr, ptr @__stderrp, align 8
%12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i32 0, i32 1
%13 = load ptr, ptr %12, align 8
%14 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %13, align 8
call void @"github.com/goplus/llgo/internal/runtime.stringTracef"(ptr %11, ptr @3, %"github.com/goplus/llgo/internal/runtime.String" %14)
br label %_llgo_1
}
define ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %0, i64 %1) {
_llgo_0:
%2 = call ptr @memset(ptr %0, i32 0, i64 %1)
ret ptr %2
}
define ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 %0) {
_llgo_0:
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 56)
%2 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %1, i32 0, i32 0
%3 = getelementptr inbounds i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 %0
%4 = load i64, ptr %3, align 4
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %1, i32 0, i32 2
%6 = trunc i64 %0 to i32
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Type", ptr %1, i32 0, i32 6
%8 = trunc i64 %0 to i8
store i64 %4, ptr %2, align 4
store i32 %6, ptr %5, align 4
store i8 %8, ptr %7, align 1
ret ptr %1
}
declare i32 @rand()
define void @"github.com/goplus/llgo/internal/runtime.init"() {
_llgo_0:
%0 = load i1, ptr @"github.com/goplus/llgo/internal/runtime.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"github.com/goplus/llgo/internal/runtime.init$guard", align 1
call void @"github.com/goplus/llgo/internal/abi.init"()
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 88)
store ptr %1, ptr @"github.com/goplus/llgo/internal/runtime.TyAny", align 8
store i64 1, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 1), align 4
store i64 8, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 2), align 4
store i64 1, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 3), align 4
store i64 2, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 4), align 4
store i64 4, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 5), align 4
store i64 8, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 6), align 4
store i64 8, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 7), align 4
store i64 1, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 8), align 4
store i64 2, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 9), align 4
store i64 4, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 10), align 4
store i64 8, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 11), align 4
store i64 8, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 12), align 4
store i64 4, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 13), align 4
store i64 8, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 14), align 4
store i64 8, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 15), align 4
store i64 16, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 16), align 4
store i64 16, ptr getelementptr inbounds (i64, ptr @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes", i64 24), align 4
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 1)
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 2)
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 3)
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 4)
%6 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 5)
%7 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 6)
%8 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 7)
%9 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 8)
%10 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 9)
%11 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 10)
%12 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 11)
%13 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 12)
%14 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 13)
%15 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 14)
%16 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 15)
%17 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 16)
%18 = call ptr @"github.com/goplus/llgo/internal/runtime.basicType"(i64 24)
store ptr %2, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 1), align 8
store ptr %3, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 2), align 8
store ptr %4, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 3), align 8
store ptr %5, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 4), align 8
store ptr %6, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 5), align 8
store ptr %7, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 6), align 8
store ptr %8, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 7), align 8
store ptr %9, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 8), align 8
store ptr %10, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 9), align 8
store ptr %11, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 10), align 8
store ptr %12, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 11), align 8
store ptr %13, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 12), align 8
store ptr %14, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 13), align 8
store ptr %15, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 14), align 8
store ptr %16, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 15), align 8
store ptr %17, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 16), align 8
store ptr %18, ptr getelementptr inbounds (ptr, ptr @"github.com/goplus/llgo/internal/runtime.basicTypes", i64 24), align 8
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define i1 @"github.com/goplus/llgo/internal/runtime.isEmpty"(i8 %0) {
_llgo_0:
%1 = icmp ule i8 %0, 1
ret i1 %1
}
define ptr @"github.com/goplus/llgo/internal/runtime.makemap_small"() {
_llgo_0:
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 48)
%1 = call i32 @rand()
%2 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.hmap", ptr %0, i32 0, i32 4
store i32 %1, ptr %2, align 4
ret ptr %0
}
define void @"github.com/goplus/llgo/internal/runtime.stringTracef"(ptr %0, ptr %1, %"github.com/goplus/llgo/internal/runtime.String" %2) {
_llgo_0:
%3 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %3, i64 16)
store %"github.com/goplus/llgo/internal/runtime.String" %2, ptr %4, align 8
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %4, i32 0, i32 1
%6 = load i64, ptr %5, align 4
%7 = add i64 %6, 1
%8 = alloca i8, i64 %7, align 1
%9 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %4, align 8
%10 = call ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr %8, %"github.com/goplus/llgo/internal/runtime.String" %9)
%11 = call i32 (ptr, ptr, ...) @fprintf(ptr %0, ptr %1, ptr %10)
ret void
}
declare ptr @malloc(i64)
declare ptr @memset(ptr, i32, i64)
declare ptr @memcpy(ptr, ptr, i64)
declare void @"github.com/goplus/llgo/internal/abi.init"()
declare i32 @fprintf(ptr, ptr, ...)

1726
internal/runtime/map.go Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,37 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package runtime
import (
"unsafe"
)
type iface struct {
tab *itab
data unsafe.Pointer
}
/*
type eface struct {
_type *_type
data unsafe.Pointer
}
func efaceOf(ep *any) *eface {
return (*eface)(unsafe.Pointer(ep))
}
*/
// layout of Itab known to compilers
// allocated in non-garbage-collected memory
// Needs to be in sync with
// ../cmd/compile/internal/reflectdata/reflect.go:/^func.WriteTabs.
type itab struct {
inter *interfacetype
_type *_type
hash uint32 // copy of _type.hash. Used for type switches.
_ [4]byte
fun [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter.
}

38
internal/runtime/stubs.go Normal file
View File

@@ -0,0 +1,38 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package runtime
import _ "unsafe"
//go:linkname fastrand C.rand
func fastrand() uint32
/* TODO(xsw):
func fastrand() uint32 {
mp := getg().m
// Implement wyrand: https://github.com/wangyi-fudan/wyhash
// Only the platform that math.Mul64 can be lowered
// by the compiler should be in this list.
if goarch.IsAmd64|goarch.IsArm64|goarch.IsPpc64|
goarch.IsPpc64le|goarch.IsMips64|goarch.IsMips64le|
goarch.IsS390x|goarch.IsRiscv64|goarch.IsLoong64 == 1 {
mp.fastrand += 0xa0761d6478bd642f
hi, lo := math.Mul64(mp.fastrand, mp.fastrand^0xe7037ed1a0b428db)
return uint32(hi ^ lo)
}
// Implement xorshift64+: 2 32-bit xorshift sequences added together.
// Shift triplet [17,7,16] was calculated as indicated in Marsaglia's
// Xorshift paper: https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf
// This generator passes the SmallCrush suite, part of TestU01 framework:
// http://simul.iro.umontreal.ca/testu01/tu01.html
t := (*[2]uint32)(unsafe.Pointer(&mp.fastrand))
s1, s0 := t[0], t[1]
s1 ^= s1 << 17
s1 = s1 ^ s0 ^ s1>>7 ^ s0>>16
t[0], t[1] = s0, s1
return s0 + s1
}
*/

Some files were not shown because too many files have changed in this diff Show More