mirror of https://github.com/rui314/chibicc
[GNU] Support case ranges
This commit is contained in:
parent
e0bf168041
commit
d90c73b605
|
@ -259,10 +259,14 @@ struct Node {
|
||||||
char *unique_label;
|
char *unique_label;
|
||||||
Node *goto_next;
|
Node *goto_next;
|
||||||
|
|
||||||
// Switch-cases
|
// Switch
|
||||||
Node *case_next;
|
Node *case_next;
|
||||||
Node *default_case;
|
Node *default_case;
|
||||||
|
|
||||||
|
// Case
|
||||||
|
long begin;
|
||||||
|
long end;
|
||||||
|
|
||||||
// "asm" string literal
|
// "asm" string literal
|
||||||
char *asm_str;
|
char *asm_str;
|
||||||
|
|
||||||
|
|
17
codegen.c
17
codegen.c
|
@ -1160,9 +1160,20 @@ static void gen_stmt(Node *node) {
|
||||||
gen_expr(node->cond);
|
gen_expr(node->cond);
|
||||||
|
|
||||||
for (Node *n = node->case_next; n; n = n->case_next) {
|
for (Node *n = node->case_next; n; n = n->case_next) {
|
||||||
char *reg = (node->cond->ty->size == 8) ? "%rax" : "%eax";
|
char *ax = (node->cond->ty->size == 8) ? "%rax" : "%eax";
|
||||||
println(" cmp $%ld, %s", n->val, reg);
|
char *di = (node->cond->ty->size == 8) ? "%rdi" : "%edi";
|
||||||
println(" je %s", n->label);
|
|
||||||
|
if (n->begin == n->end) {
|
||||||
|
println(" cmp $%ld, %s", n->begin, ax);
|
||||||
|
println(" je %s", n->label);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// [GNU] Case ranges
|
||||||
|
println(" mov %s, %s", ax, di);
|
||||||
|
println(" sub $%ld, %s", n->begin, di);
|
||||||
|
println(" cmp $%ld, %s", n->end - n->begin, di);
|
||||||
|
println(" jbe %s", n->label);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->default_case)
|
if (node->default_case)
|
||||||
|
|
18
parse.c
18
parse.c
|
@ -1507,7 +1507,7 @@ static Node *asm_stmt(Token **rest, Token *tok) {
|
||||||
// stmt = "return" expr? ";"
|
// stmt = "return" expr? ";"
|
||||||
// | "if" "(" expr ")" stmt ("else" stmt)?
|
// | "if" "(" expr ")" stmt ("else" stmt)?
|
||||||
// | "switch" "(" expr ")" stmt
|
// | "switch" "(" expr ")" stmt
|
||||||
// | "case" const-expr ":" stmt
|
// | "case" const-expr ("..." const-expr)? ":" stmt
|
||||||
// | "default" ":" stmt
|
// | "default" ":" stmt
|
||||||
// | "for" "(" expr-stmt expr? ";" expr? ")" stmt
|
// | "for" "(" expr-stmt expr? ";" expr? ")" stmt
|
||||||
// | "while" "(" expr ")" stmt
|
// | "while" "(" expr ")" stmt
|
||||||
|
@ -1573,11 +1573,23 @@ static Node *stmt(Token **rest, Token *tok) {
|
||||||
error_tok(tok, "stray case");
|
error_tok(tok, "stray case");
|
||||||
|
|
||||||
Node *node = new_node(ND_CASE, tok);
|
Node *node = new_node(ND_CASE, tok);
|
||||||
int val = const_expr(&tok, tok->next);
|
int begin = const_expr(&tok, tok->next);
|
||||||
|
int end;
|
||||||
|
|
||||||
|
if (equal(tok, "...")) {
|
||||||
|
// [GNU] Case ranges, e.g. "case 1 ... 5:"
|
||||||
|
end = const_expr(&tok, tok->next);
|
||||||
|
if (end < begin)
|
||||||
|
error_tok(tok, "empty case range specified");
|
||||||
|
} else {
|
||||||
|
end = begin;
|
||||||
|
}
|
||||||
|
|
||||||
tok = skip(tok, ":");
|
tok = skip(tok, ":");
|
||||||
node->label = new_unique_name();
|
node->label = new_unique_name();
|
||||||
node->lhs = stmt(rest, tok);
|
node->lhs = stmt(rest, tok);
|
||||||
node->val = val;
|
node->begin = begin;
|
||||||
|
node->end = end;
|
||||||
node->case_next = current_switch->case_next;
|
node->case_next = current_switch->case_next;
|
||||||
current_switch->case_next = node;
|
current_switch->case_next = node;
|
||||||
return node;
|
return node;
|
||||||
|
|
|
@ -83,6 +83,10 @@ int main() {
|
||||||
ASSERT(10, ({ double i=10.0; int j=0; for (; i; i--, j++); j; }));
|
ASSERT(10, ({ double i=10.0; int j=0; for (; i; i--, j++); j; }));
|
||||||
ASSERT(10, ({ double i=10.0; int j=0; do j++; while(--i); j; }));
|
ASSERT(10, ({ double i=10.0; int j=0; do j++; while(--i); j; }));
|
||||||
|
|
||||||
|
ASSERT(2, ({ int i=0; switch(7) { case 0 ... 5: i=1; break; case 6 ... 20: i=2; break; } i; }));
|
||||||
|
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; }));
|
||||||
|
|
||||||
printf("OK\n");
|
printf("OK\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue