From aeacff34c071b910614cb55a0e9c9787c40530e8 Mon Sep 17 00:00:00 2001 From: Denys Smirnov Date: Sun, 16 Oct 2022 15:40:35 +0300 Subject: [PATCH] Remove strdup/strndup when cloning Go strings. --- c_expr.go | 5 ++--- funcs.go | 14 ++++++++++++++ libs/builtin.go | 2 ++ libs/string.go | 6 ++---- types/env_c.go | 15 +++++++++++++++ 5 files changed, 35 insertions(+), 7 deletions(-) diff --git a/c_expr.go b/c_expr.go index e948c01..5be9961 100644 --- a/c_expr.go +++ b/c_expr.go @@ -1438,9 +1438,8 @@ func (e *SliceExpr) HasSideEffects() bool { return false } -func (e *SliceExpr) CType(types.Type) types.Type { - arr := types.Unwrap(e.Expr.CType(nil)).(types.ArrayType) - return types.SliceT(arr.Elem()) +func (e *SliceExpr) CType(exp types.Type) types.Type { + return e.Expr.CType(exp) } func (e *SliceExpr) AsExpr() GoExpr { diff --git a/funcs.go b/funcs.go index d87587d..e0bbcf3 100644 --- a/funcs.go +++ b/funcs.go @@ -143,6 +143,20 @@ func (g *translator) NewCCallExpr(fnc FuncExpr, args []Expr) Expr { } } } + case g.env.C().StrdupFunc(): + // strdup(string) -> string + if len(args) == 1 { + if args[0].CType(nil) == g.env.Go().String() { + return args[0] + } + } + case g.env.C().StrndupFunc(): + // strndup(string, n) -> string[:n] + if len(args) == 2 { + if args[0].CType(nil) == g.env.Go().String() { + return &SliceExpr{Expr: args[0], High: args[1]} + } + } case g.env.Go().SliceFunc(): // _slice(arr, -1, 1) -> arr[:1] if len(args) == 3 || len(args) == 4 { diff --git a/libs/builtin.go b/libs/builtin.go index 324d53c..6485742 100644 --- a/libs/builtin.go +++ b/libs/builtin.go @@ -187,6 +187,8 @@ void* malloc(_cxgo_go_int); c.C().MemmoveFunc(), c.C().MemcpyFunc(), c.C().MemsetFunc(), + c.C().StrdupFunc(), + c.C().StrndupFunc(), c.NewIdent("_cxgo_func_name", "libc.FuncName", libc.FuncName, c.FuncTT(c.Go().String())), c.NewIdent("__builtin_strcpy", "libc.StrCpy", libc.StrCpy, c.FuncTT(charP, charP, charP)), c.NewIdent("__sync_lock_test_and_set", "atomic.SwapInt32", atomic.SwapInt32, c.FuncTT(int32T, c.PtrT(int32T), int32T)), diff --git a/libs/string.go b/libs/string.go index 1cedafe..289dff9 100644 --- a/libs/string.go +++ b/libs/string.go @@ -35,8 +35,6 @@ func init() { "strtok": c.NewIdent("strtok", "libc.StrTok", libc.StrTok, c.FuncTT(cstrT, cstrT, cstrT)), "strspn": c.NewIdent("strspn", "libc.StrSpn", libc.StrSpn, c.FuncTT(gintT, cstrT, cstrT)), "strcspn": c.NewIdent("strcspn", "libc.StrCSpn", libc.StrCSpn, c.FuncTT(gintT, cstrT, cstrT)), - "strdup": c.NewIdent("strdup", "libc.StrDup", libc.StrDup, c.FuncTT(cstrT, cstrT)), - "strndup": c.NewIdent("strndup", "libc.StrNDup", libc.StrNDup, c.FuncTT(cstrT, cstrT, gintT)), }, Header: ` #include <` + BuiltinH + `> @@ -59,7 +57,8 @@ _cxgo_go_int strcoll(const char *, const char *); //int strcoll_l(const char *, const char *, locale_t); char *strcpy(char *restrict, const char *restrict); _cxgo_go_int strcspn(const char *, const char *); -char *strdup(const char *); +#define strdup __builtin_strdup +#define strndup __builtin_strndup char *strerror(int); //char *strerror_l(int, locale_t); int strerror_r(int, char *, size_t); @@ -67,7 +66,6 @@ _cxgo_go_int strlen(const char *); char *strncat(char *restrict, const char *restrict, _cxgo_go_int); _cxgo_go_int strncmp(const char *, const char *, _cxgo_go_int); char *strncpy(char *restrict, const char *restrict, _cxgo_go_int); -char *strndup(const char *, _cxgo_go_int); _cxgo_go_int strnlen(const char *, _cxgo_go_int); char *strpbrk(const char *, const char *); char *strrchr(const char *, _cxgo_go_byte); diff --git a/types/env_c.go b/types/env_c.go index 165a480..5deeb9a 100644 --- a/types/env_c.go +++ b/types/env_c.go @@ -16,6 +16,8 @@ type C struct { memmoveF *Ident memcpyF *Ident memsetF *Ident + strdupF *Ident + strndupF *Ident } // C returns a package containing builtin C types. @@ -60,12 +62,15 @@ func (c *C) init() { c.pkg.NewAlias("_QWORD", "", UintT(8)) unsafePtr := g.UnsafePtr() + cstring := c.String() c.mallocF = NewIdentGo("__builtin_malloc", "libc.Malloc", c.e.FuncTT(unsafePtr, g.Int())) c.freeF = NewIdentGo("free", "libc.Free", c.e.FuncTT(nil, unsafePtr)) c.callocF = NewIdentGo("calloc", "libc.Calloc", c.e.FuncTT(unsafePtr, g.Int(), g.Int())) c.memmoveF = NewIdentGo("__builtin_memmove", "libc.MemMove", c.e.FuncTT(unsafePtr, unsafePtr, unsafePtr, g.Int())) c.memcpyF = NewIdentGo("__builtin_memcpy", "libc.MemCpy", c.e.FuncTT(unsafePtr, unsafePtr, unsafePtr, g.Int())) c.memsetF = NewIdentGo("__builtin_memset", "libc.MemSet", c.e.FuncTT(unsafePtr, unsafePtr, g.Byte(), g.Int())) + c.strdupF = NewIdentGo("__builtin_strdup", "libc.StrDup", c.e.FuncTT(cstring, cstring)) + c.strndupF = NewIdentGo("__builtin_strndup", "libc.StrNDup", c.e.FuncTT(cstring, cstring, g.Int())) } func (c *C) WCharSize() int { @@ -234,3 +239,13 @@ func (c *C) MemcpyFunc() *Ident { func (c *C) MemsetFunc() *Ident { return c.memsetF } + +// StrdupFunc returns C strdup function ident. +func (c *C) StrdupFunc() *Ident { + return c.strdupF +} + +// StrndupFunc returns C strndup function ident. +func (c *C) StrndupFunc() *Ident { + return c.strndupF +}