From 2964bf9e23f772aa837175e50a624cf416cc0433 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sun, 17 Nov 2019 00:58:09 +0300 Subject: [PATCH] inline assembly --- vlib/compiler/asm.v | 38 ++++++++++++++++++++++++++++++++++ vlib/compiler/parser.v | 5 ++++- vlib/compiler/tests/asm_test.v | 14 +++++++++++++ vlib/compiler/token.v | 2 ++ 4 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 vlib/compiler/asm.v create mode 100644 vlib/compiler/tests/asm_test.v diff --git a/vlib/compiler/asm.v b/vlib/compiler/asm.v new file mode 100644 index 0000000000..dce43e817f --- /dev/null +++ b/vlib/compiler/asm.v @@ -0,0 +1,38 @@ +// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. +// Use of this source code is governed by an MIT license +// that can be found in the LICENSE file. + +module compiler + +fn (p mut Parser) inline_asm() { + if !p.inside_unsafe { + p.error('asm() needs to be run unside `unsafe {}`') + } + p.next() + p.check(.lpar) + s := p.check_string() + p.genln('asm("$s"') + for p.tok == .str { + p.genln('"$p.lit"') + p.next() + } + for p.tok == .colon { + p.next() + arg := p.check_string() + p.gen(': "$arg"') + if p.tok == .lpar { + p.next() + var_name := p.check_name() + if !p.known_var(var_name) { + p.error('unknown variable `$var_name`') + } + p.check(.rpar) + p.genln('($var_name)') + + } + + } + p.genln(');') + p.check(.rpar) + +} diff --git a/vlib/compiler/parser.v b/vlib/compiler/parser.v index 87ba9f11d8..bd8563f8c3 100644 --- a/vlib/compiler/parser.v +++ b/vlib/compiler/parser.v @@ -1208,6 +1208,9 @@ fn (p mut Parser) statement(add_semi bool) string { .key_assert { p.assert_statement() } + .key_asm { + p.inline_asm() + } else { // An expression as a statement typ := p.expression() @@ -2745,7 +2748,7 @@ fn (p mut Parser) return_st() { p.returns = true } -fn (p Parser) get_deferred_text() string { +fn (p &Parser) get_deferred_text() string { // @emily33901: Scoped defer // Check all of our defer texts to see if there is one at a higher scope level // The one for our current scope would be the last so any before that need to be diff --git a/vlib/compiler/tests/asm_test.v b/vlib/compiler/tests/asm_test.v new file mode 100644 index 0000000000..3597aa0a0e --- /dev/null +++ b/vlib/compiler/tests/asm_test.v @@ -0,0 +1,14 @@ +fn test_inline_asm() { + a := 10 + b := 0 + unsafe { + asm ("movl %1, %%eax;" + "movl %%eax, %0;" + :"=r"(b) + :"r"(a) + :"%eax" + ) + } + assert a == 10 + assert b == 10 +} diff --git a/vlib/compiler/token.v b/vlib/compiler/token.v index 77793bbce1..f285362837 100644 --- a/vlib/compiler/token.v +++ b/vlib/compiler/token.v @@ -80,6 +80,7 @@ enum TokenKind { // keywords keyword_beg key_as + key_asm key_assert key_atomic key_break @@ -201,6 +202,7 @@ fn build_token_str() []string { s[TokenKind.key_if] = 'if' //s[TokenKind.key_it] = 'it' s[TokenKind.key_else] = 'else' + s[TokenKind.key_asm] = 'asm' s[TokenKind.key_return] = 'return' s[TokenKind.key_module] = 'module' s[TokenKind.key_sizeof] = 'sizeof'