}
}
-static void print_string_literal(
- const string_literal_expression_t *string_literal)
+static void print_quoted_string(const char *string)
{
fputc('"', out);
- for(const char *c = string_literal->value; *c != '\0'; ++c) {
+ for(const char *c = string; *c != '\0'; ++c) {
switch(*c) {
case '\"': fputs("\\\"", out); break;
case '\\': fputs("\\\\", out); break;
fputc('"', out);
}
+static void print_string_literal(
+ const string_literal_expression_t *string_literal)
+{
+ print_quoted_string(string_literal->value);
+}
+
static void print_call_expression(const call_expression_t *call)
{
print_expression(call->function);
print_statement(statement->body);
}
+static void print_asm_constraints(asm_constraint_t *constraints)
+{
+ asm_constraint_t *constraint = constraints;
+ for( ; constraint != NULL; constraint = constraint->next) {
+ if(constraint != constraints)
+ fputs(", ", out);
+
+ if(constraint->symbol) {
+ fprintf(out, "[%s] ", constraint->symbol->string);
+ }
+ print_quoted_string(constraint->constraints);
+ fputs(" (", out);
+ print_expression(constraint->expression);
+ fputs(")", out);
+ }
+}
+
+static void print_asm_clobbers(asm_clobber_t *clobbers)
+{
+ asm_clobber_t *clobber = clobbers;
+ for( ; clobber != NULL; clobber = clobber->next) {
+ if(clobber != clobbers)
+ fputs(", ", out);
+
+ print_quoted_string(clobber->clobber);
+ }
+}
+
+static void print_asm_statement(const asm_statement_t *statement)
+{
+ fputs("asm", out);
+ if(statement->is_volatile) {
+ fputs(" volatile", out);
+ }
+ fputs("(", out);
+ print_quoted_string(statement->asm_text);
+ if(statement->inputs == NULL && statement->outputs == NULL
+ && statement->clobbers == NULL)
+ goto end_of_print_asm_statement;
+
+ fputs(" : ", out);
+ print_asm_constraints(statement->inputs);
+ if(statement->outputs == NULL && statement->clobbers == NULL)
+ goto end_of_print_asm_statement;
+
+ fputs(": ", out);
+ print_asm_constraints(statement->outputs);
+ if(statement->clobbers == NULL)
+ goto end_of_print_asm_statement;
+
+ fputs(": ", out);
+ print_asm_clobbers(statement->clobbers);
+
+end_of_print_asm_statement:
+ fputs(");\n", out);
+}
+
void print_statement(const statement_t *statement)
{
switch(statement->type) {
case STATEMENT_COMPOUND:
- print_compound_statement((const compound_statement_t*) statement);
+ print_compound_statement(&statement->compound);
break;
case STATEMENT_RETURN:
- print_return_statement((const return_statement_t*) statement);
+ print_return_statement(&statement->returns);
break;
case STATEMENT_EXPRESSION:
- print_expression_statement((const expression_statement_t*) statement);
+ print_expression_statement(&statement->expression);
break;
case STATEMENT_LABEL:
- print_label_statement((const label_statement_t*) statement);
+ print_label_statement(&statement->label);
break;
case STATEMENT_GOTO:
- print_goto_statement((const goto_statement_t*) statement);
+ print_goto_statement(&statement->gotos);
break;
case STATEMENT_CONTINUE:
fputs("continue;\n", out);
fputs("break;\n", out);
break;
case STATEMENT_IF:
- print_if_statement((const if_statement_t*) statement);
+ print_if_statement(&statement->ifs);
break;
case STATEMENT_SWITCH:
- print_switch_statement((const switch_statement_t*) statement);
+ print_switch_statement(&statement->switchs);
break;
case STATEMENT_CASE_LABEL:
- print_case_label((const case_label_statement_t*) statement);
+ print_case_label(&statement->case_label);
break;
case STATEMENT_DECLARATION:
- print_declaration_statement((const declaration_statement_t*) statement);
+ print_declaration_statement(&statement->declaration);
break;
case STATEMENT_WHILE:
- print_while_statement((const while_statement_t*) statement);
+ print_while_statement(&statement->whiles);
break;
case STATEMENT_DO_WHILE:
- print_do_while_statement((const do_while_statement_t*) statement);
+ print_do_while_statement(&statement->do_while);
break;
case STATEMENT_FOR:
- print_for_statement((const for_statement_t*) statement);
+ print_for_statement(&statement->fors);
+ break;
+ case STATEMENT_ASM:
+ print_asm_statement(&statement->asms);
break;
case STATEMENT_INVALID:
fprintf(out, "*invalid statement*");
static void print_normal_declaration(const declaration_t *declaration)
{
print_storage_class(declaration->storage_class);
- print_type_ext(declaration->type, declaration->symbol,
- &declaration->context);
if(declaration->is_inline) {
fputs("inline ", out);
}
+ print_type_ext(declaration->type, declaration->symbol,
+ &declaration->context);
if(declaration->type->type == TYPE_FUNCTION) {
if(declaration->init.statement != NULL) {
typedef struct while_statement_t while_statement_t;
typedef struct do_while_statement_t do_while_statement_t;
typedef struct for_statement_t for_statement_t;
+typedef struct asm_constraint_t asm_constraint_t;
+typedef struct asm_clobber_t asm_clobber_t;
+typedef struct asm_statement_t asm_statement_t;
typedef union statement_t statement_t;
typedef struct translation_unit_t translation_unit_t;
static void statement_to_firm(statement_t *statement)
{
switch(statement->type) {
+ case STATEMENT_INVALID:
+ panic("invalid statement found");
case STATEMENT_COMPOUND:
compound_statement_to_firm((compound_statement_t*) statement);
return;
case STATEMENT_GOTO:
goto_to_firm((goto_statement_t*) statement);
return;
- default:
+ case STATEMENT_ASM:
break;
}
panic("Statement not implemented\n");
break;
}
+ case STATEMENT_ASM:
case STATEMENT_BREAK:
case STATEMENT_CASE_LABEL:
case STATEMENT_CONTINUE:
STATEMENT_CASE_LABEL,
STATEMENT_WHILE,
STATEMENT_DO_WHILE,
- STATEMENT_FOR
+ STATEMENT_FOR,
+ STATEMENT_ASM
} statement_type_t;
struct statement_base_t {
context_t context;
};
+struct asm_constraint_t {
+ const char *constraints;
+ expression_t *expression;
+ symbol_t *symbol;
+ asm_constraint_t *next;
+};
+
+struct asm_clobber_t {
+ const char *clobber;
+ asm_clobber_t *next;
+};
+
+struct asm_statement_t {
+ statement_base_t statement;
+ const char *asm_text;
+ asm_constraint_t *inputs;
+ asm_constraint_t *outputs;
+ asm_clobber_t *clobbers;
+ bool is_volatile;
+};
+
union statement_t {
statement_type_t type;
statement_base_t base;
while_statement_t whiles;
do_while_statement_t do_while;
for_statement_t fors;
+ asm_statement_t asms;
};
struct translation_unit_t {
return res;
}
+static size_t get_statement_struct_size(statement_type_t type)
+{
+ static const size_t sizes[] = {
+ [STATEMENT_COMPOUND] = sizeof(compound_statement_t),
+ [STATEMENT_RETURN] = sizeof(return_statement_t),
+ [STATEMENT_DECLARATION] = sizeof(declaration_statement_t),
+ [STATEMENT_IF] = sizeof(if_statement_t),
+ [STATEMENT_SWITCH] = sizeof(switch_statement_t),
+ [STATEMENT_EXPRESSION] = sizeof(expression_statement_t),
+ [STATEMENT_CONTINUE] = sizeof(statement_base_t),
+ [STATEMENT_BREAK] = sizeof(statement_base_t),
+ [STATEMENT_GOTO] = sizeof(goto_statement_t),
+ [STATEMENT_LABEL] = sizeof(label_statement_t),
+ [STATEMENT_CASE_LABEL] = sizeof(case_label_statement_t),
+ [STATEMENT_WHILE] = sizeof(while_statement_t),
+ [STATEMENT_DO_WHILE] = sizeof(do_while_statement_t),
+ [STATEMENT_FOR] = sizeof(for_statement_t),
+ [STATEMENT_ASM] = sizeof(asm_statement_t)
+ };
+ assert(sizeof(sizes) / sizeof(sizes[0]) == STATEMENT_ASM + 1);
+ assert(type <= STATEMENT_ASM);
+ assert(sizes[type] != 0);
+ return sizes[type];
+}
+
+static statement_t *allocate_statement_zero(statement_type_t type)
+{
+ size_t size = get_statement_struct_size(type);
+ statement_t *res = allocate_ast_zero(size);
+
+ res->base.type = type;
+ return res;
+}
+
+
static size_t get_expression_struct_size(expression_type_t type)
{
static const size_t sizes[] = {
T___builtin_classify_type, 25);
}
+static asm_constraint_t *parse_asm_constraints(void)
+{
+ asm_constraint_t *result = NULL;
+ asm_constraint_t *last = NULL;
+
+ while(token.type == T_STRING_LITERAL || token.type == '[') {
+ asm_constraint_t *constraint = allocate_ast_zero(sizeof(constraint[0]));
+ memset(constraint, 0, sizeof(constraint[0]));
+
+ if(token.type == '[') {
+ eat('[');
+ if(token.type != T_IDENTIFIER) {
+ parse_error_expected("while parsing asm constraint",
+ T_IDENTIFIER, 0);
+ return NULL;
+ }
+ constraint->symbol = token.v.symbol;
+
+ expect(']');
+ }
+
+ constraint->constraints = parse_string_literals();
+ expect('(');
+ constraint->expression = parse_expression();
+ expect(')');
+
+ if(last != NULL) {
+ last->next = constraint;
+ } else {
+ result = constraint;
+ }
+ last = constraint;
+
+ if(token.type != ',')
+ break;
+ eat(',');
+ }
+
+ return result;
+}
+
+static asm_clobber_t *parse_asm_clobbers(void)
+{
+ asm_clobber_t *result = NULL;
+ asm_clobber_t *last = NULL;
+
+ while(token.type == T_STRING_LITERAL) {
+ asm_clobber_t *clobber = allocate_ast_zero(sizeof(clobber[0]));
+ clobber->clobber = parse_string_literals();
+
+ if(last != NULL) {
+ last->next = clobber;
+ } else {
+ result = clobber;
+ }
+ last = clobber;
+
+ if(token.type != ',')
+ break;
+ eat(',');
+ }
+
+ return result;
+}
+
+static statement_t *parse_asm_statement(void)
+{
+ eat(T_asm);
+
+ statement_t *statement = allocate_statement_zero(STATEMENT_ASM);
+ statement->base.source_position = token.source_position;
+
+ asm_statement_t *asm_statement = &statement->asms;
+
+ if(token.type == T_volatile) {
+ next_token();
+ asm_statement->is_volatile = true;
+ }
+
+ expect('(');
+ asm_statement->asm_text = parse_string_literals();
+
+ if(token.type != ':')
+ goto end_of_asm;
+ eat(':');
+
+ asm_statement->inputs = parse_asm_constraints();
+ if(token.type != ':')
+ goto end_of_asm;
+ eat(':');
+
+ asm_statement->outputs = parse_asm_constraints();
+ if(token.type != ':')
+ goto end_of_asm;
+ eat(':');
+
+ asm_statement->clobbers = parse_asm_clobbers();
+
+end_of_asm:
+ expect(')');
+ expect(';');
+ return statement;
+}
static statement_t *parse_case_statement(void)
{
/* declaration or statement */
switch(token.type) {
+ case T_asm:
+ statement = parse_asm_statement();
+ break;
+
case T_case:
statement = parse_case_statement();
break;
S(union)
S(unsigned)
S(void)
-S(volatile)
S(while)
S(_Bool)
S(_Complex)
T(_restrict, "restrict", = T_restrict)
T(asm, "asm",)
T(__asm__, "__asm__", = T_asm)
+T(volatile, "volatile",)
+T(__volatile__, "__volatile__", = T_volatile)
T(inline, "inline",)
T(__inline, "__inline", = T_inline)
T(__inline__, "__inline__", = T_inline)