print_type(unexpr->expression.datatype);
fputs(")", out);
break;
+ case UNEXPR_CAST_IMPLICIT:
+ break;
case UNEXPR_INVALID:
fprintf(out, "unop%d", (int) unexpr->type);
break;
static void print_asm_statement(const asm_statement_t *statement)
{
- fputs("asm", out);
+ fputs("asm ", out);
if(statement->is_volatile) {
- fputs(" volatile", out);
+ fputs("volatile ", out);
}
fputs("(", out);
print_quoted_string(statement->asm_text);
if(statement->outputs == NULL && statement->clobbers == NULL)
goto end_of_print_asm_statement;
- fputs(": ", out);
+ fputs(" : ", out);
print_asm_constraints(statement->outputs);
if(statement->clobbers == NULL)
goto end_of_print_asm_statement;
- fputs(": ", out);
+ fputs(" : ", out);
print_asm_clobbers(statement->clobbers);
end_of_print_asm_statement:
static type_t *type_void;
static type_t *type_int;
-static symbol_t *symbol_alloca;
+static symbol_t *symbol_builtin_alloca;
+static symbol_t *symbol_builtin_nanf;
static int next_value_number_function;
static ir_node *continue_label;
type_void->base.firm_type = ir_type_void;
- symbol_alloca = symbol_table_insert("__builtin_alloca");
+ symbol_builtin_alloca = symbol_table_insert("__builtin_alloca");
+ symbol_builtin_nanf = symbol_table_insert("__builtin_nanf");
}
void exit_ast2firm(void)
return load_res;
}
+static ir_node *do_strict_conv(dbg_info *dbgi, ir_node *node)
+{
+ ir_mode *mode = get_irn_mode(node);
+
+ if(!(get_irg_fp_model(current_ir_graph) & fp_explicit_rounding))
+ return node;
+ if(!mode_is_float(mode))
+ return node;
+
+ /* check if there is already a Conv */
+ if (get_irn_op(node) == op_Conv) {
+ /* convert it into a strict Conv */
+ set_Conv_strict(node, 1);
+ return node;
+ }
+
+ /* otherwise create a new one */
+ return new_d_strictConv(dbgi, node, mode);
+}
+
static ir_node *get_global_var_address(dbg_info *const dbgi,
const declaration_t *const decl)
{
= (builtin_symbol_expression_t*) call->function;
symbol_t *symbol = builtin->symbol;
- if(symbol == symbol_alloca) {
+ if(symbol == symbol_builtin_alloca) {
if(call->arguments == NULL || call->arguments->next != NULL) {
panic("invalid number of parameters on __builtin_alloca");
}
set_store(proj_m);
ir_node *res = new_Proj(alloca, mode_P_data, pn_Alloc_res);
+ return res;
+ } else if(symbol == symbol_builtin_nanf) {
+ /* Ignore string for now... */
+ ir_mode *mode = mode_D;
+ tarval *tv = get_mode_NAN(mode);
+ ir_node *res = new_d_Const(dbgi, mode, tv);
return res;
} else {
panic("Unsupported builtin found\n");
++n_parameters;
}
+ dbg_info *dbgi = get_dbg_info(&call->expression.source_position);
+
ir_type *ir_method_type = get_ir_type((type_t*) function_type);
ir_type *new_method_type = NULL;
if(function_type->variadic || function_type->unspecified_parameters) {
expression_t *expression = argument->expression;
ir_node *arg_node = expression_to_firm(expression);
+ arg_node = do_strict_conv(dbgi, arg_node);
+
in[n] = arg_node;
if(new_method_type != NULL) {
ir_type *irtype = get_ir_type(expression->base.datatype);
if(new_method_type != NULL)
ir_method_type = new_method_type;
- dbg_info *dbgi = get_dbg_info(&call->expression.source_position);
ir_node *store = get_store();
ir_node *node = new_d_Call(dbgi, store, callee, n_parameters, in,
ir_method_type);
static void set_value_for_expression(const expression_t *expression,
ir_node *value)
{
+ dbg_info *dbgi = get_dbg_info(&expression->base.source_position);
+ value = do_strict_conv(dbgi, value);
+
if(expression->type == EXPR_REFERENCE) {
reference_expression_t *ref = (reference_expression_t*) expression;
}
}
- dbg_info *dbgi = get_dbg_info(&expression->base.source_position);
ir_node *addr = expression_to_addr(expression);
ir_node *memory = get_store();
case UNEXPR_PREFIX_INCREMENT:
case UNEXPR_PREFIX_DECREMENT:
return create_incdec(expression);
- case UNEXPR_CAST:
+ case UNEXPR_CAST: {
+ ir_node *node = create_conv(dbgi, value_node, get_ir_mode(type));
+ node = do_strict_conv(dbgi, node);
+ return node;
+ }
+ case UNEXPR_CAST_IMPLICIT:
return create_conv(dbgi, value_node, get_ir_mode(type));
case UNEXPR_TAKE_ADDRESS:
set_cur_block(NULL);
}
-
static void return_statement_to_firm(return_statement_t *statement)
{
if(get_cur_block() == NULL)
ir_type *res_type = get_method_res_type(func_irtype, 0);
if(statement->return_value != NULL) {
- in[0] = expression_to_firm(statement->return_value);
+ ir_node *node = expression_to_firm(statement->return_value);
+ node = do_strict_conv(dbgi, node);
+ in[0] = node;
} else {
ir_mode *mode;
if(is_compound_type(res_type)) {
case STATEMENT_INVALID:
panic("invalid statement found");
case STATEMENT_COMPOUND:
- compound_statement_to_firm((compound_statement_t*) statement);
+ compound_statement_to_firm(&statement->compound);
return;
case STATEMENT_RETURN:
- return_statement_to_firm((return_statement_t*) statement);
+ return_statement_to_firm(&statement->returns);
return;
case STATEMENT_EXPRESSION:
- expression_statement_to_firm((expression_statement_t*) statement);
+ expression_statement_to_firm(&statement->expression);
return;
case STATEMENT_IF:
- if_statement_to_firm((if_statement_t*) statement);
+ if_statement_to_firm(&statement->ifs);
return;
case STATEMENT_WHILE:
- while_statement_to_firm((while_statement_t*) statement);
+ while_statement_to_firm(&statement->whiles);
return;
case STATEMENT_DO_WHILE:
- do_while_statement_to_firm((do_while_statement_t*) statement);
+ do_while_statement_to_firm(&statement->do_while);
return;
case STATEMENT_DECLARATION:
- declaration_statement_to_firm((declaration_statement_t*) statement);
+ declaration_statement_to_firm(&statement->declaration);
return;
case STATEMENT_BREAK:
create_jump_statement(statement, break_label);
create_jump_statement(statement, continue_label);
return;
case STATEMENT_SWITCH:
- switch_statement_to_firm((switch_statement_t*) statement);
+ switch_statement_to_firm(&statement->switchs);
return;
case STATEMENT_CASE_LABEL:
- case_label_to_firm((case_label_statement_t*) statement);
+ case_label_to_firm(&statement->case_label);
return;
case STATEMENT_FOR:
- for_statement_to_firm((for_statement_t*) statement);
+ for_statement_to_firm(&statement->fors);
return;
case STATEMENT_LABEL:
- label_to_firm((label_statement_t*) statement);
+ label_to_firm(&statement->label);
return;
case STATEMENT_GOTO:
- goto_to_firm((goto_statement_t*) statement);
+ goto_to_firm(&statement->gotos);
return;
case STATEMENT_ASM:
break;
UNEXPR_POSTFIX_DECREMENT,
UNEXPR_PREFIX_INCREMENT,
UNEXPR_PREFIX_DECREMENT,
- UNEXPR_CAST
+ UNEXPR_CAST,
+ UNEXPR_CAST_IMPLICIT /* compiler generated cast */
} unary_expression_type_t;
struct unary_expression_t {
#include "adt/strset.h"
#include "adt/util.h"
#include "type_t.h"
+#include "target_architecture.h"
#include <assert.h>
#include <errno.h>
#define strtold(s, e) strtod(s, e)
#endif
-#define HAS_SIGNED_CHAR
-//#define HAS_UNSIGNED_CHAR
-
#if defined HAS_SIGNED_CHAR
typedef signed char char_type;
#elif defined HAS_UNSIGNED_CHAR
static type_t *type_int = NULL;
static type_t *type_uint = NULL;
+static type_t *type_long = NULL;
static type_t *type_ulong = NULL;
static type_t *type_longlong = NULL;
static type_t *type_ulonglong = NULL;
}
}
-static void parse_integer_suffix(void)
+static void parse_integer_suffix(bool is_oct_hex)
{
+ bool is_unsigned = false;
+ bool min_long = false;
+ bool min_longlong = false;
+
if(c == 'U' || c == 'u') {
+ is_unsigned = true;
next_char();
if(c == 'L' || c == 'l') {
+ min_long = true;
next_char();
if(c == 'L' || c == 'l') {
+ min_longlong = true;
next_char();
- lexer_token.datatype = type_ulonglong;
- } else {
- lexer_token.datatype = type_ulong;
}
- } else {
- lexer_token.datatype = type_uint;
}
} else if(c == 'l' || c == 'L') {
+ min_long = true;
next_char();
if(c == 'l' || c == 'L') {
+ min_longlong = true;
next_char();
if(c == 'u' || c == 'U') {
+ is_unsigned = true;
next_char();
- lexer_token.datatype = type_ulonglong;
- } else {
- lexer_token.datatype = type_longlong;
}
} else if(c == 'u' || c == 'U') {
+ is_unsigned = true;
next_char();
lexer_token.datatype = type_ulong;
- } else {
- lexer_token.datatype = type_int;
}
+ }
+
+ if(!is_unsigned) {
+ long long v = lexer_token.v.intvalue;
+ if(!min_long) {
+ if(v >= TARGET_INT_MIN && v <= TARGET_INT_MAX) {
+ lexer_token.datatype = type_int;
+ return;
+ } else if(is_oct_hex && v >= 0 && v <= TARGET_UINT_MAX) {
+ lexer_token.datatype = type_uint;
+ return;
+ }
+ }
+ if(!min_longlong) {
+ if(v >= TARGET_LONG_MIN && v <= TARGET_LONG_MAX) {
+ lexer_token.datatype = type_long;
+ return;
+ } else if(is_oct_hex && v >= 0 && v <= TARGET_ULONG_MAX) {
+ lexer_token.datatype = type_ulong;
+ return;
+ }
+ }
+ unsigned long long uv = (unsigned long long) v;
+ if(is_oct_hex && uv > (unsigned long long) TARGET_LONGLONG_MAX) {
+ lexer_token.datatype = type_ulonglong;
+ return;
+ }
+
+ lexer_token.datatype = type_longlong;
} else {
- lexer_token.datatype = type_int;
+ unsigned long long v = (unsigned long long) lexer_token.v.intvalue;
+ if(!min_long && v <= TARGET_UINT_MAX) {
+ lexer_token.datatype = type_uint;
+ return;
+ }
+ if(!min_longlong && v <= TARGET_ULONG_MAX) {
+ lexer_token.datatype = type_ulong;
+ return;
+ }
+ lexer_token.datatype = type_ulonglong;
}
}
}
obstack_free(&symbol_obstack, string);
- parse_integer_suffix();
+ parse_integer_suffix(true);
}
static inline bool is_octal_digit(int chr)
}
obstack_free(&symbol_obstack, string);
- parse_integer_suffix();
+ parse_integer_suffix(true);
}
static void parse_number_dec(void)
parse_error("invalid number literal");
}
- parse_integer_suffix();
+ parse_integer_suffix(false);
}
obstack_free(&symbol_obstack, string);
}
{
strset_init(&stringset);
- type_int = make_atomic_type(ATOMIC_TYPE_INT, TYPE_QUALIFIER_CONST);
- type_uint = make_atomic_type(ATOMIC_TYPE_UINT, TYPE_QUALIFIER_CONST);
- type_ulong = make_atomic_type(ATOMIC_TYPE_ULONG, TYPE_QUALIFIER_CONST);
+ type_int = make_atomic_type(ATOMIC_TYPE_INT, TYPE_QUALIFIER_NONE);
+ type_uint = make_atomic_type(ATOMIC_TYPE_UINT, TYPE_QUALIFIER_NONE);
+ type_long = make_atomic_type(ATOMIC_TYPE_LONG, TYPE_QUALIFIER_NONE);
+ type_ulong = make_atomic_type(ATOMIC_TYPE_ULONG, TYPE_QUALIFIER_NONE);
type_longlong = make_atomic_type(ATOMIC_TYPE_LONGLONG,
- TYPE_QUALIFIER_CONST);
+ TYPE_QUALIFIER_NONE);
type_ulonglong = make_atomic_type(ATOMIC_TYPE_ULONGLONG,
- TYPE_QUALIFIER_CONST);
+ TYPE_QUALIFIER_NONE);
type_float = make_atomic_type(ATOMIC_TYPE_FLOAT, TYPE_QUALIFIER_CONST);
type_double = make_atomic_type(ATOMIC_TYPE_DOUBLE,
#include "write_fluffy.h"
#ifndef PREPROCESSOR
-#define PREPROCESSOR "cpp"
+#define PREPROCESSOR "cpp -std=c99"
#endif
#ifndef LINKER
{
expression_t *cast = allocate_expression_zero(EXPR_UNARY);
- cast->unary.type = UNEXPR_CAST;
+ cast->unary.type = UNEXPR_CAST_IMPLICIT;
cast->unary.value = expression;
cast->base.datatype = dest_type;
switch(symbol->ID) {
case T___builtin_alloca:
return make_function_1_type(type_void_ptr, type_size_t);
+ case T___builtin_nanf:
+ return make_function_1_type(type_double, type_string);
default:
panic("not implemented builtin symbol found");
}
return parse_offsetof();
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:
S(__builtin_va_arg)
S(__builtin_va_end)
S(__builtin_alloca)
+S(__builtin_nanf)
S(__PRETTY_FUNCTION__)
S(__FUNCTION__)
S(__func__)
S(__alignof__)
-S(__typeof__)
S(__real__)
S(__imag__)
#undef S
T(inline, "inline",)
T(__inline, "__inline", = T_inline)
T(__inline__, "__inline__", = T_inline)
+T(typeof, "typeof",)
+T(__typeof__, "__typeof__", = T_typeof)
T(MINUSGREATER, "->",)
T(PLUSPLUS, "++",)