Skip to content

Commit

Permalink
cxgo: rewrite free instead of relying on the preprocessor
Browse files Browse the repository at this point in the history
  • Loading branch information
dennwc committed Jan 21, 2021
1 parent b5a67ab commit bbd1132
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 2 deletions.
9 changes: 9 additions & 0 deletions c_expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ type Expr interface {
Uses() []types.Usage
}

func canAssignTo(x Expr) bool {
x = cUnwrap(x)
switch x.(type) {
case Ident, *Deref, *CSelectExpr, *CIndexExpr:
return true
}
return false
}

type Ident interface {
Expr
Identifier() *types.Ident
Expand Down
4 changes: 2 additions & 2 deletions libs/stdlib.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func init() {
"malloc": c.C().MallocFunc(),
"calloc": c.C().CallocFunc(),
"realloc": c.NewIdent("realloc", "libc.Realloc", libc.Realloc, c.FuncTT(voidPtr, voidPtr, gintT)),
"free": c.NewIdent("free", "libc.Free", libc.Free, c.FuncTT(nil, voidPtr)),
"free": c.C().FreeFunc(),
"atoi": c.NewIdent("atoi", "libc.Atoi", libc.Atoi, c.FuncTT(gintT, gstrT)),
"atol": c.NewIdent("atol", "libc.Atoi", libc.Atoi, c.FuncTT(gintT, gstrT)),
"atof": c.NewIdent("atof", "libc.Atof", libc.Atof, c.FuncTT(types.FloatT(8), gstrT)),
Expand All @@ -52,7 +52,7 @@ func init() {
#define malloc __builtin_malloc
#define abort __builtin_abort
#define free(x) x = 0
void free(void*);
typedef struct {
int quot;
Expand Down
45 changes: 45 additions & 0 deletions postproc.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,48 @@ func (g *translator) fixImplicitReturnStmt(ret types.Type, st CStmt) bool {
return false
}
}

func (g *translator) rewriteFree(decl []CDecl) {
for _, d := range decl {
f, ok := d.(*CFuncDecl)
if !ok || f.Body == nil {
continue
}
g.rewriteFreeStmts(f.Body.Stmts)
}
}

func (g *translator) rewriteFreeStmts(stmts []CStmt) {
for i, st := range stmts {
if s, ok := g.rewriteFreeStmt(st); ok {
stmts[i] = s
}
}
}

func (g *translator) rewriteFreeStmt(st CStmt) (CStmt, bool) {
switch st := st.(type) {
case *CExprStmt:
if c, ok := st.Expr.(*CallExpr); ok && len(c.Args) == 1 && canAssignTo(c.Args[0]) {
if id, ok := c.Fun.(Ident); ok && id.Identifier() == g.env.C().FreeFunc() {
return g.NewCAssignStmtP(c.Args[0], "", g.Nil()), true
}
}
case *BlockStmt:
g.rewriteFreeStmts(st.Stmts)
case *CIfStmt:
g.rewriteFreeStmts(st.Then.Stmts)
if st.Else != nil {
if e, ok := g.rewriteFreeStmt(st.Else); ok {
st.Else = g.toElseStmt(e)
}
}
case *CForStmt:
g.rewriteFreeStmts(st.Body.Stmts)
case *CSwitchStmt:
for _, c := range st.Cases {
g.rewriteFreeStmts(c.Stmts)
}
}
return st, false
}
1 change: 1 addition & 0 deletions translate.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ func (g *translator) translateMain(d *CFuncDecl) {

func (g *translator) translate(cur string, ast *cc.AST) []GoDecl {
decl := g.translateC(cur, ast)
g.rewriteFree(decl)
if g.conf.FixImplicitReturns {
g.fixImplicitReturns(decl)
}
Expand Down
7 changes: 7 additions & 0 deletions types/env_c.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type C struct {
charT Type
wcharT Type
mallocF *Ident
freeF *Ident
callocF *Ident
memmoveF *Ident
memcpyF *Ident
Expand Down Expand Up @@ -60,6 +61,7 @@ func (c *C) init() {

unsafePtr := g.UnsafePtr()
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()))
Expand Down Expand Up @@ -208,6 +210,11 @@ func (c *C) MallocFunc() *Ident {
return c.mallocF
}

// FreeFunc returns C free function ident.
func (c *C) FreeFunc() *Ident {
return c.freeF
}

// CallocFunc returns C calloc function ident.
func (c *C) CallocFunc() *Ident {
return c.callocF
Expand Down

0 comments on commit bbd1132

Please sign in to comment.