cgen: support a `[_naked]` fn attribute (#10418)

pull/10424/head
crthpl 2021-06-11 01:03:39 -07:00 committed by GitHub
parent 7878bad95e
commit 6576d876fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 37 additions and 4 deletions

View File

@ -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)
} }
} }

View File

@ -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.

View File

@ -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 {

View File

@ -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()

View File

@ -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()
}

View File

@ -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()
}