cgen: support a `[_naked]` fn attribute (#10418)
parent
7878bad95e
commit
6576d876fc
|
@ -7260,7 +7260,7 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||||
&& (node.is_method || node.name !in ['panic', 'exit']) {
|
&& (node.is_method || node.name !in ['panic', 'exit']) {
|
||||||
if c.inside_anon_fn {
|
if c.inside_anon_fn {
|
||||||
c.error('missing return at the end of an anonymous function', node.pos)
|
c.error('missing return at the end of an anonymous function', node.pos)
|
||||||
} else {
|
} else if !node.attrs.contains('_naked') {
|
||||||
c.error('missing return at end of function `$node.name`', node.pos)
|
c.error('missing return at end of function `$node.name`', node.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -332,7 +332,8 @@ fn (mut g Gen) gen_fn_decl(node &ast.FnDecl, skip bool) {
|
||||||
} else {
|
} else {
|
||||||
g.defer_stmts = []
|
g.defer_stmts = []
|
||||||
}
|
}
|
||||||
if node.return_type != ast.void_type && node.stmts.len > 0 && node.stmts.last() !is ast.Return {
|
if node.return_type != ast.void_type && node.stmts.len > 0 && node.stmts.last() !is ast.Return
|
||||||
|
&& !node.attrs.contains('_naked') {
|
||||||
default_expr := g.type_default(node.return_type)
|
default_expr := g.type_default(node.return_type)
|
||||||
// TODO: perf?
|
// TODO: perf?
|
||||||
if default_expr == '{0}' {
|
if default_expr == '{0}' {
|
||||||
|
@ -1354,6 +1355,9 @@ fn (mut g Gen) write_fn_attrs(attrs []ast.Attr) string {
|
||||||
// repeated invocations of the function with the same argument values.
|
// repeated invocations of the function with the same argument values.
|
||||||
g.write('__attribute__((const)) ')
|
g.write('__attribute__((const)) ')
|
||||||
}
|
}
|
||||||
|
'_naked' {
|
||||||
|
g.write('__attribute__((naked)) ')
|
||||||
|
}
|
||||||
'windows_stdcall' {
|
'windows_stdcall' {
|
||||||
// windows attributes (msvc/mingw)
|
// windows attributes (msvc/mingw)
|
||||||
// prefixed by windows to indicate they're for advanced users only and not really supported by V.
|
// prefixed by windows to indicate they're for advanced users only and not really supported by V.
|
||||||
|
|
|
@ -342,7 +342,8 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
||||||
short_fn_name := name
|
short_fn_name := name
|
||||||
is_main := short_fn_name == 'main' && p.mod == 'main'
|
is_main := short_fn_name == 'main' && p.mod == 'main'
|
||||||
mut is_test := (short_fn_name.starts_with('test_') || short_fn_name.starts_with('testsuite_'))
|
mut is_test := (short_fn_name.starts_with('test_') || short_fn_name.starts_with('testsuite_'))
|
||||||
&& (p.file_base.ends_with('_test.v') || p.file_base.ends_with('_test.vv'))
|
&& (p.file_base.ends_with('_test.v')
|
||||||
|
|| p.file_base.all_before_last('.v').all_before_last('.').ends_with('_test'))
|
||||||
|
|
||||||
// Register
|
// Register
|
||||||
if is_method {
|
if is_method {
|
||||||
|
|
|
@ -900,7 +900,7 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
|
||||||
p.check(.name)
|
p.check(.name)
|
||||||
}
|
}
|
||||||
// dots are part of instructions for some riscv extensions
|
// dots are part of instructions for some riscv extensions
|
||||||
if arch in [.rv32, .rv64] {
|
if arch in [.rv32, .rv64, .amd64] {
|
||||||
for p.tok.kind == .dot {
|
for p.tok.kind == .dot {
|
||||||
name += '.'
|
name += '.'
|
||||||
p.next()
|
p.next()
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
[_naked]
|
||||||
|
fn naked_fn() {
|
||||||
|
asm amd64 {
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
mov rsp, rbp
|
||||||
|
pop rbp
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_naked_attr() {
|
||||||
|
naked_fn()
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
[_naked]
|
||||||
|
fn naked_fn() {
|
||||||
|
asm i386 {
|
||||||
|
push ebp
|
||||||
|
mov ebp, esp
|
||||||
|
mov esp, ebp
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_naked_attr() {
|
||||||
|
naked_fn()
|
||||||
|
}
|
Loading…
Reference in New Issue