diff --git a/_cmptest/osexec/exec.go b/_cmptest/osexec/exec.go index ec983c4b..0ec5c09e 100644 --- a/_cmptest/osexec/exec.go +++ b/_cmptest/osexec/exec.go @@ -1,9 +1,12 @@ package main import ( + "fmt" "os" "os/exec" "runtime" + + "github.com/goplus/llgo/xtool/env/llvm" ) func main() { @@ -15,4 +18,7 @@ func main() { cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Run() + + dir := llvm.New("").BinDir() + fmt.Println(dir) } diff --git a/cl/import.go b/cl/import.go index 5d9b8b25..43d5aa0e 100644 --- a/cl/import.go +++ b/cl/import.go @@ -500,41 +500,6 @@ func (p *context) ensureLoaded(pkgTypes *types.Package) *types.Package { return pkgTypes } -func pkgKindByPath(pkgPath string) int { - switch pkgPath { - case "runtime/cgo", "unsafe": - return PkgDeclOnly - } - return PkgNormal -} - -func replaceGoName(v string, pos int) string { - switch v[:pos] { - case "runtime": - return "github.com/goplus/llgo/internal/runtime" + v[pos:] - } - return v -} - -func ignoreName(name string) bool { - /* TODO(xsw): confirm this is not needed more - if name == "unsafe.init" { - return true - } - */ - const internal = "internal/" - return (strings.HasPrefix(name, internal) && !supportedInternal(name[len(internal):])) || - strings.HasPrefix(name, "crypto/") || strings.HasPrefix(name, "runtime/") || - strings.HasPrefix(name, "arena.") || strings.HasPrefix(name, "maps.") || - strings.HasPrefix(name, "plugin.") -} - -func supportedInternal(name string) bool { - return strings.HasPrefix(name, "abi.") || strings.HasPrefix(name, "bytealg.") || - strings.HasPrefix(name, "oserror.") || strings.HasPrefix(name, "reflectlite.") || - strings.HasPrefix(name, "syscall/unix.") || strings.HasPrefix(name, "syscall/execenv.") -} - // ----------------------------------------------------------------------------- const ( @@ -600,3 +565,40 @@ func toBackground(bg string) llssa.Background { } // ----------------------------------------------------------------------------- + +func pkgKindByPath(pkgPath string) int { + switch pkgPath { + case "runtime/cgo", "unsafe": + return PkgDeclOnly + } + return PkgNormal +} + +func replaceGoName(v string, pos int) string { + switch v[:pos] { + case "runtime": + return "github.com/goplus/llgo/internal/runtime" + v[pos:] + } + return v +} + +func ignoreName(name string) bool { + /* TODO(xsw): confirm this is not needed more + if name == "unsafe.init" { + return true + } + */ + const internal = "internal/" + return (strings.HasPrefix(name, internal) && !supportedInternal(name[len(internal):])) || + strings.HasPrefix(name, "crypto/") || strings.HasPrefix(name, "runtime/") || + strings.HasPrefix(name, "arena.") || strings.HasPrefix(name, "maps.") || + strings.HasPrefix(name, "plugin.") +} + +func supportedInternal(name string) bool { + return strings.HasPrefix(name, "abi.") || strings.HasPrefix(name, "bytealg.") || + strings.HasPrefix(name, "itoa.") || strings.HasPrefix(name, "oserror.") || strings.HasPrefix(name, "reflectlite.") || + strings.HasPrefix(name, "syscall/unix.") || strings.HasPrefix(name, "syscall/execenv.") +} + +// ----------------------------------------------------------------------------- diff --git a/internal/build/build.go b/internal/build/build.go index ba27fc65..6de1e0c4 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -750,6 +750,7 @@ var hasAltPkg = map[string]none{ "fmt": {}, "internal/abi": {}, "internal/bytealg": {}, + "internal/itoa": {}, "internal/oserror": {}, "internal/reflectlite": {}, "internal/syscall/execenv": {}, diff --git a/internal/lib/fmt/print.go b/internal/lib/fmt/print.go index 88786f0a..450d5a0d 100644 --- a/internal/lib/fmt/print.go +++ b/internal/lib/fmt/print.go @@ -1218,19 +1218,16 @@ formatLoop: } func (p *pp) doPrint(a []any) { - /* - prevString := false - for argNum, arg := range a { - isString := arg != nil && reflect.TypeOf(arg).Kind() == reflect.String - // Add a space between two non-string arguments. - if argNum > 0 && !isString && !prevString { - p.buf.writeByte(' ') - } - p.printArg(arg, 'v') - prevString = isString + prevString := false + for argNum, arg := range a { + isString := arg != nil && reflect.TypeOf(arg).Kind() == reflect.String + // Add a space between two non-string arguments. + if argNum > 0 && !isString && !prevString { + p.buf.writeByte(' ') } - */ - panic("todo: fmt.(*pp).doPrint") + p.printArg(arg, 'v') + prevString = isString + } } // doPrintln is like doPrint but always adds a space between arguments diff --git a/internal/lib/internal/itoa/itoa.go b/internal/lib/internal/itoa/itoa.go new file mode 100644 index 00000000..32b15359 --- /dev/null +++ b/internal/lib/internal/itoa/itoa.go @@ -0,0 +1,34 @@ +// Copyright 2021 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. + +// Simple conversions to avoid depending on strconv. + +// llgo:skipall +package itoa + +// Itoa converts val to a decimal string. +func Itoa(val int) string { + if val < 0 { + return "-" + Uitoa(uint(-val)) + } + return Uitoa(uint(val)) +} + +// Uitoa converts val to a decimal string. +func Uitoa(val uint) string { + if val == 0 { // avoid string allocation + return "0" + } + var buf [20]byte // big enough for 64bit value base 10 + i := len(buf) - 1 + for val >= 10 { + q := val / 10 + buf[i] = byte('0' + val - q*10) + i-- + val = q + } + // val < 10 + buf[i] = byte('0' + val) + return string(buf[i:]) +} diff --git a/internal/lib/os/exec_posix.go b/internal/lib/os/exec_posix.go index 1c698988..54462588 100644 --- a/internal/lib/os/exec_posix.go +++ b/internal/lib/os/exec_posix.go @@ -7,8 +7,10 @@ package os import ( + "runtime" "syscall" + "github.com/goplus/llgo/internal/lib/internal/itoa" "github.com/goplus/llgo/internal/lib/internal/syscall/execenv" ) @@ -96,7 +98,6 @@ func (p *ProcessState) sysUsage() any { } func (p *ProcessState) String() string { - /* TODO(xsw): if p == nil { return "" } @@ -124,8 +125,6 @@ func (p *ProcessState) String() string { res += " (core dumped)" } return res - */ - panic("todo: os.ProcessState.String") } // ExitCode returns the exit code of the exited process, or -1 diff --git a/internal/lib/os/str.go b/internal/lib/os/str.go new file mode 100644 index 00000000..242c945c --- /dev/null +++ b/internal/lib/os/str.go @@ -0,0 +1,39 @@ +// 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. + +// Simple conversions to avoid depending on strconv. + +package os + +// itox converts val (an int) to a hexadecimal string. +func itox(val int) string { + if val < 0 { + return "-" + uitox(uint(-val)) + } + return uitox(uint(val)) +} + +const hex = "0123456789abcdef" + +// uitox converts val (a uint) to a hexadecimal string. +func uitox(val uint) string { + if val == 0 { // avoid string allocation + return "0x0" + } + var buf [20]byte // big enough for 64bit value base 16 + 0x + i := len(buf) - 1 + for val >= 16 { + q := val / 16 + buf[i] = hex[val%16] + i-- + val = q + } + // val < 16 + buf[i] = hex[val%16] + i-- + buf[i] = 'x' + i-- + buf[i] = '0' + return string(buf[i:]) +} diff --git a/internal/lib/syscall/exec_libc2.go b/internal/lib/syscall/exec_libc2.go index 02237240..3a5dede4 100644 --- a/internal/lib/syscall/exec_libc2.go +++ b/internal/lib/syscall/exec_libc2.go @@ -7,6 +7,8 @@ package syscall import ( + "unsafe" + "github.com/goplus/llgo/c" "github.com/goplus/llgo/c/os" "github.com/goplus/llgo/c/syscall" @@ -261,15 +263,15 @@ func forkAndExecInChild(argv0 *c.Char, argv, envv **c.Char, chroot, dir *c.Char, if fd[i] == i { // dup2(i, i) won't clear close-on-exec flag on Linux, // probably not elsewhere either. - if ret := os.Fcntl(c.Int(fd[i]), syscall.F_SETFD, 0); ret != 0 { - err1 = Errno(ret) + if ret := os.Fcntl(c.Int(fd[i]), syscall.F_SETFD, 0); ret < 0 { + err1 = Errno(os.Errno) goto childerror } continue } // The new fd is created NOT close-on-exec, - if ret := os.Dup2(c.Int(fd[i]), c.Int(i)); ret != 0 { - err1 = Errno(ret) + if ret := os.Dup2(c.Int(fd[i]), c.Int(i)); ret < 0 { + err1 = Errno(os.Errno) goto childerror } } @@ -279,10 +281,7 @@ func forkAndExecInChild(argv0 *c.Char, argv, envv **c.Char, chroot, dir *c.Char, // Programs that know they inherit fds >= 3 will need // to set them close-on-exec. for i = len(fd); i < 3; i++ { - /* TODO(xsw): - rawSyscall(abi.FuncPCABI0(libc_close_trampoline), uintptr(i), 0, 0) - */ - panic("todo: syscall.forkAndExecInChild - for i") + os.Close(c.Int(i)) } // Detach fd 0 from tty @@ -322,12 +321,9 @@ func forkAndExecInChild(argv0 *c.Char, argv, envv **c.Char, chroot, dir *c.Char, */ childerror: - /* TODO(xsw): // send error code on pipe - rawSyscall(abi.FuncPCABI0(libc_write_trampoline), uintptr(pipe), uintptr(unsafe.Pointer(&err1)), unsafe.Sizeof(err1)) + os.Write(c.Int(pipe), unsafe.Pointer(&err1), unsafe.Sizeof(err1)) for { - rawSyscall(abi.FuncPCABI0(libc_exit_trampoline), 253, 0, 0) + os.Exit(253) } - */ - panic("todo: syscall.forkAndExecInChild - childerror") }