fputs(")", out);
}
+static void print_va_start(const va_start_expression_t *const expression)
+{
+ fputs("__builtin_va_start(", out);
+ print_expression(expression->ap);
+ fputs(", ", out);
+ fputs(expression->parameter->symbol->string, out);
+ fputs(")", out);
+}
+
static void print_va_arg(const va_arg_expression_t *expression)
{
fputs("__builtin_va_arg(", out);
- print_expression(expression->arg);
+ print_expression(expression->ap);
fputs(", ", out);
print_type(expression->expression.datatype);
fputs(")", out);
case EXPR_CONDITIONAL:
print_conditional(&expression->conditional);
break;
+ case EXPR_VA_START:
+ print_va_start(&expression->va_starte);
case EXPR_VA_ARG:
print_va_arg(&expression->va_arge);
break;
typedef struct statement_expression_t statement_expression_t;
typedef struct designator_t designator_t;
typedef struct offsetof_expression_t offsetof_expression_t;
+typedef struct va_start_expression_t va_start_expression_t;
typedef struct va_arg_expression_t va_arg_expression_t;
typedef struct builtin_symbol_expression_t builtin_symbol_expression_t;
typedef struct classify_type_expression_t classify_type_expression_t;
case TYPE_ARRAY:
return get_array_type_size(&type->array);
case TYPE_BUILTIN:
+ return get_type_size(type->builtin.real_type);
case TYPE_TYPEDEF:
case TYPE_TYPEOF:
case TYPE_INVALID:
firm_type = create_enum_type(&type->enumt);
break;
case TYPE_BUILTIN:
+ firm_type = get_ir_type(type->builtin.real_type);
+ break;
case TYPE_TYPEOF:
case TYPE_TYPEDEF:
case TYPE_INVALID:
ir_node *res = new_d_Const(dbgi, mode, tv);
return res;
}
+ case T___builtin_va_end:
+ return NULL;
default:
panic("Unsupported builtin found\n");
}
return compound_statement_to_firm((compound_statement_t*) statement);
}
+static ir_node *va_start_expression_to_firm(
+ const va_start_expression_t *const expr)
+{
+ ir_type *const method_type = get_ir_type(current_function_decl->type);
+ int const n = get_method_n_params(method_type) - 1;
+ ir_entity *const parm_ent = get_method_value_param_ent(method_type, n);
+ ir_node *const arg_base = get_irg_value_param_base(current_ir_graph);
+ dbg_info *const dbgi =
+ get_dbg_info(&expr->expression.source_position);
+ ir_node *const no_mem = new_NoMem();
+ ir_node *const arg_sel =
+ new_d_simpleSel(dbgi, no_mem, arg_base, parm_ent);
+
+ size_t const parm_size = get_type_size(expr->parameter->type);
+ ir_node *const cnst = new_Const_long(mode_Iu, parm_size);
+ ir_node *const add = new_d_Add(dbgi, arg_sel, cnst, mode_P_data);
+ set_value_for_expression(expr->ap, add);
+
+ return NULL;
+}
+
+static ir_node *va_arg_expression_to_firm(const va_arg_expression_t *const expr)
+{
+ ir_type *const irtype = get_ir_type(expr->expression.datatype);
+ ir_node *const ap = expression_to_firm(expr->ap);
+ dbg_info *const dbgi = get_dbg_info(&expr->expression.source_position);
+ ir_node *const res = deref_address(irtype, ap, dbgi);
+
+ size_t const parm_size = get_type_size(expr->expression.datatype);
+ ir_node *const cnst = new_Const_long(mode_Iu, parm_size);
+ ir_node *const add = new_d_Add(dbgi, ap, cnst, mode_P_data);
+ set_value_for_expression(expr->ap, add);
+
+ return res;
+}
+
static ir_node *dereference_addr(const unary_expression_t *const expression)
{
assert(expression->type == UNEXPR_DEREFERENCE);
return function_name_to_firm(&expression->string);
case EXPR_STATEMENT:
return statement_expression_to_firm(&expression->statement);
- case EXPR_OFFSETOF:
+ case EXPR_VA_START:
+ return va_start_expression_to_firm(&expression->va_starte);
case EXPR_VA_ARG:
+ return va_arg_expression_to_firm(&expression->va_arge);
+ case EXPR_OFFSETOF:
case EXPR_BUILTIN_SYMBOL:
panic("unimplemented expression found");
EXPR_PRETTY_FUNCTION,
EXPR_BUILTIN_SYMBOL,
EXPR_OFFSETOF,
+ EXPR_VA_START,
EXPR_VA_ARG,
EXPR_STATEMENT
} expression_type_t;
designator_t *designator;
};
+struct va_start_expression_t {
+ expression_base_t expression;
+ expression_t *ap;
+ declaration_t *parameter;
+};
+
struct va_arg_expression_t {
expression_base_t expression;
- expression_t *arg;
- type_t *type;
+ expression_t *ap;
};
struct conditional_expression_t {
array_access_expression_t array_access;
sizeof_expression_t sizeofe;
offsetof_expression_t offsetofe;
+ va_start_expression_t va_starte;
va_arg_expression_t va_arge;
conditional_expression_t conditional;
statement_expression_t statement;
static type_t *type_string = NULL;
static type_t *type_void = NULL;
static type_t *type_void_ptr = NULL;
+static type_t *type_valist = NULL;
type_t *type_size_t = NULL;
type_t *type_ptrdiff_t = NULL;
#define IMAGINARY_SPECIFIERS
#endif
-#define TYPE_SPECIFIERS \
- case T_void: \
- case T_char: \
- case T_short: \
- case T_int: \
- case T_long: \
- case T_float: \
- case T_double: \
- case T_signed: \
- case T_unsigned: \
- case T__Bool: \
- case T_struct: \
- case T_union: \
- case T_enum: \
- case T___typeof__: \
- COMPLEX_SPECIFIERS \
+#define TYPE_SPECIFIERS \
+ case T_void: \
+ case T_char: \
+ case T_short: \
+ case T_int: \
+ case T_long: \
+ case T_float: \
+ case T_double: \
+ case T_signed: \
+ case T_unsigned: \
+ case T__Bool: \
+ case T_struct: \
+ case T_union: \
+ case T_enum: \
+ case T___typeof__: \
+ case T___builtin_va_list: \
+ COMPLEX_SPECIFIERS \
IMAGINARY_SPECIFIERS
#define DECLARATION_START \
[EXPR_PRETTY_FUNCTION] = sizeof(string_literal_expression_t),
[EXPR_BUILTIN_SYMBOL] = sizeof(builtin_symbol_expression_t),
[EXPR_OFFSETOF] = sizeof(offsetof_expression_t),
+ [EXPR_VA_START] = sizeof(va_start_expression_t),
[EXPR_VA_ARG] = sizeof(va_arg_expression_t),
[EXPR_STATEMENT] = sizeof(statement_expression_t)
};
eat(';');
}
-static void eat_brace(void)
+static void eat_paren(void)
{
if(token.type == '(')
next_token();
return;
}
if(token.type == '(') {
- eat_brace();
+ eat_paren();
continue;
}
if(token.type == '{') {
if(token.type != T_STRING_LITERAL) {
parse_error_expected("while parsing assembler attribute",
T_STRING_LITERAL);
- eat_brace();
+ eat_paren();
break;
} else {
parse_string_literals();
#endif
} specifiers_t;
-static type_t *create_builtin_type(symbol_t *symbol)
+static type_t *create_builtin_type(symbol_t *const symbol,
+ type_t *const real_type)
{
type_t *type = allocate_type_zero(TYPE_BUILTIN);
type->builtin.symbol = symbol;
- /* TODO... */
- type->builtin.real_type = type_int;
+ type->builtin.real_type = real_type;
- return type;
+ type_t *result = typehash_insert(type);
+ if (type != result) {
+ free_type(type);
+ }
+
+ return result;
}
static type_t *get_typedef_type(symbol_t *symbol)
type = parse_typeof();
break;
case T___builtin_va_list:
- type = create_builtin_type(token.v.symbol);
+ type = duplicate_type(type_valist);
next_token();
break;
expression_parser_function_t expression_parsers[T_LAST_TOKEN];
-static expression_t *make_invalid_expression(void)
+static expression_t *create_invalid_expression(void)
{
expression_t *expression = allocate_expression_zero(EXPR_INVALID);
expression->base.source_position = token.source_position;
next_token();
- return make_invalid_expression();
+ return create_invalid_expression();
}
static expression_t *parse_string_const(void)
return make_function_1_type(type_float, type_string);
case T___builtin_nand:
return make_function_1_type(type_long_double, type_string);
+ case T___builtin_va_end:
+ return make_function_1_type(type_void, type_valist);
default:
panic("not implemented builtin symbol found");
}
if(token.type != T_IDENTIFIER) {
parse_error_expected("while parsing member designator",
T_IDENTIFIER, 0);
- eat_brace();
+ eat_paren();
return NULL;
}
result->symbol = token.v.symbol;
if(token.type != T_IDENTIFIER) {
parse_error_expected("while parsing member designator",
T_IDENTIFIER, 0);
- eat_brace();
+ eat_paren();
return NULL;
}
designator_t *designator = allocate_ast_zero(sizeof(result[0]));
designator_t *designator = allocate_ast_zero(sizeof(result[0]));
designator->array_access = parse_expression();
if(designator->array_access == NULL) {
- eat_brace();
+ eat_paren();
return NULL;
}
expect(']');
return expression;
}
+static expression_t *parse_va_start(void)
+{
+ eat(T___builtin_va_start);
+
+ expression_t *expression = allocate_expression_zero(EXPR_VA_START);
+
+ expect('(');
+ expression->va_starte.ap = parse_assignment_expression();
+ expect(',');
+ if (token.type != T_IDENTIFIER) {
+ parse_error_expected("while parsing va_start", T_IDENTIFIER, 0);
+ eat_paren();
+ return create_invalid_expression();
+ }
+ expression_t *const expr = parse_reference();
+ if (expr->type == EXPR_INVALID) {
+ return create_invalid_expression();
+ }
+ assert(expr->type == EXPR_REFERENCE);
+ declaration_t *const decl = expr->reference.declaration;
+ if (decl->parent_context != ¤t_function->context ||
+ decl->next != NULL) {
+ parser_print_error_prefix_pos(decl->source_position);
+ fprintf(stderr, "second argument of 'va_start' must be last parameter "
+ "of the current function\n");
+ }
+ expression->va_starte.parameter = decl;
+ expect(')');
+
+ return expression;
+}
+
static expression_t *parse_va_arg(void)
{
eat(T___builtin_va_arg);
expression_t *expression = allocate_expression_zero(EXPR_VA_ARG);
expect('(');
- expression->va_arge.arg = parse_assignment_expression();
+ expression->va_arge.ap = parse_assignment_expression();
expect(',');
expression->base.datatype = parse_typename();
expect(')');
return parse_pretty_function_keyword();
case T___builtin_offsetof:
return parse_offsetof();
+ case T___builtin_va_start:
+ return parse_va_start();
case T___builtin_va_arg:
return parse_va_arg();
case T___builtin_nanf:
case T___builtin_alloca:
case T___builtin_expect:
- case T___builtin_va_start:
case T___builtin_va_end:
return parse_builtin_symbol();
fprintf(stderr, "\n");
eat_statement();
- return make_invalid_expression();
+ return create_invalid_expression();
}
static expression_t *parse_array_expression(unsigned precedence,
type_t *orig_type = compound->base.datatype;
if(orig_type == NULL)
- return make_invalid_expression();
+ return create_invalid_expression();
type_t *type = skip_typeref(orig_type);
fprintf(stderr, "left hand side of '->' is not a pointer, but ");
print_type_quoted(orig_type);
fputc('\n', stderr);
- return make_invalid_expression();
+ return create_invalid_expression();
}
pointer_type_t *pointer_type = &type->pointer;
type_left = pointer_type->points_to;
"union, but ", symbol->string);
print_type_quoted(type_left);
fputc('\n', stderr);
- return make_invalid_expression();
+ return create_invalid_expression();
}
compound_type_t *compound_type = &type_left->compound;
symbol->string);
print_type_quoted(type_left);
fputc('\n', stderr);
- return make_invalid_expression();
+ return create_invalid_expression();
}
declaration_t *iter = declaration->context.declarations;
parser_print_error_prefix();
print_type_quoted(type_left);
fprintf(stderr, " has no member named '%s'\n", symbol->string);
- return make_invalid_expression();
+ return create_invalid_expression();
}
/* we always do the auto-type conversions; the & and sizeof parser contains
type_void = make_atomic_type(ATOMIC_TYPE_VOID, TYPE_QUALIFIER_NONE);
type_void_ptr = make_pointer_type(type_void, TYPE_QUALIFIER_NONE);
type_string = make_pointer_type(type_char, TYPE_QUALIFIER_NONE);
+
+ symbol_t *const va_list_sym = symbol_table_insert("__builtin_va_list");
+ type_valist = create_builtin_type(va_list_sym, type_void_ptr);
}
void exit_parser(void)
S(__builtin_va_list)
S(__builtin_expect)
S(__builtin_offsetof)
-S(__builtin_va_start)
S(__builtin_va_arg)
S(__builtin_va_end)
S(__builtin_alloca)
S(__imag__)
#undef S
-T(const, "__const",)
-T(_const, "const", = T_const)
-T(restrict, "__restrict",)
-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)
-T(typeof, "typeof",)
-T(__typeof__, "__typeof__", = T_typeof)
+T(const, "__const",)
+T(_const, "const", = T_const)
+T(restrict, "__restrict",)
+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)
+T(typeof, "typeof",)
+T(__typeof__, "__typeof__", = T_typeof)
+T(__builtin_va_start, "__builtin_va_start",)
+T(__builtin_stdarg_start, "__builtin_stdarg_start", = T___builtin_va_start)
T(MINUSGREATER, "->",)
T(PLUSPLUS, "++",)
assert(!is_typeref(type));
if(is_type_integer(type) || is_type_floating(type))
- return 1;
+ return true;
- return 0;
+ return false;
}
bool is_type_scalar(const type_t *type)
{
assert(!is_typeref(type));
- if(type->type == TYPE_POINTER)
- return 1;
+ switch (type->type) {
+ case TYPE_POINTER: return true;
+ case TYPE_BUILTIN: return is_type_scalar(type->builtin.real_type);
+ default: break;
+ }
return is_type_arithmetic(type);
}
case TYPE_ATOMIC:
case TYPE_POINTER:
case TYPE_ENUM:
+ case TYPE_BUILTIN:
return false;
case TYPE_TYPEDEF:
case TYPE_TYPEOF:
- case TYPE_BUILTIN:
panic("is_type_incomplete called without typerefs skipped");
case TYPE_INVALID:
break;
}
continue;
}
- case TYPE_BUILTIN: {
- const builtin_type_t *builtin_type = &type->builtin;
- type = builtin_type->real_type;
- continue;
- }
default:
break;
}