cgen: write_fn_attr()

pull/5209/head
Alexander Medvednikov 2020-06-04 12:20:14 +02:00
parent 41dca3ef58
commit 277b7b35d0
1 changed files with 81 additions and 77 deletions

View File

@ -34,86 +34,12 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
g.cur_generic_type = 0 g.cur_generic_type = 0
return return
} }
//
if is_main && g.pref.is_liveshared { if is_main && g.pref.is_liveshared {
return return
} }
//
fn_start_pos := g.out.len fn_start_pos := g.out.len
msvc_attrs := g.write_fn_attr()
mut msvc_attrs := '' // Live
match g.attr {
'inline' {
g.write('inline ')
}
// since these are supported by GCC, clang and MSVC, we can consider them officially supported.
'no_inline' {
g.write('__NOINLINE ')
}
'irq_handler' {
g.write('__IRQHANDLER ')
}
// GCC/clang attributes
// prefixed by _ to indicate they're for advanced users only and not really supported by V.
// source for descriptions: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes
// The cold attribute on functions is used to inform the compiler that the function is unlikely
// to be executed. The function is optimized for size rather than speed and on many targets it
// is placed into a special subsection of the text section so all cold functions appear close
// together, improving code locality of non-cold parts of program.
'_cold' {
g.write('__attribute__((cold)) ')
}
// The constructor attribute causes the function to be called automatically before execution
// enters main ().
'_constructor' {
g.write('__attribute__((constructor)) ')
}
// The destructor attribute causes the function to be called automatically after main ()
// completes or exit () is called.
'_destructor' {
g.write('__attribute__((destructor)) ')
}
// Generally, inlining into a function is limited. For a function marked with this attribute,
// every call inside this function is inlined, if possible.
'_flatten' {
g.write('__attribute__((flatten)) ')
}
// The hot attribute on a function is used to inform the compiler that the function is a hot
// spot of the compiled program.
'_hot' {
g.write('__attribute__((hot)) ')
}
// This tells the compiler that a function is malloc-like, i.e., that the pointer P returned by
// the function cannot alias any other pointer valid when the function returns, and moreover no
// pointers to valid objects occur in any storage addressed by P.
'_malloc' {
g.write('__attribute__((malloc)) ')
}
// Calls to functions whose return value is not affected by changes to the observable state
// of the program and that have no observable effects on such state other than to return a
// value may lend themselves to optimizations such as common subexpression elimination.
// Declaring such functions with the const attribute allows GCC to avoid emitting some calls in
// repeated invocations of the function with the same argument values.
'_pure' {
g.write('__attribute__((const)) ')
}
// windows attributes (msvc/mingw)
// prefixed by windows to indicate they're for advanced users only and not really supported by V.
'windows_stdcall' {
msvc_attrs += '__stdcall '
}
else {
// nothing but keep V happy
}
}
//
is_livefn := g.attr == 'live' is_livefn := g.attr == 'live'
is_livemain := g.pref.is_livemain && is_livefn is_livemain := g.pref.is_livemain && is_livefn
is_liveshared := g.pref.is_liveshared && is_livefn is_liveshared := g.pref.is_liveshared && is_livefn
@ -309,6 +235,7 @@ fn (mut g Gen) write_defer_stmts_when_needed() {
} }
} }
// fn decl args
fn (mut g Gen) fn_args(args []table.Arg, is_variadic bool) ([]string, []string) { fn (mut g Gen) fn_args(args []table.Arg, is_variadic bool) ([]string, []string) {
mut fargs := []string{} mut fargs := []string{}
mut fargtypes := []string{} mut fargtypes := []string{}
@ -319,7 +246,7 @@ fn (mut g Gen) fn_args(args []table.Arg, is_variadic bool) ([]string, []string)
arg_type_sym := g.table.get_type_symbol(typ) arg_type_sym := g.table.get_type_symbol(typ)
mut arg_type_name := g.typ(typ) // arg_type_sym.name.replace('.', '__') mut arg_type_name := g.typ(typ) // arg_type_sym.name.replace('.', '__')
// if arg.name == 'xxx' { // if arg.name == 'xxx' {
// println('! ' + arg_type_name) // println('xxx arg type= ' + arg_type_name)
// } // }
is_varg := i == args.len - 1 && is_variadic is_varg := i == args.len - 1 && is_variadic
if is_varg { if is_varg {
@ -774,3 +701,80 @@ fn (mut g Gen) is_gui_app() bool {
fn (g &Gen) fileis(s string) bool { fn (g &Gen) fileis(s string) bool {
return g.file.path.contains(s) return g.file.path.contains(s)
} }
fn (mut g Gen) write_fn_attr() string{
mut msvc_attrs := ''
match g.attr {
'inline' {
g.write('inline ')
}
// since these are supported by GCC, clang and MSVC, we can consider them officially supported.
'no_inline' {
g.write('__NOINLINE ')
}
'irq_handler' {
g.write('__IRQHANDLER ')
}
// GCC/clang attributes
// prefixed by _ to indicate they're for advanced users only and not really supported by V.
// source for descriptions: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes
// The cold attribute on functions is used to inform the compiler that the function is unlikely
// to be executed. The function is optimized for size rather than speed and on many targets it
// is placed into a special subsection of the text section so all cold functions appear close
// together, improving code locality of non-cold parts of program.
'_cold' {
g.write('__attribute__((cold)) ')
}
// The constructor attribute causes the function to be called automatically before execution
// enters main ().
'_constructor' {
g.write('__attribute__((constructor)) ')
}
// The destructor attribute causes the function to be called automatically after main ()
// completes or exit () is called.
'_destructor' {
g.write('__attribute__((destructor)) ')
}
// Generally, inlining into a function is limited. For a function marked with this attribute,
// every call inside this function is inlined, if possible.
'_flatten' {
g.write('__attribute__((flatten)) ')
}
// The hot attribute on a function is used to inform the compiler that the function is a hot
// spot of the compiled program.
'_hot' {
g.write('__attribute__((hot)) ')
}
// This tells the compiler that a function is malloc-like, i.e., that the pointer P returned by
// the function cannot alias any other pointer valid when the function returns, and moreover no
// pointers to valid objects occur in any storage addressed by P.
'_malloc' {
g.write('__attribute__((malloc)) ')
}
// Calls to functions whose return value is not affected by changes to the observable state
// of the program and that have no observable effects on such state other than to return a
// value may lend themselves to optimizations such as common subexpression elimination.
// Declaring such functions with the const attribute allows GCC to avoid emitting some calls in
// repeated invocations of the function with the same argument values.
'_pure' {
g.write('__attribute__((const)) ')
}
// windows attributes (msvc/mingw)
// prefixed by windows to indicate they're for advanced users only and not really supported by V.
'windows_stdcall' {
msvc_attrs += '__stdcall '
}
else {
// nothing but keep V happy
}
}
return msvc_attrs
}