llgo.string; c string library
This commit is contained in:
58
c/c.go
58
c/c.go
@@ -77,8 +77,64 @@ 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, n ...int) string
|
||||
func GoString(cstr *Char, __llgo_va_list /* n */ ...any) string
|
||||
|
||||
//go:linkname GoStringData llgo.stringData
|
||||
func GoStringData(string) *Char
|
||||
|
||||
@@ -59,7 +59,7 @@ _llgo_1: ; preds = %_llgo_3
|
||||
store i64 7, ptr %4, align 4
|
||||
%5 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %2, align 8
|
||||
%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)
|
||||
%9 = extractvalue { i32, i64 } %8, 0
|
||||
%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 %"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")
|
||||
|
||||
|
||||
@@ -700,7 +700,7 @@ _llgo_2: ; preds = %_llgo_0
|
||||
%12 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1
|
||||
%13 = load i64, ptr %12, align 4
|
||||
%14 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %11, 1
|
||||
%15 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %11, i64 %13, i64 %14)
|
||||
%15 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %11, i64 %13, i64 %14)
|
||||
%16 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %15, 0
|
||||
%17 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %15, 1
|
||||
%18 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCopy"(%"github.com/goplus/llgo/internal/runtime.Slice" %1, ptr %16, i64 %17, i64 1)
|
||||
@@ -746,7 +746,7 @@ _llgo_4: ; preds = %_llgo_2
|
||||
%14 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 0
|
||||
%15 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %14, align 8
|
||||
%16 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %15, 1
|
||||
%17 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %15, i64 %2, i64 %16)
|
||||
%17 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %15, i64 %2, i64 %16)
|
||||
%18 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %17, 0
|
||||
%19 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %17, 1
|
||||
%20 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCopy"(%"github.com/goplus/llgo/internal/runtime.Slice" %1, ptr %18, i64 %19, i64 1)
|
||||
@@ -860,7 +860,7 @@ _llgo_4: ; preds = %_llgo_2
|
||||
%31 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1
|
||||
%32 = load i64, ptr %31, align 4
|
||||
%33 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %30, 1
|
||||
%34 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %30, i64 %32, i64 %33)
|
||||
%34 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %30, i64 %32, i64 %33)
|
||||
%35 = call { i32, i64 } @"unicode/utf8.DecodeRuneInString"(%"github.com/goplus/llgo/internal/runtime.String" %34)
|
||||
%36 = extractvalue { i32, i64 } %35, 0
|
||||
%37 = extractvalue { i32, i64 } %35, 1
|
||||
@@ -1041,7 +1041,7 @@ _llgo_2: ; preds = %_llgo_0
|
||||
%11 = getelementptr inbounds %main.stringReader, ptr %0, i32 0, i32 1
|
||||
%12 = load i64, ptr %11, align 4
|
||||
%13 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %10, 1
|
||||
%14 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %10, i64 %12, i64 %13)
|
||||
%14 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %10, i64 %12, i64 %13)
|
||||
%15 = call { i64, %"github.com/goplus/llgo/internal/runtime.iface" } @main.WriteString(%"github.com/goplus/llgo/internal/runtime.iface" %1, %"github.com/goplus/llgo/internal/runtime.String" %14)
|
||||
%16 = extractvalue { i64, %"github.com/goplus/llgo/internal/runtime.iface" } %15, 0
|
||||
%17 = extractvalue { i64, %"github.com/goplus/llgo/internal/runtime.iface" } %15, 1
|
||||
@@ -2724,7 +2724,7 @@ declare void @"github.com/goplus/llgo/internal/runtime.PrintIface"(%"github.com/
|
||||
|
||||
declare void @"github.com/goplus/llgo/internal/runtime.Panic"(%"github.com/goplus/llgo/internal/runtime.eface")
|
||||
|
||||
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 i64 @"github.com/goplus/llgo/internal/runtime.SliceCopy"(%"github.com/goplus/llgo/internal/runtime.Slice", ptr, i64, i64)
|
||||
|
||||
|
||||
@@ -229,14 +229,14 @@ _llgo_0:
|
||||
store i64 5, ptr %74, align 4
|
||||
%75 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %72, align 8
|
||||
%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
|
||||
%79 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %78, i32 0, i32 0
|
||||
store ptr @0, ptr %79, align 8
|
||||
%80 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %78, i32 0, i32 1
|
||||
store i64 5, ptr %80, align 4
|
||||
%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
|
||||
%84 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %83, i32 0, i32 0
|
||||
store ptr @0, ptr %84, align 8
|
||||
@@ -244,7 +244,7 @@ _llgo_0:
|
||||
store i64 5, ptr %85, align 4
|
||||
%86 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %83, align 8
|
||||
%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
|
||||
%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
|
||||
@@ -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 %"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")
|
||||
|
||||
|
||||
@@ -381,8 +381,9 @@ const (
|
||||
llgoAllocaCStr = llgoInstrBase + 3
|
||||
llgoAdvance = llgoInstrBase + 4
|
||||
llgoIndex = llgoInstrBase + 5
|
||||
llgoStringData = llgoInstrBase + 6
|
||||
llgoDeferData = llgoInstrBase + 7
|
||||
llgoDeferData = llgoInstrBase + 6
|
||||
llgoStringData = llgoInstrBase + 7
|
||||
llgoString = llgoInstrBase + 8
|
||||
|
||||
llgoSigjmpbuf = llgoInstrBase + 0xa
|
||||
llgoSigsetjmp = llgoInstrBase + 0xb
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
// 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 (p *context) stringData(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
|
||||
if len(args) == 1 {
|
||||
@@ -147,6 +158,7 @@ var llgoInstrs = map[string]int{
|
||||
"index": llgoIndex,
|
||||
"alloca": llgoAlloca,
|
||||
"allocaCStr": llgoAllocaCStr,
|
||||
"string": llgoString,
|
||||
"stringData": llgoStringData,
|
||||
"pyList": llgoPyList,
|
||||
"sigjmpbuf": llgoSigjmpbuf,
|
||||
@@ -297,6 +309,8 @@ func (p *context) call(b llssa.Builder, act llssa.DoAction, call *ssa.CallCommon
|
||||
ret = p.alloca(b, args)
|
||||
case llgoAllocaCStr:
|
||||
ret = p.allocaCStr(b, args)
|
||||
case llgoString:
|
||||
ret = p.string(b, args)
|
||||
case llgoStringData:
|
||||
ret = p.stringData(b, args)
|
||||
case llgoAtomicLoad:
|
||||
|
||||
@@ -86,12 +86,12 @@ func toMode(mode FileMode) os.ModeT {
|
||||
panic("todo")
|
||||
}
|
||||
|
||||
func toPathErr(op, path string, errno c.Int) error {
|
||||
func toSyscallErr(errno c.Int) error {
|
||||
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 {
|
||||
@@ -255,7 +255,7 @@ func Setenv(key, value string) error {
|
||||
if ret == 0 {
|
||||
return nil
|
||||
}
|
||||
return &SyscallError{Syscall: "setenv", Err: toSyscallErr(ret)}
|
||||
return &SyscallError{"setenv", toSyscallErr(ret)}
|
||||
}
|
||||
|
||||
func Symlink(oldname, newname string) error {
|
||||
|
||||
@@ -50,8 +50,7 @@ func StringCat(a, b String) String {
|
||||
func CStrCopy(dest unsafe.Pointer, s String) *int8 {
|
||||
n := s.len
|
||||
c.Memcpy(dest, s.data, uintptr(n))
|
||||
arr := (*[1 << 30]int8)(dest)
|
||||
arr[n] = 0
|
||||
*(*int8)(c.Advance(dest, n)) = 0
|
||||
return (*int8)(dest)
|
||||
}
|
||||
|
||||
@@ -60,7 +59,7 @@ func CStrDup(s String) *int8 {
|
||||
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 {
|
||||
panic("string slice index out of bounds")
|
||||
}
|
||||
@@ -121,13 +120,21 @@ func StringToRunes(s string) []rune {
|
||||
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) {
|
||||
if b.len == 0 {
|
||||
return StringFrom(b.data, b.len)
|
||||
}
|
||||
|
||||
func StringFrom(data unsafe.Pointer, n int) (s String) {
|
||||
if n == 0 {
|
||||
return
|
||||
}
|
||||
s.len = b.len
|
||||
s.data = AllocU(uintptr(s.len))
|
||||
c.Memcpy(s.data, b.data, uintptr(b.len))
|
||||
s.len = n
|
||||
s.data = AllocU(uintptr(n))
|
||||
c.Memcpy(s.data, data, uintptr(n))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -64,6 +64,21 @@ func (b Builder) getField(x Expr, idx int) Expr {
|
||||
return Expr{fld, tfld}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// MakeString creates a new string from a C string pointer and length.
|
||||
func (b Builder) MakeString(cstr Expr, n ...Expr) Expr {
|
||||
if debugInstr {
|
||||
log.Printf("MakeString %v\n", cstr.impl)
|
||||
}
|
||||
pkg := b.Pkg
|
||||
if len(n) == 0 {
|
||||
return b.Call(pkg.rtFunc("StringFromCStr"), cstr)
|
||||
}
|
||||
// TODO(xsw): remove Convert
|
||||
return b.Call(pkg.rtFunc("StringFrom"), cstr, b.Convert(b.Prog.Int(), n[0]))
|
||||
}
|
||||
|
||||
// StringData returns the data pointer of a string.
|
||||
func (b Builder) StringData(x Expr) Expr {
|
||||
if debugInstr {
|
||||
@@ -82,6 +97,8 @@ func (b Builder) StringLen(x Expr) Expr {
|
||||
return Expr{ptr, b.Prog.Int()}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// SliceData returns the data pointer of a slice.
|
||||
func (b Builder) SliceData(x Expr) Expr {
|
||||
if debugInstr {
|
||||
@@ -109,6 +126,8 @@ func (b Builder) SliceCap(x Expr) Expr {
|
||||
return Expr{ptr, b.Prog.Int()}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// The IndexAddr instruction yields the address of the element at
|
||||
// index `idx` of collection `x`. `idx` is an integer expression.
|
||||
//
|
||||
@@ -277,6 +296,8 @@ func (b Builder) Index(x, idx Expr, addr func(Expr) (Expr, bool)) Expr {
|
||||
return b.Load(buf)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// The Slice instruction yields a slice of an existing string, slice
|
||||
// or *array X between optional integer bounds Low and High.
|
||||
//
|
||||
@@ -310,7 +331,7 @@ func (b Builder) Slice(x, low, high, max Expr) (ret Expr) {
|
||||
high = b.StringLen(x)
|
||||
}
|
||||
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
|
||||
case *types.Slice:
|
||||
nEltSize = SizeOf(prog, prog.Index(x.Type))
|
||||
|
||||
Reference in New Issue
Block a user