mirror of
https://github.com/rui314/chibicc
synced 2024-11-28 17:03:13 +03:00
[GNU] Treat labels-as-values as compile-time constant
This commit is contained in:
parent
4f165ec60b
commit
f0c98e0d59
@ -169,7 +169,7 @@ typedef struct Relocation Relocation;
|
|||||||
struct Relocation {
|
struct Relocation {
|
||||||
Relocation *next;
|
Relocation *next;
|
||||||
int offset;
|
int offset;
|
||||||
char *label;
|
char **label;
|
||||||
long addend;
|
long addend;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1338,7 +1338,7 @@ static void emit_data(Obj *prog) {
|
|||||||
int pos = 0;
|
int pos = 0;
|
||||||
while (pos < var->ty->size) {
|
while (pos < var->ty->size) {
|
||||||
if (rel && rel->offset == pos) {
|
if (rel && rel->offset == pos) {
|
||||||
println(" .quad %s%+ld", rel->label, rel->addend);
|
println(" .quad %s%+ld", *rel->label, rel->addend);
|
||||||
rel = rel->next;
|
rel = rel->next;
|
||||||
pos += 8;
|
pos += 8;
|
||||||
} else {
|
} else {
|
||||||
|
17
parse.c
17
parse.c
@ -136,8 +136,8 @@ static Node *stmt(Token **rest, Token *tok);
|
|||||||
static Node *expr_stmt(Token **rest, Token *tok);
|
static Node *expr_stmt(Token **rest, Token *tok);
|
||||||
static Node *expr(Token **rest, Token *tok);
|
static Node *expr(Token **rest, Token *tok);
|
||||||
static int64_t eval(Node *node);
|
static int64_t eval(Node *node);
|
||||||
static int64_t eval2(Node *node, char **label);
|
static int64_t eval2(Node *node, char ***label);
|
||||||
static int64_t eval_rval(Node *node, char **label);
|
static int64_t eval_rval(Node *node, char ***label);
|
||||||
static bool is_const_expr(Node *node);
|
static bool is_const_expr(Node *node);
|
||||||
static Node *assign(Token **rest, Token *tok);
|
static Node *assign(Token **rest, Token *tok);
|
||||||
static Node *logor(Token **rest, Token *tok);
|
static Node *logor(Token **rest, Token *tok);
|
||||||
@ -1462,7 +1462,7 @@ write_gvar_data(Relocation *cur, Initializer *init, Type *ty, char *buf, int off
|
|||||||
return cur;
|
return cur;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *label = NULL;
|
char **label = NULL;
|
||||||
uint64_t val = eval2(init->expr, &label);
|
uint64_t val = eval2(init->expr, &label);
|
||||||
|
|
||||||
if (!label) {
|
if (!label) {
|
||||||
@ -1830,7 +1830,7 @@ static int64_t eval(Node *node) {
|
|||||||
// is a pointer to a global variable and n is a postiive/negative
|
// is a pointer to a global variable and n is a postiive/negative
|
||||||
// number. The latter form is accepted only as an initialization
|
// number. The latter form is accepted only as an initialization
|
||||||
// expression for a global variable.
|
// expression for a global variable.
|
||||||
static int64_t eval2(Node *node, char **label) {
|
static int64_t eval2(Node *node, char ***label) {
|
||||||
add_type(node);
|
add_type(node);
|
||||||
|
|
||||||
if (is_flonum(node->ty))
|
if (is_flonum(node->ty))
|
||||||
@ -1902,6 +1902,9 @@ static int64_t eval2(Node *node, char **label) {
|
|||||||
}
|
}
|
||||||
case ND_ADDR:
|
case ND_ADDR:
|
||||||
return eval_rval(node->lhs, label);
|
return eval_rval(node->lhs, label);
|
||||||
|
case ND_LABEL_VAL:
|
||||||
|
*label = &node->unique_label;
|
||||||
|
return 0;
|
||||||
case ND_MEMBER:
|
case ND_MEMBER:
|
||||||
if (!label)
|
if (!label)
|
||||||
error_tok(node->tok, "not a compile-time constant");
|
error_tok(node->tok, "not a compile-time constant");
|
||||||
@ -1913,7 +1916,7 @@ static int64_t eval2(Node *node, char **label) {
|
|||||||
error_tok(node->tok, "not a compile-time constant");
|
error_tok(node->tok, "not a compile-time constant");
|
||||||
if (node->var->ty->kind != TY_ARRAY && node->var->ty->kind != TY_FUNC)
|
if (node->var->ty->kind != TY_ARRAY && node->var->ty->kind != TY_FUNC)
|
||||||
error_tok(node->tok, "invalid initializer");
|
error_tok(node->tok, "invalid initializer");
|
||||||
*label = node->var->name;
|
*label = &node->var->name;
|
||||||
return 0;
|
return 0;
|
||||||
case ND_NUM:
|
case ND_NUM:
|
||||||
return node->val;
|
return node->val;
|
||||||
@ -1922,12 +1925,12 @@ static int64_t eval2(Node *node, char **label) {
|
|||||||
error_tok(node->tok, "not a compile-time constant");
|
error_tok(node->tok, "not a compile-time constant");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t eval_rval(Node *node, char **label) {
|
static int64_t eval_rval(Node *node, char ***label) {
|
||||||
switch (node->kind) {
|
switch (node->kind) {
|
||||||
case ND_VAR:
|
case ND_VAR:
|
||||||
if (node->var->is_local)
|
if (node->var->is_local)
|
||||||
error_tok(node->tok, "not a compile-time constant");
|
error_tok(node->tok, "not a compile-time constant");
|
||||||
*label = node->var->name;
|
*label = &node->var->name;
|
||||||
return 0;
|
return 0;
|
||||||
case ND_DEREF:
|
case ND_DEREF:
|
||||||
return eval2(node->lhs, label);
|
return eval2(node->lhs, label);
|
||||||
|
@ -91,6 +91,10 @@ int main() {
|
|||||||
ASSERT(2, ({ void *p = &&v22; int i=0; goto *p; v21:i++; v22:i++; v23: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; }));
|
ASSERT(1, ({ void *p = &&v33; int i=0; goto *p; v31:i++; v32:i++; v33:i++; i; }));
|
||||||
|
|
||||||
|
ASSERT(3, ({ static void *p[]={&&v41,&&v42,&&v43}; int i=0; goto *p[0]; v41:i++; v42:i++; v43:i++; i; }));
|
||||||
|
ASSERT(2, ({ static void *p[]={&&v52,&&v52,&&v53}; int i=0; goto *p[1]; v51:i++; v52:i++; v53:i++; i; }));
|
||||||
|
ASSERT(1, ({ static void *p[]={&&v62,&&v62,&&v63}; int i=0; goto *p[2]; v61:i++; v62:i++; v63:i++; i; }));
|
||||||
|
|
||||||
printf("OK\n");
|
printf("OK\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user