Add basic "asm" statement

This commit is contained in:
Rui Ueyama 2020-08-27 23:50:52 +09:00
parent e28a612e9c
commit a2535163e2
5 changed files with 51 additions and 1 deletions

View File

@ -202,6 +202,7 @@ typedef enum {
ND_NUM, // Integer
ND_CAST, // Type cast
ND_MEMZERO, // Zero-clear a stack variable
ND_ASM, // "asm"
} NodeKind;
// AST node type
@ -246,6 +247,9 @@ struct Node {
Node *case_next;
Node *default_case;
// "asm" string literal
char *asm_str;
// Variable
Obj *var;

View File

@ -1046,6 +1046,9 @@ static void gen_stmt(Node *node) {
case ND_EXPR_STMT:
gen_expr(node->lhs);
return;
case ND_ASM:
println(" %s", node->asm_str);
return;
}
error_tok(node->tok, "invalid statement");

20
parse.c
View File

@ -1410,6 +1410,22 @@ static bool is_typename(Token *tok) {
return find_typedef(tok);
}
// asm-stmt = "asm" ("volatile" | "inline")* "(" string-literal ")"
static Node *asm_stmt(Token **rest, Token *tok) {
Node *node = new_node(ND_ASM, tok);
tok = tok->next;
while (equal(tok, "volatile") || equal(tok, "inline"))
tok = tok->next;
tok = skip(tok, "(");
if (tok->kind != TK_STR || tok->ty->base->kind != TY_CHAR)
error_tok(tok, "expected string literal");
node->asm_str = tok->str;
*rest = skip(tok->next, ")");
return node;
}
// stmt = "return" expr? ";"
// | "if" "(" expr ")" stmt ("else" stmt)?
// | "switch" "(" expr ")" stmt
@ -1418,6 +1434,7 @@ static bool is_typename(Token *tok) {
// | "for" "(" expr-stmt expr? ";" expr? ")" stmt
// | "while" "(" expr ")" stmt
// | "do" stmt "while" "(" expr ")" ";"
// | "asm" asm-stmt
// | "goto" ident ";"
// | "break" ";"
// | "continue" ";"
@ -1573,6 +1590,9 @@ static Node *stmt(Token **rest, Token *tok) {
return node;
}
if (equal(tok, "asm"))
return asm_stmt(rest, tok);
if (equal(tok, "goto")) {
Node *node = new_node(ND_GOTO, tok);
node->label = get_ident(tok->next);

23
test/asm.c Normal file
View File

@ -0,0 +1,23 @@
#include "test.h"
char *asm_fn1(void) {
asm("mov $50, %rax\n\t"
"mov %rbp, %rsp\n\t"
"pop %rbp\n\t"
"ret");
}
char *asm_fn2(void) {
asm inline volatile("mov $55, %rax\n\t"
"mov %rbp, %rsp\n\t"
"pop %rbp\n\t"
"ret");
}
int main() {
ASSERT(50, asm_fn1());
ASSERT(55, asm_fn2());
printf("OK\n");
return 0;
}

View File

@ -163,7 +163,7 @@ static bool is_keyword(Token *tok) {
"default", "extern", "_Alignof", "_Alignas", "do", "signed",
"unsigned", "const", "volatile", "auto", "register", "restrict",
"__restrict", "__restrict__", "_Noreturn", "float", "double",
"typeof",
"typeof", "asm",
};
for (int i = 0; i < sizeof(kw) / sizeof(*kw); i++)