Merge pull request #364 from xushiwei/q
patch: io, io/fs, os; llgo.string; c string library; demo: getcwd; abi.TypeName fix: error interface is public
This commit is contained in:
11
_demo/getcwd/getcwd.go
Normal file
11
_demo/getcwd/getcwd.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
wd := os.Getcwd(c.Alloca(os.PATH_MAX), os.PATH_MAX)
|
||||||
|
c.Printf(c.Str("cwd: %s\n"), wd)
|
||||||
|
}
|
||||||
59
c/c.go
59
c/c.go
@@ -77,6 +77,65 @@ func Memset(s Pointer, c Int, n uintptr) Pointer
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//go:linkname Strlen C.strlen
|
||||||
|
func Strlen(s *Char) uintptr
|
||||||
|
|
||||||
|
//go:linkname Strcpy C.strcpy
|
||||||
|
func Strcpy(dst, src *Char) *Char
|
||||||
|
|
||||||
|
//go:linkname Strncpy C.strncpy
|
||||||
|
func Strncpy(dst, src *Char, n uintptr) *Char
|
||||||
|
|
||||||
|
//go:linkname Strcat C.strcat
|
||||||
|
func Strcat(dst, src *Char) *Char
|
||||||
|
|
||||||
|
//go:linkname Strncat C.strncat
|
||||||
|
func Strncat(dst, src *Char, n uintptr) *Char
|
||||||
|
|
||||||
|
//go:linkname Strcmp C.strcmp
|
||||||
|
func Strcmp(s1, s2 *Char) Int
|
||||||
|
|
||||||
|
//go:linkname Strncmp C.strncmp
|
||||||
|
func Strncmp(s1, s2 *Char, n uintptr) Int
|
||||||
|
|
||||||
|
//go:linkname Strchr C.strchr
|
||||||
|
func Strchr(s *Char, c Int) *Char
|
||||||
|
|
||||||
|
//go:linkname Strrchr C.strrchr
|
||||||
|
func Strrchr(s *Char, c Int) *Char
|
||||||
|
|
||||||
|
//go:linkname Strstr C.strstr
|
||||||
|
func Strstr(s1, s2 *Char) *Char
|
||||||
|
|
||||||
|
//go:linkname Strdup C.strdup
|
||||||
|
func Strdup(s *Char) *Char
|
||||||
|
|
||||||
|
//go:linkname Strndup C.strndup
|
||||||
|
func Strndup(s *Char, n uintptr) *Char
|
||||||
|
|
||||||
|
//go:linkname Strtok C.strtok
|
||||||
|
func Strtok(s, delim *Char) *Char
|
||||||
|
|
||||||
|
//go:linkname Strerror C.strerror
|
||||||
|
func Strerror(errnum Int) *Char
|
||||||
|
|
||||||
|
//go:linkname Sprintf C.sprintf
|
||||||
|
func Sprintf(s *Char, format *Char, __llgo_va_list ...any) Int
|
||||||
|
|
||||||
|
//go:linkname Snprintf C.snprintf
|
||||||
|
func Snprintf(s *Char, n uintptr, format *Char, __llgo_va_list ...any) Int
|
||||||
|
|
||||||
|
//go:linkname Vsnprintf C.vsnprintf
|
||||||
|
func Vsnprintf(s *Char, n uintptr, format *Char, ap Pointer) Int
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// GoString converts a C string to a Go string.
|
||||||
|
// TODO(xsw): any => int
|
||||||
|
//
|
||||||
|
//go:linkname GoString llgo.string
|
||||||
|
func GoString(cstr *Char, __llgo_va_list /* n */ ...any) string
|
||||||
|
|
||||||
//go:linkname GoStringData llgo.stringData
|
//go:linkname GoStringData llgo.stringData
|
||||||
func GoStringData(string) *Char
|
func GoStringData(string) *Char
|
||||||
|
|
||||||
|
|||||||
225
c/os/os.go
Normal file
225
c/os/os.go
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
/*
|
||||||
|
* 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 os
|
||||||
|
|
||||||
|
// #include <sys/stat.h>
|
||||||
|
// #include <limits.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoPackage = "decl"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
PATH_MAX = C.PATH_MAX
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
ModeT C.mode_t
|
||||||
|
UidT C.uid_t
|
||||||
|
GidT C.gid_t
|
||||||
|
OffT C.off_t
|
||||||
|
DevT C.dev_t
|
||||||
|
StatT C.struct_stat
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:linkname Errno errno
|
||||||
|
var Errno c.Int
|
||||||
|
|
||||||
|
//go:linkname Umask C.umask
|
||||||
|
func Umask(cmask ModeT) ModeT
|
||||||
|
|
||||||
|
//go:linkname Mkdir C.mkdir
|
||||||
|
func Mkdir(path *c.Char, mode ModeT) c.Int
|
||||||
|
|
||||||
|
//go:linkname Rmdir C.rmdir
|
||||||
|
func Rmdir(path *c.Char) c.Int
|
||||||
|
|
||||||
|
//go:linkname Link C.link
|
||||||
|
func Link(oldpath *c.Char, newpath *c.Char) c.Int
|
||||||
|
|
||||||
|
//go:linkname Symlink C.symlink
|
||||||
|
func Symlink(target *c.Char, linkpath *c.Char) c.Int
|
||||||
|
|
||||||
|
//go:linkname Readlink C.readlink
|
||||||
|
func Readlink(path *c.Char, buf c.Pointer, bufsize uintptr) int
|
||||||
|
|
||||||
|
//go:linkname Unlink C.unlink
|
||||||
|
func Unlink(path *c.Char) c.Int
|
||||||
|
|
||||||
|
//go:linkname Remove C.remove
|
||||||
|
func Remove(path *c.Char) c.Int
|
||||||
|
|
||||||
|
//go:linkname Rename C.rename
|
||||||
|
func Rename(oldpath *c.Char, newpath *c.Char) c.Int
|
||||||
|
|
||||||
|
//go:linkname Stat C.stat
|
||||||
|
func Stat(path *c.Char, buf *StatT) c.Int
|
||||||
|
|
||||||
|
//go:linkname Lstat C.lstat
|
||||||
|
func Lstat(path *c.Char, buf *StatT) c.Int
|
||||||
|
|
||||||
|
//go:linkname Truncate C.truncate
|
||||||
|
func Truncate(path *c.Char, length OffT) c.Int
|
||||||
|
|
||||||
|
//go:linkname Chmod C.chmod
|
||||||
|
func Chmod(path *c.Char, mode ModeT) c.Int
|
||||||
|
|
||||||
|
//go:linkname Chown C.chown
|
||||||
|
func Chown(path *c.Char, owner UidT, group GidT) c.Int
|
||||||
|
|
||||||
|
//go:linkname Lchown C.lchown
|
||||||
|
func Lchown(path *c.Char, owner UidT, group GidT) c.Int
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//go:linkname Getcwd C.getcwd
|
||||||
|
func Getcwd(buffer c.Pointer, size uintptr) *c.Char
|
||||||
|
|
||||||
|
//go:linkname Chdir C.chdir
|
||||||
|
func Chdir(path *c.Char) c.Int
|
||||||
|
|
||||||
|
//go:linkname Chroot C.chroot
|
||||||
|
func Chroot(path *c.Char) c.Int
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//go:linkname Environ C.environ
|
||||||
|
func Environ() **c.Char
|
||||||
|
|
||||||
|
//go:linkname Getenv C.getenv
|
||||||
|
func Getenv(name *c.Char) *c.Char
|
||||||
|
|
||||||
|
//go:linkname Setenv C.setenv
|
||||||
|
func Setenv(name *c.Char, value *c.Char, overwrite c.Int) c.Int
|
||||||
|
|
||||||
|
//go:linkname Putenv C.putenv
|
||||||
|
func Putenv(env *c.Char) c.Int
|
||||||
|
|
||||||
|
//go:linkname Unsetenv C.unsetenv
|
||||||
|
func Unsetenv(name *c.Char) c.Int
|
||||||
|
|
||||||
|
//go:linkname Clearenv C.clearenv
|
||||||
|
func Clearenv()
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//go:linkname Fchdir C.fchdir
|
||||||
|
func Fchdir(dirfd c.Int) c.Int
|
||||||
|
|
||||||
|
//go:linkname Faccessat C.faccessat
|
||||||
|
func Faccessat(dirfd c.Int, path *c.Char, mode c.Int, flags c.Int) c.Int
|
||||||
|
|
||||||
|
//go:linkname Fchmodat C.fchmodat
|
||||||
|
func Fchmodat(dirfd c.Int, path *c.Char, mode ModeT, flags c.Int) c.Int
|
||||||
|
|
||||||
|
//go:linkname Fchownat C.fchownat
|
||||||
|
func Fchownat(dirfd c.Int, path *c.Char, owner UidT, group GidT, flags c.Int) c.Int
|
||||||
|
|
||||||
|
//go:linkname Fstatat C.fstatat
|
||||||
|
func Fstatat(dirfd c.Int, path *c.Char, buf *StatT, flags c.Int) c.Int
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//go:linkname Open C.open
|
||||||
|
func Open(path *c.Char, flags c.Int, mode ModeT) c.Int
|
||||||
|
|
||||||
|
//go:linkname Creat C.creat
|
||||||
|
func Creat(path *c.Char, mode ModeT) c.Int
|
||||||
|
|
||||||
|
//go:linkname Dup C.dup
|
||||||
|
func Dup(fd c.Int) c.Int
|
||||||
|
|
||||||
|
//go:linkname Dup2 C.dup2
|
||||||
|
func Dup2(oldfd c.Int, newfd c.Int) c.Int
|
||||||
|
|
||||||
|
/* TODO(xsw):
|
||||||
|
On Alpha, IA-64, MIPS, SuperH, and SPARC/SPARC64, pipe() has the following prototype:
|
||||||
|
struct fd_pair {
|
||||||
|
long fd[2];
|
||||||
|
};
|
||||||
|
struct fd_pair pipe(void);
|
||||||
|
*/
|
||||||
|
//go:linkname Pipe C.pipe
|
||||||
|
func Pipe(fds *[2]c.Int) c.Int
|
||||||
|
|
||||||
|
//go:linkname Mkfifo C.mkfifo
|
||||||
|
func Mkfifo(path *c.Char, mode ModeT) c.Int
|
||||||
|
|
||||||
|
//go:linkname Mknod C.mknod
|
||||||
|
func Mknod(path *c.Char, mode ModeT, dev DevT) c.Int
|
||||||
|
|
||||||
|
//go:linkname Close C.close
|
||||||
|
func Close(fd c.Int) c.Int
|
||||||
|
|
||||||
|
//go:linkname Read C.read
|
||||||
|
func Read(fd c.Int, buf c.Pointer, count uintptr) int
|
||||||
|
|
||||||
|
//go:linkname Write C.write
|
||||||
|
func Write(fd c.Int, buf c.Pointer, count uintptr) int
|
||||||
|
|
||||||
|
//go:linkname Lseek C.lseek
|
||||||
|
func Lseek(fd c.Int, offset OffT, whence c.Int) OffT
|
||||||
|
|
||||||
|
//go:linkname Fsync C.fsync
|
||||||
|
func Fsync(fd c.Int) c.Int
|
||||||
|
|
||||||
|
//go:linkname Ftruncate C.ftruncate
|
||||||
|
func Ftruncate(fd c.Int, length OffT) c.Int
|
||||||
|
|
||||||
|
//go:linkname Fchmod C.fchmod
|
||||||
|
func Fchmod(fd c.Int, mode ModeT) c.Int
|
||||||
|
|
||||||
|
//go:linkname Fchown C.fchown
|
||||||
|
func Fchown(fd c.Int, owner UidT, group GidT) c.Int
|
||||||
|
|
||||||
|
//go:linkname Fstat C.fstat
|
||||||
|
func Fstat(fd c.Int, buf *StatT) c.Int
|
||||||
|
|
||||||
|
//go:linkname Isatty C.isatty
|
||||||
|
func Isatty(fd c.Int) c.Int
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//go:linkname Exit C.exit
|
||||||
|
func Exit(c.Int)
|
||||||
|
|
||||||
|
//go:linkname Getpid C.getpid
|
||||||
|
func Getpid() c.Int
|
||||||
|
|
||||||
|
//go:linkname Getppid C.getppid
|
||||||
|
func Getppid() c.Int
|
||||||
|
|
||||||
|
//go:linkname Getuid C.getuid
|
||||||
|
func Getuid() UidT
|
||||||
|
|
||||||
|
//go:linkname Geteuid C.geteuid
|
||||||
|
func Geteuid() UidT
|
||||||
|
|
||||||
|
//go:linkname Getgid C.getgid
|
||||||
|
func Getgid() GidT
|
||||||
|
|
||||||
|
//go:linkname Getegid C.getegid
|
||||||
|
func Getegid() GidT
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
@@ -47,10 +47,10 @@ func (o *Once) Do(f func()) c.Int { return 0 }
|
|||||||
type MutexType c.Int
|
type MutexType c.Int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MutexNormal MutexType = C.PTHREAD_MUTEX_NORMAL
|
MUTEX_NORMAL MutexType = C.PTHREAD_MUTEX_NORMAL
|
||||||
MutexErrorCheck MutexType = C.PTHREAD_MUTEX_ERRORCHECK
|
MUTEX_ERRORCHECK MutexType = C.PTHREAD_MUTEX_ERRORCHECK
|
||||||
MutexRecursive MutexType = C.PTHREAD_MUTEX_RECURSIVE
|
MUTEX_RECURSIVE MutexType = C.PTHREAD_MUTEX_RECURSIVE
|
||||||
MutexDefault MutexType = C.PTHREAD_MUTEX_DEFAULT
|
MUTEX_DEFAULT MutexType = C.PTHREAD_MUTEX_DEFAULT
|
||||||
)
|
)
|
||||||
|
|
||||||
// MutexAttr is a mutex attribute object.
|
// MutexAttr is a mutex attribute object.
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ _llgo_1: ; preds = %_llgo_3
|
|||||||
store i64 7, ptr %4, align 4
|
store i64 7, ptr %4, align 4
|
||||||
%5 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %2, align 8
|
%5 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %2, align 8
|
||||||
%6 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %5, 1
|
%6 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %5, 1
|
||||||
%7 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %5, i64 %15, i64 %6)
|
%7 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %5, i64 %15, i64 %6)
|
||||||
%8 = call { i32, i64 } @"unicode/utf8.DecodeRuneInString"(%"github.com/goplus/llgo/internal/runtime.String" %7)
|
%8 = call { i32, i64 } @"unicode/utf8.DecodeRuneInString"(%"github.com/goplus/llgo/internal/runtime.String" %7)
|
||||||
%9 = extractvalue { i32, i64 } %8, 0
|
%9 = extractvalue { i32, i64 } %8, 0
|
||||||
%10 = extractvalue { i32, i64 } %8, 1
|
%10 = extractvalue { i32, i64 } %8, 1
|
||||||
@@ -95,7 +95,7 @@ declare void @"unicode/utf8.init"()
|
|||||||
|
|
||||||
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
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 %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringSlice"(%"github.com/goplus/llgo/internal/runtime.String", i64, i64)
|
||||||
|
|
||||||
declare { i32, i64 } @"unicode/utf8.DecodeRuneInString"(%"github.com/goplus/llgo/internal/runtime.String")
|
declare { i32, i64 } @"unicode/utf8.DecodeRuneInString"(%"github.com/goplus/llgo/internal/runtime.String")
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -14,6 +14,8 @@ func f() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
println(c.GoString(c.Str("sync.Once demo\n"), 9))
|
||||||
|
println(c.GoString(c.Str("sync.Once demo\n")))
|
||||||
f()
|
f()
|
||||||
f()
|
f()
|
||||||
}
|
}
|
||||||
|
|||||||
11
cl/_testlibgo/os/in.go
Normal file
11
cl/_testlibgo/os/in.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
wd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
println("cwd:", wd)
|
||||||
|
}
|
||||||
95
cl/_testlibgo/os/out.ll
Normal file
95
cl/_testlibgo/os/out.ll
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
; 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 }
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.eface" = type { ptr, ptr }
|
||||||
|
|
||||||
|
@"main.init$guard" = global i1 false, align 1
|
||||||
|
@__llgo_argc = global i32 0, align 4
|
||||||
|
@__llgo_argv = global ptr null, align 8
|
||||||
|
@0 = private unnamed_addr constant [4 x i8] c"cwd:", 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
|
||||||
|
call void @os.init()
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @main(i32 %0, ptr %1) {
|
||||||
|
_llgo_0:
|
||||||
|
store i32 %0, ptr @__llgo_argc, align 4
|
||||||
|
store ptr %1, ptr @__llgo_argv, align 8
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%2 = call { %"github.com/goplus/llgo/internal/runtime.String", %"github.com/goplus/llgo/internal/runtime.iface" } @os.Getwd()
|
||||||
|
%3 = extractvalue { %"github.com/goplus/llgo/internal/runtime.String", %"github.com/goplus/llgo/internal/runtime.iface" } %2, 0
|
||||||
|
%4 = extractvalue { %"github.com/goplus/llgo/internal/runtime.String", %"github.com/goplus/llgo/internal/runtime.iface" } %2, 1
|
||||||
|
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.IfaceType"(%"github.com/goplus/llgo/internal/runtime.iface" %4)
|
||||||
|
%6 = extractvalue %"github.com/goplus/llgo/internal/runtime.iface" %4, 1
|
||||||
|
%7 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8
|
||||||
|
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %7, i32 0, i32 0
|
||||||
|
store ptr %5, ptr %8, align 8
|
||||||
|
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %7, i32 0, i32 1
|
||||||
|
store ptr %6, ptr %9, align 8
|
||||||
|
%10 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %7, align 8
|
||||||
|
%11 = call ptr @"github.com/goplus/llgo/internal/runtime.IfaceType"(%"github.com/goplus/llgo/internal/runtime.iface" zeroinitializer)
|
||||||
|
%12 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8
|
||||||
|
%13 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %12, i32 0, i32 0
|
||||||
|
store ptr %11, ptr %13, align 8
|
||||||
|
%14 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %12, i32 0, i32 1
|
||||||
|
store ptr null, ptr %14, align 8
|
||||||
|
%15 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %12, align 8
|
||||||
|
%16 = call i1 @"github.com/goplus/llgo/internal/runtime.EfaceEqual"(%"github.com/goplus/llgo/internal/runtime.eface" %10, %"github.com/goplus/llgo/internal/runtime.eface" %15)
|
||||||
|
%17 = xor i1 %16, true
|
||||||
|
br i1 %17, label %_llgo_1, label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%18 = call ptr @"github.com/goplus/llgo/internal/runtime.IfaceType"(%"github.com/goplus/llgo/internal/runtime.iface" %4)
|
||||||
|
%19 = extractvalue %"github.com/goplus/llgo/internal/runtime.iface" %4, 1
|
||||||
|
%20 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8
|
||||||
|
%21 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %20, i32 0, i32 0
|
||||||
|
store ptr %18, ptr %21, align 8
|
||||||
|
%22 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %20, i32 0, i32 1
|
||||||
|
store ptr %19, ptr %22, align 8
|
||||||
|
%23 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %20, align 8
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.Panic"(%"github.com/goplus/llgo/internal/runtime.eface" %23)
|
||||||
|
unreachable
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_0
|
||||||
|
%24 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%25 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %24, i32 0, i32 0
|
||||||
|
store ptr @0, ptr %25, align 8
|
||||||
|
%26 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %24, i32 0, i32 1
|
||||||
|
store i64 4, ptr %26, align 4
|
||||||
|
%27 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %24, align 8
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %27)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %3)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @os.init()
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare { %"github.com/goplus/llgo/internal/runtime.String", %"github.com/goplus/llgo/internal/runtime.iface" } @os.Getwd()
|
||||||
|
|
||||||
|
declare i1 @"github.com/goplus/llgo/internal/runtime.EfaceEqual"(%"github.com/goplus/llgo/internal/runtime.eface", %"github.com/goplus/llgo/internal/runtime.eface")
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.IfaceType"(%"github.com/goplus/llgo/internal/runtime.iface")
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.Panic"(%"github.com/goplus/llgo/internal/runtime.eface")
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String")
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8)
|
||||||
@@ -229,14 +229,14 @@ _llgo_0:
|
|||||||
store i64 5, ptr %74, align 4
|
store i64 5, ptr %74, align 4
|
||||||
%75 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %72, align 8
|
%75 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %72, align 8
|
||||||
%76 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %75, 1
|
%76 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %75, 1
|
||||||
%77 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %75, i64 1, i64 %76)
|
%77 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %75, i64 1, i64 %76)
|
||||||
%78 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
%78 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
%79 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %78, i32 0, i32 0
|
%79 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %78, i32 0, i32 0
|
||||||
store ptr @0, ptr %79, align 8
|
store ptr @0, ptr %79, align 8
|
||||||
%80 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %78, i32 0, i32 1
|
%80 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %78, i32 0, i32 1
|
||||||
store i64 5, ptr %80, align 4
|
store i64 5, ptr %80, align 4
|
||||||
%81 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %78, align 8
|
%81 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %78, align 8
|
||||||
%82 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %81, i64 1, i64 2)
|
%82 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %81, i64 1, i64 2)
|
||||||
%83 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
%83 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
%84 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %83, i32 0, i32 0
|
%84 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %83, i32 0, i32 0
|
||||||
store ptr @0, ptr %84, align 8
|
store ptr @0, ptr %84, align 8
|
||||||
@@ -244,7 +244,7 @@ _llgo_0:
|
|||||||
store i64 5, ptr %85, align 4
|
store i64 5, ptr %85, align 4
|
||||||
%86 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %83, align 8
|
%86 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %83, align 8
|
||||||
%87 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %86, 1
|
%87 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %86, 1
|
||||||
%88 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %86, i64 5, i64 %87)
|
%88 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %86, i64 5, i64 %87)
|
||||||
%89 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %88, 1
|
%89 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %88, 1
|
||||||
%90 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
%90 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
%91 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %90, i32 0, i32 0
|
%91 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %90, i32 0, i32 0
|
||||||
@@ -654,7 +654,7 @@ declare void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8)
|
|||||||
|
|
||||||
declare void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64)
|
declare void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64)
|
||||||
|
|
||||||
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 %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringSlice"(%"github.com/goplus/llgo/internal/runtime.String", i64, i64)
|
||||||
|
|
||||||
declare void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String")
|
declare void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String")
|
||||||
|
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ func TestErrBuiltin(t *testing.T) {
|
|||||||
test("advance", func(ctx *context) { ctx.advance(nil, nil) })
|
test("advance", func(ctx *context) { ctx.advance(nil, nil) })
|
||||||
test("alloca", func(ctx *context) { ctx.alloca(nil, nil) })
|
test("alloca", func(ctx *context) { ctx.alloca(nil, nil) })
|
||||||
test("allocaCStr", func(ctx *context) { ctx.allocaCStr(nil, nil) })
|
test("allocaCStr", func(ctx *context) { ctx.allocaCStr(nil, nil) })
|
||||||
|
test("string", func(ctx *context) { ctx.string(nil, nil) })
|
||||||
test("stringData", func(ctx *context) { ctx.stringData(nil, nil) })
|
test("stringData", func(ctx *context) { ctx.stringData(nil, nil) })
|
||||||
test("sigsetjmp", func(ctx *context) { ctx.sigsetjmp(nil, nil) })
|
test("sigsetjmp", func(ctx *context) { ctx.sigsetjmp(nil, nil) })
|
||||||
test("siglongjmp", func(ctx *context) { ctx.siglongjmp(nil, nil) })
|
test("siglongjmp", func(ctx *context) { ctx.siglongjmp(nil, nil) })
|
||||||
|
|||||||
@@ -381,8 +381,9 @@ const (
|
|||||||
llgoAllocaCStr = llgoInstrBase + 3
|
llgoAllocaCStr = llgoInstrBase + 3
|
||||||
llgoAdvance = llgoInstrBase + 4
|
llgoAdvance = llgoInstrBase + 4
|
||||||
llgoIndex = llgoInstrBase + 5
|
llgoIndex = llgoInstrBase + 5
|
||||||
llgoStringData = llgoInstrBase + 6
|
llgoDeferData = llgoInstrBase + 6
|
||||||
llgoDeferData = llgoInstrBase + 7
|
llgoStringData = llgoInstrBase + 7
|
||||||
|
llgoString = llgoInstrBase + 8
|
||||||
|
|
||||||
llgoSigjmpbuf = llgoInstrBase + 0xa
|
llgoSigjmpbuf = llgoInstrBase + 0xa
|
||||||
llgoSigsetjmp = llgoInstrBase + 0xb
|
llgoSigsetjmp = llgoInstrBase + 0xb
|
||||||
@@ -520,8 +521,8 @@ func ignoreName(name string) bool {
|
|||||||
return strings.HasPrefix(name, "internal/") || strings.HasPrefix(name, "crypto/") ||
|
return strings.HasPrefix(name, "internal/") || strings.HasPrefix(name, "crypto/") ||
|
||||||
strings.HasPrefix(name, "arena.") || strings.HasPrefix(name, "maps.") ||
|
strings.HasPrefix(name, "arena.") || strings.HasPrefix(name, "maps.") ||
|
||||||
strings.HasPrefix(name, "time.") || strings.HasPrefix(name, "syscall.") ||
|
strings.HasPrefix(name, "time.") || strings.HasPrefix(name, "syscall.") ||
|
||||||
strings.HasPrefix(name, "os.") || strings.HasPrefix(name, "plugin.") ||
|
strings.HasPrefix(name, "plugin.") || strings.HasPrefix(name, "reflect.") ||
|
||||||
strings.HasPrefix(name, "reflect.") || strings.HasPrefix(name, "runtime/")
|
strings.HasPrefix(name, "runtime/")
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
14
cl/instr.go
14
cl/instr.go
@@ -74,6 +74,17 @@ func (p *context) allocaCStr(b llssa.Builder, args []ssa.Value) (ret llssa.Expr)
|
|||||||
panic("allocaCStr(s string): invalid arguments")
|
panic("allocaCStr(s string): invalid arguments")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func string(cstr *int8, n ...int) *int8
|
||||||
|
func (p *context) string(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
|
||||||
|
if len(args) == 2 {
|
||||||
|
cstr := p.compileValue(b, args[0])
|
||||||
|
n := make([]llssa.Expr, 0, 1)
|
||||||
|
n = p.compileVArg(n, b, args[1])
|
||||||
|
return b.MakeString(cstr, n...)
|
||||||
|
}
|
||||||
|
panic("string(cstr *int8, n ...int): invalid arguments")
|
||||||
|
}
|
||||||
|
|
||||||
// func stringData(s string) *int8
|
// func stringData(s string) *int8
|
||||||
func (p *context) stringData(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
|
func (p *context) stringData(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
@@ -147,6 +158,7 @@ var llgoInstrs = map[string]int{
|
|||||||
"index": llgoIndex,
|
"index": llgoIndex,
|
||||||
"alloca": llgoAlloca,
|
"alloca": llgoAlloca,
|
||||||
"allocaCStr": llgoAllocaCStr,
|
"allocaCStr": llgoAllocaCStr,
|
||||||
|
"string": llgoString,
|
||||||
"stringData": llgoStringData,
|
"stringData": llgoStringData,
|
||||||
"pyList": llgoPyList,
|
"pyList": llgoPyList,
|
||||||
"sigjmpbuf": llgoSigjmpbuf,
|
"sigjmpbuf": llgoSigjmpbuf,
|
||||||
@@ -297,6 +309,8 @@ func (p *context) call(b llssa.Builder, act llssa.DoAction, call *ssa.CallCommon
|
|||||||
ret = p.alloca(b, args)
|
ret = p.alloca(b, args)
|
||||||
case llgoAllocaCStr:
|
case llgoAllocaCStr:
|
||||||
ret = p.allocaCStr(b, args)
|
ret = p.allocaCStr(b, args)
|
||||||
|
case llgoString:
|
||||||
|
ret = p.string(b, args)
|
||||||
case llgoStringData:
|
case llgoStringData:
|
||||||
ret = p.stringData(b, args)
|
ret = p.stringData(b, args)
|
||||||
case llgoAtomicLoad:
|
case llgoAtomicLoad:
|
||||||
|
|||||||
@@ -719,9 +719,12 @@ type none struct{}
|
|||||||
|
|
||||||
var hasAltPkg = map[string]none{
|
var hasAltPkg = map[string]none{
|
||||||
"errors": {},
|
"errors": {},
|
||||||
|
"io": {},
|
||||||
|
"io/fs": {},
|
||||||
"math": {},
|
"math": {},
|
||||||
"sync": {},
|
"sync": {},
|
||||||
"sync/atomic": {},
|
"sync/atomic": {},
|
||||||
|
"os": {},
|
||||||
"runtime": {},
|
"runtime": {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
52
internal/lib/io/fs/fs.go
Normal file
52
internal/lib/io/fs/fs.go
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* 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 fs
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// A FileMode represents a file's mode and permission bits.
|
||||||
|
// The bits have the same definition on all systems, so that
|
||||||
|
// information about files can be moved from one system
|
||||||
|
// to another portably. Not all bits apply to all systems.
|
||||||
|
// The only required bit is [ModeDir] for directories.
|
||||||
|
type FileMode uint32
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// PathError records an error and the operation and file path that caused it.
|
||||||
|
type PathError struct {
|
||||||
|
Op string
|
||||||
|
Path string
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *PathError) Error() string { return e.Op + " " + e.Path + ": " + e.Err.Error() }
|
||||||
|
|
||||||
|
func (e *PathError) Unwrap() error { return e.Err }
|
||||||
|
|
||||||
|
// Timeout reports whether this error represents a timeout.
|
||||||
|
func (e *PathError) Timeout() bool {
|
||||||
|
t, ok := e.Err.(interface{ Timeout() bool })
|
||||||
|
return ok && t.Timeout()
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
22
internal/lib/io/io.go
Normal file
22
internal/lib/io/io.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
)
|
||||||
292
internal/lib/os/os.go
Normal file
292
internal/lib/os/os.go
Normal file
@@ -0,0 +1,292 @@
|
|||||||
|
/*
|
||||||
|
* 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 os
|
||||||
|
|
||||||
|
// llgo:skipall
|
||||||
|
import (
|
||||||
|
"io/fs"
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/os"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LLGoPackage = true
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
FileMode = fs.FileMode
|
||||||
|
)
|
||||||
|
|
||||||
|
type timeout interface {
|
||||||
|
Timeout() bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type PathError = fs.PathError
|
||||||
|
|
||||||
|
// SyscallError records an error from a specific system call.
|
||||||
|
type SyscallError struct {
|
||||||
|
Syscall string
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SyscallError) Error() string { return e.Syscall + ": " + e.Err.Error() }
|
||||||
|
|
||||||
|
func (e *SyscallError) Unwrap() error { return e.Err }
|
||||||
|
|
||||||
|
// Timeout reports whether this error represents a timeout.
|
||||||
|
func (e *SyscallError) Timeout() bool {
|
||||||
|
t, ok := e.Err.(timeout)
|
||||||
|
return ok && t.Timeout()
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSyscallError returns, as an error, a new SyscallError
|
||||||
|
// with the given system call name and error details.
|
||||||
|
// As a convenience, if err is nil, NewSyscallError returns nil.
|
||||||
|
func NewSyscallError(syscall string, err error) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &SyscallError{syscall, err}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LinkError records an error during a link or symlink or rename
|
||||||
|
// system call and the paths that caused it.
|
||||||
|
type LinkError struct {
|
||||||
|
Op string
|
||||||
|
Old string
|
||||||
|
New string
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *LinkError) Error() string {
|
||||||
|
return e.Op + " " + e.Old + " " + e.New + ": " + e.Err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *LinkError) Unwrap() error {
|
||||||
|
return e.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
func toMode(mode FileMode) os.ModeT {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func toSyscallErr(errno c.Int) error {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func toPathErr(op, path string, errno c.Int) error {
|
||||||
|
return &PathError{Op: op, Path: path, Err: toSyscallErr(errno)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Chdir(dir string) error {
|
||||||
|
ret := os.Chdir(c.AllocaCStr(dir))
|
||||||
|
if ret == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return toPathErr("chdir", dir, ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Chmod(name string, mode FileMode) error {
|
||||||
|
ret := os.Chmod(c.AllocaCStr(name), toMode(mode))
|
||||||
|
if ret == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return toPathErr("chmod", name, ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Chown(name string, uid, gid int) error {
|
||||||
|
ret := os.Chown(c.AllocaCStr(name), os.UidT(uid), os.GidT(gid))
|
||||||
|
if ret == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return toPathErr("chown", name, ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(xsw):
|
||||||
|
// func Chtimes(name string, atime time.Time, mtime time.Time) error
|
||||||
|
|
||||||
|
//go:linkname Clearenv C.clearenv
|
||||||
|
func Clearenv()
|
||||||
|
|
||||||
|
// TODO(xsw):
|
||||||
|
// func DirFS(dir string) fs.FS
|
||||||
|
// func Environ() []string
|
||||||
|
// func Executable() (string, error)
|
||||||
|
|
||||||
|
func Exit(code int) {
|
||||||
|
os.Exit(c.Int(code))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(xsw):
|
||||||
|
// func Expand(s string, mapping func(string) string) string
|
||||||
|
// func ExpandEnv(s string) string
|
||||||
|
|
||||||
|
func Getegid() int {
|
||||||
|
return int(os.Getegid())
|
||||||
|
}
|
||||||
|
|
||||||
|
func Getenv(key string) string {
|
||||||
|
return c.GoString(os.Getenv(c.AllocaCStr(key)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Geteuid() int {
|
||||||
|
return int(os.Geteuid())
|
||||||
|
}
|
||||||
|
|
||||||
|
func Getgid() int {
|
||||||
|
return int(os.Getgid())
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(xsw):
|
||||||
|
// func Getgroups() ([]int, error)
|
||||||
|
// func Getpagesize() int
|
||||||
|
|
||||||
|
func Getpid() int {
|
||||||
|
return int(os.Getpid())
|
||||||
|
}
|
||||||
|
|
||||||
|
func Getppid() int {
|
||||||
|
return int(os.Getppid())
|
||||||
|
}
|
||||||
|
|
||||||
|
func Getuid() int {
|
||||||
|
return int(os.Getuid())
|
||||||
|
}
|
||||||
|
|
||||||
|
func Getwd() (dir string, err error) {
|
||||||
|
wd := os.Getcwd(c.Alloca(os.PATH_MAX), os.PATH_MAX)
|
||||||
|
if wd != nil {
|
||||||
|
return c.GoString(wd), nil
|
||||||
|
}
|
||||||
|
return "", toSyscallErr(os.Errno)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(xsw):
|
||||||
|
// func Hostname() (name string, err error)
|
||||||
|
// func IsExist(err error) bool
|
||||||
|
// func IsNotExist(err error) bool
|
||||||
|
// func IsPathSeparator(c uint8) bool
|
||||||
|
// func IsPermission(err error) bool
|
||||||
|
// func IsTimeout(err error) bool
|
||||||
|
|
||||||
|
func Lchown(name string, uid, gid int) error {
|
||||||
|
ret := os.Lchown(c.AllocaCStr(name), os.UidT(uid), os.GidT(gid))
|
||||||
|
if ret == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return toPathErr("lchown", name, ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Link(oldname, newname string) error {
|
||||||
|
ret := os.Link(c.AllocaCStr(oldname), c.AllocaCStr(newname))
|
||||||
|
if ret == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &LinkError{"link", oldname, newname, toSyscallErr(ret)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(xsw):
|
||||||
|
// func LookupEnv(key string) (string, bool)
|
||||||
|
|
||||||
|
func Mkdir(name string, perm FileMode) error {
|
||||||
|
ret := os.Mkdir(c.AllocaCStr(name), toMode(perm))
|
||||||
|
if ret == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return toPathErr("mkdir", name, ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(xsw):
|
||||||
|
// func MkdirAll(path string, perm FileMode) error
|
||||||
|
// func MkdirTemp(dir, pattern string) (string, error)
|
||||||
|
// func NewSyscallError(syscall string, err error) error
|
||||||
|
// func Pipe() (r *File, w *File, err error)
|
||||||
|
// func ReadFile(name string) ([]byte, error)
|
||||||
|
|
||||||
|
func Readlink(name string) (string, error) {
|
||||||
|
ptr := c.Alloca(os.PATH_MAX)
|
||||||
|
ret := os.Readlink(c.AllocaCStr(name), ptr, os.PATH_MAX)
|
||||||
|
if ret < os.PATH_MAX {
|
||||||
|
return c.GoString((*c.Char)(ptr), ret), nil
|
||||||
|
}
|
||||||
|
panic("todo: buffer too small")
|
||||||
|
}
|
||||||
|
|
||||||
|
func Remove(name string) error {
|
||||||
|
ret := os.Remove(c.AllocaCStr(name))
|
||||||
|
if ret == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return toPathErr("remove", name, ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(xsw):
|
||||||
|
// func RemoveAll(path string) error
|
||||||
|
|
||||||
|
func Rename(oldpath, newpath string) error {
|
||||||
|
ret := os.Rename(c.AllocaCStr(oldpath), c.AllocaCStr(newpath))
|
||||||
|
if ret == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &LinkError{"rename", oldpath, newpath, toSyscallErr(ret)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(xsw):
|
||||||
|
// func SameFile(fi1, fi2 FileInfo) bool
|
||||||
|
|
||||||
|
func Setenv(key, value string) error {
|
||||||
|
ret := os.Setenv(c.AllocaCStr(key), c.AllocaCStr(value), 1)
|
||||||
|
if ret == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &SyscallError{"setenv", toSyscallErr(ret)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Symlink(oldname, newname string) error {
|
||||||
|
ret := os.Symlink(c.AllocaCStr(oldname), c.AllocaCStr(newname))
|
||||||
|
if ret == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &LinkError{"symlink", oldname, newname, toSyscallErr(ret)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(xsw):
|
||||||
|
// func TempDir() string
|
||||||
|
|
||||||
|
func Truncate(name string, size int64) error {
|
||||||
|
ret := os.Truncate(c.AllocaCStr(name), os.OffT(size))
|
||||||
|
if ret == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return toPathErr("truncate", name, ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Unsetenv(key string) error {
|
||||||
|
ret := os.Unsetenv(c.AllocaCStr(key))
|
||||||
|
if ret == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return toSyscallErr(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(xsw):
|
||||||
|
// func UserCacheDir() (string, error)
|
||||||
|
// func UserConfigDir() (string, error)
|
||||||
|
// func UserHomeDir() (string, error)
|
||||||
|
// func WriteFile(name string, data []byte, perm FileMode) error
|
||||||
@@ -50,8 +50,7 @@ func StringCat(a, b String) String {
|
|||||||
func CStrCopy(dest unsafe.Pointer, s String) *int8 {
|
func CStrCopy(dest unsafe.Pointer, s String) *int8 {
|
||||||
n := s.len
|
n := s.len
|
||||||
c.Memcpy(dest, s.data, uintptr(n))
|
c.Memcpy(dest, s.data, uintptr(n))
|
||||||
arr := (*[1 << 30]int8)(dest)
|
*(*int8)(c.Advance(dest, n)) = 0
|
||||||
arr[n] = 0
|
|
||||||
return (*int8)(dest)
|
return (*int8)(dest)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +59,7 @@ func CStrDup(s String) *int8 {
|
|||||||
return CStrCopy(dest, s)
|
return CStrCopy(dest, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStringSlice(base String, i, j int) String {
|
func StringSlice(base String, i, j int) String {
|
||||||
if i < 0 || j < i || j > base.len {
|
if i < 0 || j < i || j > base.len {
|
||||||
panic("string slice index out of bounds")
|
panic("string slice index out of bounds")
|
||||||
}
|
}
|
||||||
@@ -121,13 +120,21 @@ func StringToRunes(s string) []rune {
|
|||||||
return data[:index:index]
|
return data[:index:index]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func StringFromCStr(cstr *int8) (s String) {
|
||||||
|
return StringFrom(unsafe.Pointer(cstr), int(c.Strlen(cstr)))
|
||||||
|
}
|
||||||
|
|
||||||
func StringFromBytes(b Slice) (s String) {
|
func StringFromBytes(b Slice) (s String) {
|
||||||
if b.len == 0 {
|
return StringFrom(b.data, b.len)
|
||||||
|
}
|
||||||
|
|
||||||
|
func StringFrom(data unsafe.Pointer, n int) (s String) {
|
||||||
|
if n == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.len = b.len
|
s.len = n
|
||||||
s.data = AllocU(uintptr(s.len))
|
s.data = AllocU(uintptr(n))
|
||||||
c.Memcpy(s.data, b.data, uintptr(b.len))
|
c.Memcpy(s.data, data, uintptr(n))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -154,7 +154,8 @@ func (b *Builder) TypeName(t types.Type) (ret string, pub bool) {
|
|||||||
return fmt.Sprintf("[%v]%s", t.Len(), ret), pub
|
return fmt.Sprintf("[%v]%s", t.Len(), ret), pub
|
||||||
case *types.Named:
|
case *types.Named:
|
||||||
o := t.Obj()
|
o := t.Obj()
|
||||||
return "_llgo_" + TypeName(o), o.Exported()
|
pkg := o.Pkg()
|
||||||
|
return "_llgo_" + FullName(pkg, o.Name()), (pkg == nil || o.Exported())
|
||||||
case *types.Interface:
|
case *types.Interface:
|
||||||
if t.Empty() {
|
if t.Empty() {
|
||||||
return "_llgo_any", true
|
return "_llgo_any", true
|
||||||
|
|||||||
@@ -64,6 +64,25 @@ func (b Builder) getField(x Expr, idx int) Expr {
|
|||||||
return Expr{fld, tfld}
|
return Expr{fld, tfld}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// MakeString creates a new string from a C string pointer and length.
|
||||||
|
func (b Builder) MakeString(cstr Expr, n ...Expr) (ret Expr) {
|
||||||
|
if debugInstr {
|
||||||
|
log.Printf("MakeString %v\n", cstr.impl)
|
||||||
|
}
|
||||||
|
pkg := b.Pkg
|
||||||
|
prog := b.Prog
|
||||||
|
ret.Type = prog.String()
|
||||||
|
if len(n) == 0 {
|
||||||
|
ret.impl = b.Call(pkg.rtFunc("StringFromCStr"), cstr).impl
|
||||||
|
} else {
|
||||||
|
// TODO(xsw): remove Convert
|
||||||
|
ret.impl = b.Call(pkg.rtFunc("StringFrom"), cstr, b.Convert(prog.Int(), n[0])).impl
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// StringData returns the data pointer of a string.
|
// StringData returns the data pointer of a string.
|
||||||
func (b Builder) StringData(x Expr) Expr {
|
func (b Builder) StringData(x Expr) Expr {
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
@@ -82,6 +101,8 @@ func (b Builder) StringLen(x Expr) Expr {
|
|||||||
return Expr{ptr, b.Prog.Int()}
|
return Expr{ptr, b.Prog.Int()}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// SliceData returns the data pointer of a slice.
|
// SliceData returns the data pointer of a slice.
|
||||||
func (b Builder) SliceData(x Expr) Expr {
|
func (b Builder) SliceData(x Expr) Expr {
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
@@ -109,6 +130,8 @@ func (b Builder) SliceCap(x Expr) Expr {
|
|||||||
return Expr{ptr, b.Prog.Int()}
|
return Expr{ptr, b.Prog.Int()}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// The IndexAddr instruction yields the address of the element at
|
// The IndexAddr instruction yields the address of the element at
|
||||||
// index `idx` of collection `x`. `idx` is an integer expression.
|
// index `idx` of collection `x`. `idx` is an integer expression.
|
||||||
//
|
//
|
||||||
@@ -277,6 +300,8 @@ func (b Builder) Index(x, idx Expr, addr func(Expr) (Expr, bool)) Expr {
|
|||||||
return b.Load(buf)
|
return b.Load(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// The Slice instruction yields a slice of an existing string, slice
|
// The Slice instruction yields a slice of an existing string, slice
|
||||||
// or *array X between optional integer bounds Low and High.
|
// or *array X between optional integer bounds Low and High.
|
||||||
//
|
//
|
||||||
@@ -310,7 +335,7 @@ func (b Builder) Slice(x, low, high, max Expr) (ret Expr) {
|
|||||||
high = b.StringLen(x)
|
high = b.StringLen(x)
|
||||||
}
|
}
|
||||||
ret.Type = x.Type
|
ret.Type = x.Type
|
||||||
ret.impl = b.InlineCall(b.Pkg.rtFunc("NewStringSlice"), x, low, high).impl
|
ret.impl = b.InlineCall(b.Pkg.rtFunc("StringSlice"), x, low, high).impl
|
||||||
return
|
return
|
||||||
case *types.Slice:
|
case *types.Slice:
|
||||||
nEltSize = SizeOf(prog, prog.Index(x.Type))
|
nEltSize = SizeOf(prog, prog.Index(x.Type))
|
||||||
|
|||||||
Reference in New Issue
Block a user