mirror of
https://github.com/rui314/chibicc
synced 2024-11-22 06:11:18 +03:00
[GNU] Support labels-as-values
This commit is contained in:
parent
3d5550e29a
commit
4f165ec60b
@ -209,7 +209,9 @@ typedef enum {
|
||||
ND_CASE, // "case"
|
||||
ND_BLOCK, // { ... }
|
||||
ND_GOTO, // "goto"
|
||||
ND_GOTO_EXPR, // "goto" labels-as-values
|
||||
ND_LABEL, // Labeled statement
|
||||
ND_LABEL_VAL, // [GNU] Labels-as-values
|
||||
ND_FUNCALL, // Function call
|
||||
ND_EXPR_STMT, // Expression statement
|
||||
ND_STMT_EXPR, // Statement expression
|
||||
@ -254,7 +256,7 @@ struct Node {
|
||||
bool pass_by_stack;
|
||||
Obj *ret_buffer;
|
||||
|
||||
// Goto or labeled statement
|
||||
// Goto or labeled statement, or labels-as-values
|
||||
char *label;
|
||||
char *unique_label;
|
||||
Node *goto_next;
|
||||
|
@ -925,6 +925,9 @@ static void gen_expr(Node *node) {
|
||||
|
||||
return;
|
||||
}
|
||||
case ND_LABEL_VAL:
|
||||
println(" lea %s(%%rip), %%rax", node->unique_label);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (node->lhs->ty->kind) {
|
||||
@ -1194,6 +1197,10 @@ static void gen_stmt(Node *node) {
|
||||
case ND_GOTO:
|
||||
println(" jmp %s", node->unique_label);
|
||||
return;
|
||||
case ND_GOTO_EXPR:
|
||||
gen_expr(node->lhs);
|
||||
println(" jmp *%%rax");
|
||||
return;
|
||||
case ND_LABEL:
|
||||
println("%s:", node->unique_label);
|
||||
gen_stmt(node->lhs);
|
||||
|
23
parse.c
23
parse.c
@ -1533,7 +1533,7 @@ static Node *asm_stmt(Token **rest, Token *tok) {
|
||||
// | "while" "(" expr ")" stmt
|
||||
// | "do" stmt "while" "(" expr ")" ";"
|
||||
// | "asm" asm-stmt
|
||||
// | "goto" ident ";"
|
||||
// | "goto" (ident | "*" expr) ";"
|
||||
// | "break" ";"
|
||||
// | "continue" ";"
|
||||
// | ident ":" stmt
|
||||
@ -1704,6 +1704,14 @@ static Node *stmt(Token **rest, Token *tok) {
|
||||
return asm_stmt(rest, tok);
|
||||
|
||||
if (equal(tok, "goto")) {
|
||||
if (equal(tok->next, "*")) {
|
||||
// [GNU] `goto *ptr` jumps to the address specified by `ptr`.
|
||||
Node *node = new_node(ND_GOTO_EXPR, tok);
|
||||
node->lhs = expr(&tok, tok->next->next);
|
||||
*rest = skip(tok, ";");
|
||||
return node;
|
||||
}
|
||||
|
||||
Node *node = new_node(ND_GOTO, tok);
|
||||
node->label = get_ident(tok->next);
|
||||
node->goto_next = gotos;
|
||||
@ -2406,6 +2414,7 @@ static Node *cast(Token **rest, Token *tok) {
|
||||
|
||||
// unary = ("+" | "-" | "*" | "&" | "!" | "~") cast
|
||||
// | ("++" | "--") unary
|
||||
// | "&&" ident
|
||||
// | postfix
|
||||
static Node *unary(Token **rest, Token *tok) {
|
||||
if (equal(tok, "+"))
|
||||
@ -2448,6 +2457,16 @@ static Node *unary(Token **rest, Token *tok) {
|
||||
if (equal(tok, "--"))
|
||||
return to_assign(new_sub(unary(rest, tok->next), new_num(1, tok), tok));
|
||||
|
||||
// [GNU] labels-as-values
|
||||
if (equal(tok, "&&")) {
|
||||
Node *node = new_node(ND_LABEL_VAL, tok);
|
||||
node->label = get_ident(tok->next);
|
||||
node->goto_next = gotos;
|
||||
gotos = node;
|
||||
*rest = tok->next->next;
|
||||
return node;
|
||||
}
|
||||
|
||||
return postfix(rest, tok);
|
||||
}
|
||||
|
||||
@ -3005,7 +3024,7 @@ static void create_param_lvars(Type *param) {
|
||||
}
|
||||
}
|
||||
|
||||
// This function matches gotos with labels.
|
||||
// This function matches gotos or labels-as-values with labels.
|
||||
//
|
||||
// We cannot resolve gotos as we parse a function because gotos
|
||||
// can refer a label that appears later in the function.
|
||||
|
@ -87,6 +87,10 @@ int main() {
|
||||
ASSERT(1, ({ int i=0; switch(7) { case 0 ... 7: i=1; break; case 8 ... 10: i=2; break; } i; }));
|
||||
ASSERT(1, ({ int i=0; switch(7) { case 0: i=1; break; case 7 ... 7: i=1; break; } i; }));
|
||||
|
||||
ASSERT(3, ({ void *p = &&v11; int i=0; goto *p; v11:i++; v12:i++; v13:i++; i; }));
|
||||
ASSERT(2, ({ void *p = &&v22; int i=0; goto *p; v21:i++; v22:i++; v23:i++; i; }));
|
||||
ASSERT(1, ({ void *p = &&v33; int i=0; goto *p; v31:i++; v32:i++; v33:i++; i; }));
|
||||
|
||||
printf("OK\n");
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user