mirror of https://github.com/rui314/chibicc
Do not emit static inline functions if referenced by no one
This commit is contained in:
parent
31087f8d4b
commit
e5f4ca90fd
|
@ -146,6 +146,11 @@ struct Obj {
|
||||||
Obj *locals;
|
Obj *locals;
|
||||||
Obj *va_area;
|
Obj *va_area;
|
||||||
int stack_size;
|
int stack_size;
|
||||||
|
|
||||||
|
// Static inline function
|
||||||
|
bool is_live;
|
||||||
|
bool is_root;
|
||||||
|
StringArray refs;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Global variable can be initialized either by a constant expression
|
// Global variable can be initialized either by a constant expression
|
||||||
|
|
|
@ -1199,6 +1199,11 @@ static void emit_text(Obj *prog) {
|
||||||
if (!fn->is_function || !fn->is_definition)
|
if (!fn->is_function || !fn->is_definition)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// No code is emitted for "static inline" functions
|
||||||
|
// if no one is referencing them.
|
||||||
|
if (!fn->is_live)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (fn->is_static)
|
if (fn->is_static)
|
||||||
println(" .local %s", fn->name);
|
println(" .local %s", fn->name);
|
||||||
else
|
else
|
||||||
|
|
37
parse.c
37
parse.c
|
@ -2766,6 +2766,14 @@ static Node *primary(Token **rest, Token *tok) {
|
||||||
VarScope *sc = find_var(tok);
|
VarScope *sc = find_var(tok);
|
||||||
*rest = tok->next;
|
*rest = tok->next;
|
||||||
|
|
||||||
|
// For "static inline" function
|
||||||
|
if (sc && sc->var && sc->var->is_function) {
|
||||||
|
if (current_fn)
|
||||||
|
strarray_push(¤t_fn->refs, sc->var->name);
|
||||||
|
else
|
||||||
|
sc->var->is_root = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (sc) {
|
if (sc) {
|
||||||
if (sc->var)
|
if (sc->var)
|
||||||
return new_var_node(sc->var, tok);
|
return new_var_node(sc->var, tok);
|
||||||
|
@ -2847,6 +2855,29 @@ static void resolve_goto_labels(void) {
|
||||||
gotos = labels = NULL;
|
gotos = labels = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Obj *find_func(char *name) {
|
||||||
|
Scope *sc = scope;
|
||||||
|
while (sc->next)
|
||||||
|
sc = sc->next;
|
||||||
|
|
||||||
|
for (VarScope *sc2 = sc->vars; sc2; sc2 = sc2->next)
|
||||||
|
if (!strcmp(sc2->name, name) && sc2->var && sc2->var->is_function)
|
||||||
|
return sc2->var;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mark_live(Obj *var) {
|
||||||
|
if (!var->is_function || var->is_live)
|
||||||
|
return;
|
||||||
|
var->is_live = true;
|
||||||
|
|
||||||
|
for (int i = 0; i < var->refs.len; i++) {
|
||||||
|
Obj *fn = find_func(var->refs.data[i]);
|
||||||
|
if (fn)
|
||||||
|
mark_live(fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static Token *function(Token *tok, Type *basety, VarAttr *attr) {
|
static Token *function(Token *tok, Type *basety, VarAttr *attr) {
|
||||||
Type *ty = declarator(&tok, tok, basety);
|
Type *ty = declarator(&tok, tok, basety);
|
||||||
if (!ty->name)
|
if (!ty->name)
|
||||||
|
@ -2857,6 +2888,7 @@ static Token *function(Token *tok, Type *basety, VarAttr *attr) {
|
||||||
fn->is_definition = !consume(&tok, tok, ";");
|
fn->is_definition = !consume(&tok, tok, ";");
|
||||||
fn->is_static = attr->is_static || (attr->is_inline && !attr->is_extern);
|
fn->is_static = attr->is_static || (attr->is_inline && !attr->is_extern);
|
||||||
fn->is_inline = attr->is_inline;
|
fn->is_inline = attr->is_inline;
|
||||||
|
fn->is_root = !(fn->is_static && fn->is_inline);
|
||||||
|
|
||||||
if (!fn->is_definition)
|
if (!fn->is_definition)
|
||||||
return tok;
|
return tok;
|
||||||
|
@ -2953,5 +2985,10 @@ Obj *parse(Token *tok) {
|
||||||
// Global variable
|
// Global variable
|
||||||
tok = global_variable(tok, basety, &attr);
|
tok = global_variable(tok, basety, &attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (Obj *var = globals; var; var = var->next)
|
||||||
|
if (var->is_root)
|
||||||
|
mark_live(var);
|
||||||
|
|
||||||
return globals;
|
return globals;
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,4 +125,40 @@ echo 'int foo(); int main() { foo(); }' > $tmp/inline2.c
|
||||||
$chibicc -o /dev/null $tmp/inline1.c $tmp/inline2.c
|
$chibicc -o /dev/null $tmp/inline1.c $tmp/inline2.c
|
||||||
check inline
|
check inline
|
||||||
|
|
||||||
|
echo 'static inline void f1() {}' | $chibicc -o- -S - | grep -v -q f1:
|
||||||
|
check inline
|
||||||
|
|
||||||
|
echo 'static inline void f1() {} void foo() { f1(); }' | $chibicc -o- -S - | grep -q f1:
|
||||||
|
check inline
|
||||||
|
|
||||||
|
echo 'static inline void f1() {} static inline void f2() { f1(); } void foo() { f1(); }' | $chibicc -o- -S - | grep -q f1:
|
||||||
|
check inline
|
||||||
|
|
||||||
|
echo 'static inline void f1() {} static inline void f2() { f1(); } void foo() { f1(); }' | $chibicc -o- -S - | grep -v -q f2:
|
||||||
|
check inline
|
||||||
|
|
||||||
|
echo 'static inline void f1() {} static inline void f2() { f1(); } void foo() { f2(); }' | $chibicc -o- -S - | grep -q f1:
|
||||||
|
check inline
|
||||||
|
|
||||||
|
echo 'static inline void f1() {} static inline void f2() { f1(); } void foo() { f2(); }' | $chibicc -o- -S - | grep -q f2:
|
||||||
|
check inline
|
||||||
|
|
||||||
|
echo 'static inline void f2(); static inline void f1() { f2(); } static inline void f2() { f1(); } void foo() {}' | $chibicc -o- -S - | grep -v -q f1:
|
||||||
|
check inline
|
||||||
|
|
||||||
|
echo 'static inline void f2(); static inline void f1() { f2(); } static inline void f2() { f1(); } void foo() {}' | $chibicc -o- -S - | grep -v -q f2:
|
||||||
|
check inline
|
||||||
|
|
||||||
|
echo 'static inline void f2(); static inline void f1() { f2(); } static inline void f2() { f1(); } void foo() { f1(); }' | $chibicc -o- -S - | grep -q f1:
|
||||||
|
check inline
|
||||||
|
|
||||||
|
echo 'static inline void f2(); static inline void f1() { f2(); } static inline void f2() { f1(); } void foo() { f1(); }' | $chibicc -o- -S - | grep -q f2:
|
||||||
|
check inline
|
||||||
|
|
||||||
|
echo 'static inline void f2(); static inline void f1() { f2(); } static inline void f2() { f1(); } void foo() { f2(); }' | $chibicc -o- -S - | grep -q f1:
|
||||||
|
check inline
|
||||||
|
|
||||||
|
echo 'static inline void f2(); static inline void f1() { f2(); } static inline void f2() { f1(); } void foo() { f2(); }' | $chibicc -o- -S - | grep -q f2:
|
||||||
|
check inline
|
||||||
|
|
||||||
echo OK
|
echo OK
|
||||||
|
|
Loading…
Reference in New Issue