diff options
-rw-r--r-- | Makefile | 5 | ||||
-rwxr-xr-x | cgcc | 32 | ||||
-rw-r--r-- | evaluate.c | 4 | ||||
-rw-r--r-- | machine.h | 6 | ||||
-rw-r--r-- | options.c | 19 | ||||
-rw-r--r-- | parse.c | 310 | ||||
-rw-r--r-- | predefine.c | 69 | ||||
-rw-r--r-- | sparse.1 | 10 | ||||
-rw-r--r-- | symbol.c | 7 | ||||
-rw-r--r-- | symbol.h | 3 | ||||
-rw-r--r-- | target-alpha.c | 3 | ||||
-rw-r--r-- | target-arm.c | 21 | ||||
-rw-r--r-- | target-arm64.c | 5 | ||||
-rw-r--r-- | target-h8300.c | 34 | ||||
-rw-r--r-- | target-m68k.c | 9 | ||||
-rw-r--r-- | target-microblaze.c | 9 | ||||
-rw-r--r-- | target-mips.c | 10 | ||||
-rw-r--r-- | target-nds32.c | 33 | ||||
-rw-r--r-- | target-nios2.c | 20 | ||||
-rw-r--r-- | target-openrisc.c | 31 | ||||
-rw-r--r-- | target-ppc.c | 13 | ||||
-rw-r--r-- | target-riscv.c | 111 | ||||
-rw-r--r-- | target-s390.c | 12 | ||||
-rw-r--r-- | target-sh.c | 36 | ||||
-rw-r--r-- | target-sparc.c | 26 | ||||
-rw-r--r-- | target-x86.c | 122 | ||||
-rw-r--r-- | target-xtensa.c | 36 | ||||
-rw-r--r-- | target.c | 80 | ||||
-rw-r--r-- | target.h | 29 | ||||
-rw-r--r-- | validation/eval/array-quals-node.c | 29 | ||||
-rw-r--r-- | validation/eval/array-quals0.c | 6 | ||||
-rw-r--r-- | validation/eval/array-quals1.c | 49 | ||||
-rw-r--r-- | validation/linear/bug-assign-op0.c | 115 | ||||
-rw-r--r-- | validation/static_assert.c | 5 |
34 files changed, 1080 insertions, 229 deletions
@@ -73,15 +73,20 @@ LIB_OBJS += target-arm.o LIB_OBJS += target-arm64.o LIB_OBJS += target-bfin.o LIB_OBJS += target-default.o +LIB_OBJS += target-h8300.o LIB_OBJS += target-m68k.o LIB_OBJS += target-microblaze.o LIB_OBJS += target-mips.o +LIB_OBJS += target-nds32.o LIB_OBJS += target-nios2.o +LIB_OBJS += target-openrisc.o LIB_OBJS += target-ppc.o LIB_OBJS += target-riscv.o LIB_OBJS += target-s390.o +LIB_OBJS += target-sh.o LIB_OBJS += target-sparc.o LIB_OBJS += target-x86.o +LIB_OBJS += target-xtensa.o LIB_OBJS += tokenize.o LIB_OBJS += unssa.o LIB_OBJS += utils.o @@ -221,48 +221,32 @@ sub float_types { sub add_specs { my ($spec) = @_; if ($spec eq 'sunos') { - return &add_specs ('unix') . - ' -D__sun__=1 -D__sun=1 -Dsun=1' . - ' -D__svr4__=1 -DSVR4=1' . + return " --os=$spec" . + ' -DSVR4=1' . ' -D__STDC__=0' . ' -D_REENTRANT' . ' -D_SOLARIS_THREADS' . ' -DNULL="((void *)0)"'; } elsif ($spec eq 'linux') { - return &add_specs ('unix') . - ' -D__linux__=1 -D__linux=1 -Dlinux=1'; + return " --os=$spec"; } elsif ($spec eq 'gnu/kfreebsd') { return &add_specs ('unix') . ' -D__FreeBSD_kernel__=1'; } elsif ($spec eq 'openbsd') { - return &add_specs ('unix') . - ' -D__OpenBSD__=1'; + return " --os=$spec"; } elsif ($spec eq 'freebsd') { - return &add_specs ('unix') . - ' -D__FreeBSD__=1'; + return " --os=$spec"; } elsif ($spec eq 'netbsd') { - return &add_specs ('unix') . - ' -D__NetBSD__=1'; + return " --os=$spec"; } elsif ($spec eq 'darwin') { - return - ' -D__APPLE__=1 -D__APPLE_CC__=1 -D__MACH__=1'; + return " --os=$spec"; } elsif ($spec eq 'gnu') { # Hurd return &add_specs ('unix') . # So, GNU is Unix, uh? ' -D__GNU__=1 -D__gnu_hurd__=1 -D__MACH__=1'; } elsif ($spec eq 'unix') { return ' -Dunix=1 -D__unix=1 -D__unix__=1'; } elsif ( $spec =~ /^cygwin/) { - return &add_specs ('unix') . - ' -fshort-wchar' . - ' -D__CYGWIN__=1' . - ($m32 ? ' -D__CYGWIN32__=1' : '') . - " -D'_cdecl=__attribute__((__cdecl__))'" . - " -D'__cdecl=__attribute__((__cdecl__))'" . - " -D'_stdcall=__attribute__((__stdcall__))'" . - " -D'__stdcall=__attribute__((__stdcall__))'" . - " -D'_fastcall=__attribute__((__fastcall__))'" . - " -D'__fastcall=__attribute__((__fastcall__))'" . - " -D'__declspec(x)=__attribute__((x))'"; + return ' --os=cygwin'; } elsif ($spec eq 'i386') { $m32 = 1; return ( @@ -1444,8 +1444,8 @@ static int check_assignment_types(struct symbol *target, struct expression **rp, } b1 = examine_pointer_target(t); b2 = examine_pointer_target(s); - mod1 = target_qualifiers(t); - mod2 = target_qualifiers(s); + mod1 = t->ctype.modifiers & MOD_IGN; + mod2 = s->ctype.modifiers & MOD_IGN; if (whitelist_pointers(b1, b2)) { /* * assignments to/from void * are OK, provided that @@ -34,9 +34,14 @@ enum machine { MACH_S390, MACH_S390X, MACH_ALPHA, MACH_BFIN, + MACH_H8300, MACH_M68K, MACH_MICROBLAZE, + MACH_NDS32, MACH_NIOS2, + MACH_OPENRISC, + MACH_SH, + MACH_XTENSA, MACH_UNKNOWN }; @@ -94,6 +99,7 @@ enum fp_abi { enum { OS_UNKNOWN, + OS_NONE, OS_UNIX, OS_CYGWIN, OS_DARWIN, @@ -609,6 +609,13 @@ static char **handle_switch_M(char *arg, char **next) return next; } +static int handle_march(const char *opt, const char *arg, const struct flag *flag, int options) +{ + if (arch_target->parse_march) + arch_target->parse_march(arg); + return 1; +} + static int handle_mcmodel(const char *opt, const char *arg, const struct flag *flag, int options) { static const struct val_map cmodels[] = { @@ -650,6 +657,7 @@ static const struct flag mflags[] = { { "x32",&arch_m64, NULL, OPT_VAL, ARCH_X32 }, { "size-llp64", &arch_m64, NULL, OPT_VAL, ARCH_LLP64 }, { "size-long", &arch_msize_long }, + { "arch=", NULL, handle_march }, { "big-endian", &arch_big_endian, NULL }, { "little-endian", &arch_big_endian, NULL, OPT_INVERSE }, { "cmodel", &arch_cmodel, handle_mcmodel }, @@ -925,6 +933,16 @@ static char **handle_param(char *arg, char **next) return next; } +static char **handle_os(char *arg, char **next) +{ + if (*arg++ != '=') + die("missing argument for --os option"); + + target_os(arg); + + return next; +} + static char **handle_version(char *arg, char **next) { printf("%s\n", SPARSE_VERSION); @@ -941,6 +959,7 @@ static char **handle_long_options(char *arg, char **next) { static struct switches cmd[] = { { "arch", handle_arch, 1 }, + { "os", handle_os, 1 }, { "param", handle_param, 1 }, { "version", handle_version }, { NULL, NULL } @@ -455,159 +455,132 @@ static struct symbol_op mode_word_op = { .to_mode = to_word_mode }; -/* Using NS_TYPEDEF will also make the keyword a reserved one */ +/* + * Define the keyword and their effects. + * The entries in the 'typedef' and put in NS_TYPEDEF and + * are automatically set as reserved keyword while the ones + * in the 'keyword' table are just put in NS_KEYWORD. + * + * The entries are added via the 3 macros: + * N() for entries with "name" only, + * D() for entries with "name" & "__name__", + * A() for entries with "name", "__name" & "__name__", + * U() for entries with "__name" & "__name__". + */ static struct init_keyword { const char *name; - enum namespace ns; - unsigned long modifiers; struct symbol_op *op; struct symbol *type; -} keyword_table[] = { + unsigned long mods; +} typedefs[] = { +#define N(I, O,...) { I, O,##__VA_ARGS__ } +#define D(I, O,...) N(I,O,##__VA_ARGS__ ), \ + N("__" I "__",O,##__VA_ARGS__) +#define A(I, O,...) N(I,O,##__VA_ARGS__ ), \ + N("__" I,O,##__VA_ARGS__), \ + N("__" I "__",O,##__VA_ARGS__) +#define U(I, O,...) N("__" I,O,##__VA_ARGS__), \ + N("__" I "__",O,##__VA_ARGS__) + /* Storage classes */ + N("auto", &auto_op), + N("register", ®ister_op), + N("static", &static_op), + N("extern", &extern_op), + N("__thread", &thread_op), + N("_Thread_local", &thread_op), + + A("inline", &inline_op), + + /* Typedef ... */ + N("typedef", &typedef_op), + A("typeof", &typeof_op), + N("__auto_type", &autotype_op), + /* Type qualifiers */ - { "const", NS_TYPEDEF, .op = &const_op }, - { "__const", NS_TYPEDEF, .op = &const_op }, - { "__const__", NS_TYPEDEF, .op = &const_op }, - { "volatile", NS_TYPEDEF, .op = &volatile_op }, - { "__volatile", NS_TYPEDEF, .op = &volatile_op }, - { "__volatile__", NS_TYPEDEF, .op = &volatile_op }, - { "restrict", NS_TYPEDEF, .op = &restrict_op}, - { "__restrict", NS_TYPEDEF, .op = &restrict_op}, - { "__restrict__", NS_TYPEDEF, .op = &restrict_op}, - { "_Atomic", NS_TYPEDEF, .op = &atomic_op}, - - /* Typedef.. */ - { "typedef", NS_TYPEDEF, .op = &typedef_op }, + A("const", &const_op), + A("volatile", &volatile_op), + A("restrict", &restrict_op), + + N("_Atomic", &atomic_op), + N("_Noreturn", &noreturn_op), + N("_Alignas", &alignas_op), + + U("attribute", &attribute_op), /* Type specifiers */ - { "void", NS_TYPEDEF, .type = &void_ctype, .op = &spec_op}, - { "char", NS_TYPEDEF, .op = &char_op }, - { "short", NS_TYPEDEF, .op = &short_op }, - { "int", NS_TYPEDEF, .op = &int_op }, - { "long", NS_TYPEDEF, .op = &long_op }, - { "float", NS_TYPEDEF, .op = &float_op }, - { "double", NS_TYPEDEF, .op = &double_op }, - { "signed", NS_TYPEDEF, .op = &signed_op }, - { "__signed", NS_TYPEDEF, .op = &signed_op }, - { "__signed__", NS_TYPEDEF, .op = &signed_op }, - { "unsigned", NS_TYPEDEF, .op = &unsigned_op }, - { "__int128", NS_TYPEDEF, .op = &int128_op }, - { "_Bool", NS_TYPEDEF, .type = &bool_ctype, .op = &spec_op }, + N("struct", &struct_op), + N("union", &union_op), + N("enum", &enum_op), + + N("void", &spec_op, .type = &void_ctype), + N("char", &char_op), + N("short", &short_op), + N("int", &int_op), + N("long", &long_op), + N("float", &float_op), + N("double", &double_op), + A("signed", &signed_op), + N("unsigned", &unsigned_op), + N("__int128", &int128_op), + N("_Bool", &spec_op, .type = &bool_ctype), /* Predeclared types */ - { "__builtin_va_list", NS_TYPEDEF, .type = &ptr_ctype, .op = &spec_op }, - { "__builtin_ms_va_list", NS_TYPEDEF, .type = &ptr_ctype, .op = &spec_op }, - { "__int128_t", NS_TYPEDEF, .type = &sint128_ctype, .op = &spec_op }, - { "__uint128_t",NS_TYPEDEF, .type = &uint128_ctype, .op = &spec_op }, - { "_Float32", NS_TYPEDEF, .type = &float32_ctype, .op = &spec_op }, - { "_Float32x", NS_TYPEDEF, .type = &float32x_ctype, .op = &spec_op }, - { "_Float64", NS_TYPEDEF, .type = &float64_ctype, .op = &spec_op }, - { "_Float64x", NS_TYPEDEF, .type = &float64x_ctype, .op = &spec_op }, - { "_Float128", NS_TYPEDEF, .type = &float128_ctype, .op = &spec_op }, - - /* Extended types */ - { "typeof", NS_TYPEDEF, .op = &typeof_op }, - { "__typeof", NS_TYPEDEF, .op = &typeof_op }, - { "__typeof__", NS_TYPEDEF, .op = &typeof_op }, - { "__auto_type",NS_TYPEDEF, .op = &autotype_op }, - - { "__attribute", NS_TYPEDEF, .op = &attribute_op }, - { "__attribute__", NS_TYPEDEF, .op = &attribute_op }, - - { "struct", NS_TYPEDEF, .op = &struct_op }, - { "union", NS_TYPEDEF, .op = &union_op }, - { "enum", NS_TYPEDEF, .op = &enum_op }, - - { "inline", NS_TYPEDEF, .op = &inline_op }, - { "__inline", NS_TYPEDEF, .op = &inline_op }, - { "__inline__", NS_TYPEDEF, .op = &inline_op }, - - { "_Noreturn", NS_TYPEDEF, .op = &noreturn_op }, - - { "_Alignas", NS_TYPEDEF, .op = &alignas_op }, - - /* Static assertion */ - { "_Static_assert", NS_KEYWORD, .op = &static_assert_op }, - - /* Storage class */ - { "auto", NS_TYPEDEF, .op = &auto_op }, - { "register", NS_TYPEDEF, .op = ®ister_op }, - { "static", NS_TYPEDEF, .op = &static_op }, - { "extern", NS_TYPEDEF, .op = &extern_op }, - { "__thread", NS_TYPEDEF, .op = &thread_op }, - { "_Thread_local", NS_TYPEDEF, .op = &thread_op }, - - /* Statement */ - { "if", NS_KEYWORD, .op = &if_op }, - { "return", NS_KEYWORD, .op = &return_op }, - { "break", NS_KEYWORD, .op = &loop_iter_op }, - { "continue", NS_KEYWORD, .op = &loop_iter_op }, - { "default", NS_KEYWORD, .op = &default_op }, - { "case", NS_KEYWORD, .op = &case_op }, - { "switch", NS_KEYWORD, .op = &switch_op }, - { "for", NS_KEYWORD, .op = &for_op }, - { "while", NS_KEYWORD, .op = &while_op }, - { "do", NS_KEYWORD, .op = &do_op }, - { "goto", NS_KEYWORD, .op = &goto_op }, - { "context", NS_KEYWORD, .op = &context_op }, - { "__context__",NS_KEYWORD, .op = &__context___op }, - { "__range__", NS_KEYWORD, .op = &range_op }, - { "asm", NS_KEYWORD, .op = &asm_op }, - { "__asm", NS_KEYWORD, .op = &asm_op }, - { "__asm__", NS_KEYWORD, .op = &asm_op }, - - /* Attribute */ - { "packed", NS_KEYWORD, .op = &packed_op }, - { "__packed__", NS_KEYWORD, .op = &packed_op }, - { "aligned", NS_KEYWORD, .op = &aligned_op }, - { "__aligned__",NS_KEYWORD, .op = &aligned_op }, - { "nocast", NS_KEYWORD, MOD_NOCAST, .op = &attr_mod_op }, - { "__nocast__", NS_KEYWORD, MOD_NOCAST, .op = &attr_mod_op }, - { "noderef", NS_KEYWORD, MOD_NODEREF, .op = &attr_mod_op }, - { "__noderef__",NS_KEYWORD, MOD_NODEREF, .op = &attr_mod_op }, - { "safe", NS_KEYWORD, MOD_SAFE, .op = &attr_mod_op }, - { "__safe__", NS_KEYWORD, MOD_SAFE, .op = &attr_mod_op }, - { "unused", NS_KEYWORD, MOD_UNUSED, .op = &attr_mod_op }, - { "__unused__", NS_KEYWORD, MOD_UNUSED, .op = &attr_mod_op }, - { "externally_visible", NS_KEYWORD, MOD_EXT_VISIBLE,.op = &attr_mod_op }, - { "__externally_visible__", NS_KEYWORD,MOD_EXT_VISIBLE,.op = &attr_mod_op }, - { "force", NS_KEYWORD, .op = &attr_force_op }, - { "__force__", NS_KEYWORD, .op = &attr_force_op }, - { "bitwise", NS_KEYWORD, MOD_BITWISE, .op = &attr_bitwise_op }, - { "__bitwise__",NS_KEYWORD, MOD_BITWISE, .op = &attr_bitwise_op }, - { "address_space",NS_KEYWORD, .op = &address_space_op }, - { "__address_space__",NS_KEYWORD, .op = &address_space_op }, - { "designated_init", NS_KEYWORD, .op = &designated_init_op }, - { "__designated_init__", NS_KEYWORD, .op = &designated_init_op }, - { "transparent_union", NS_KEYWORD, .op = &transparent_union_op }, - { "__transparent_union__", NS_KEYWORD, .op = &transparent_union_op }, - { "noreturn", NS_KEYWORD, MOD_NORETURN, .op = &attr_fun_op }, - { "__noreturn__", NS_KEYWORD, MOD_NORETURN, .op = &attr_fun_op }, - { "pure", NS_KEYWORD, MOD_PURE, .op = &attr_fun_op }, - {"__pure__", NS_KEYWORD, MOD_PURE, .op = &attr_fun_op }, - {"const", NS_KEYWORD, MOD_PURE, .op = &attr_fun_op }, - {"__const", NS_KEYWORD, MOD_PURE, .op = &attr_fun_op }, - {"__const__", NS_KEYWORD, MOD_PURE, .op = &attr_fun_op }, - {"gnu_inline", NS_KEYWORD, MOD_GNU_INLINE, .op = &attr_fun_op }, - {"__gnu_inline__",NS_KEYWORD, MOD_GNU_INLINE, .op = &attr_fun_op }, - - { "mode", NS_KEYWORD, .op = &mode_op }, - { "__mode__", NS_KEYWORD, .op = &mode_op }, - { "QI", NS_KEYWORD, .op = &mode_QI_op }, - { "__QI__", NS_KEYWORD, .op = &mode_QI_op }, - { "HI", NS_KEYWORD, .op = &mode_HI_op }, - { "__HI__", NS_KEYWORD, .op = &mode_HI_op }, - { "SI", NS_KEYWORD, .op = &mode_SI_op }, - { "__SI__", NS_KEYWORD, .op = &mode_SI_op }, - { "DI", NS_KEYWORD, .op = &mode_DI_op }, - { "__DI__", NS_KEYWORD, .op = &mode_DI_op }, - { "TI", NS_KEYWORD, .op = &mode_TI_op }, - { "__TI__", NS_KEYWORD, .op = &mode_TI_op }, - { "byte", NS_KEYWORD, .op = &mode_QI_op }, - { "__byte__", NS_KEYWORD, .op = &mode_QI_op }, - { "pointer", NS_KEYWORD, .op = &mode_pointer_op }, - { "__pointer__",NS_KEYWORD, .op = &mode_pointer_op }, - { "word", NS_KEYWORD, .op = &mode_word_op }, - { "__word__", NS_KEYWORD, .op = &mode_word_op }, + N("__builtin_va_list", &spec_op, .type = &ptr_ctype), + N("__builtin_ms_va_list",&spec_op, .type = &ptr_ctype), + N("__int128_t", &spec_op, .type = &sint128_ctype), + N("__uint128_t", &spec_op, .type = &uint128_ctype), + N("_Float32", &spec_op, .type = &float32_ctype), + N("_Float32x", &spec_op, .type = &float32x_ctype), + N("_Float64", &spec_op, .type = &float64_ctype), + N("_Float64x", &spec_op, .type = &float64x_ctype), + N("_Float128", &spec_op, .type = &float128_ctype), +}, keywords[] = { + /* Statements */ + N("if", &if_op), + N("return", &return_op), + N("break", &loop_iter_op), + N("continue", &loop_iter_op), + N("default", &default_op), + N("case", &case_op), + N("switch", &switch_op), + N("for", &for_op), + N("while", &while_op), + N("do", &do_op), + N("goto", &goto_op), + A("asm", &asm_op), + N("context", &context_op), + N("__context__", &__context___op), + N("__range__", &range_op), + N("_Static_assert", &static_assert_op), + + /* Attributes */ + D("packed", &packed_op), + D("aligned", &aligned_op), + D("nocast", &attr_mod_op, .mods = MOD_NOCAST), + D("noderef", &attr_mod_op, .mods = MOD_NODEREF), + D("safe", &attr_mod_op, .mods = MOD_SAFE), + D("unused", &attr_mod_op, .mods = MOD_UNUSED), + D("externally_visible", &attr_mod_op, .mods = MOD_EXT_VISIBLE), + D("force", &attr_force_op), + D("bitwise", &attr_bitwise_op, .mods = MOD_BITWISE), + D("address_space", &address_space_op), + D("designated_init", &designated_init_op), + D("transparent_union", &transparent_union_op), + D("noreturn", &attr_fun_op, .mods = MOD_NORETURN), + D("pure", &attr_fun_op, .mods = MOD_PURE), + A("const", &attr_fun_op, .mods = MOD_PURE), + D("gnu_inline", &attr_fun_op, .mods = MOD_GNU_INLINE), + + /* Modes */ + D("mode", &mode_op), + D("QI", &mode_QI_op), + D("HI", &mode_HI_op), + D("SI", &mode_SI_op), + D("DI", &mode_DI_op), + D("TI", &mode_TI_op), + D("byte", &mode_QI_op), + D("pointer", &mode_pointer_op), + D("word", &mode_word_op), }; @@ -629,19 +602,24 @@ static const char *ignored_attributes[] = { }; +static void init_keyword(int stream, struct init_keyword *kw, enum namespace ns) +{ + struct symbol *sym = create_symbol(stream, kw->name, SYM_KEYWORD, ns); + sym->ident->keyword = 1; + sym->ident->reserved |= (ns == NS_TYPEDEF); + sym->ctype.modifiers = kw->mods; + sym->ctype.base_type = kw->type; + sym->op = kw->op; +} + void init_parser(int stream) { int i; - for (i = 0; i < ARRAY_SIZE(keyword_table); i++) { - struct init_keyword *ptr = keyword_table + i; - struct symbol *sym = create_symbol(stream, ptr->name, SYM_KEYWORD, ptr->ns); - sym->ident->keyword = 1; - if (ptr->ns == NS_TYPEDEF) - sym->ident->reserved = 1; - sym->ctype.modifiers = ptr->modifiers; - sym->ctype.base_type = ptr->type; - sym->op = ptr->op; - } + + for (i = 0; i < ARRAY_SIZE(typedefs); i++) + init_keyword(stream, &typedefs[i], NS_TYPEDEF); + for (i = 0; i < ARRAY_SIZE(keywords); i++) + init_keyword(stream, &keywords[i], NS_KEYWORD); for (i = 0; i < ARRAY_SIZE(ignored_attributes); i++) { const char * name = ignored_attributes[i]; @@ -2223,17 +2201,25 @@ static struct token *parse_static_assert(struct token *token, struct symbol_list token = constant_expression(token, &cond); if (!cond) sparse_error(token->pos, "Expected constant expression"); - token = expect(token, ',', "after conditional expression in _Static_assert"); - token = string_expression(token, &message, "_Static_assert()"); - if (!message) - cond = NULL; + if (match_op(token, ',')) { + token = token->next; + token = string_expression(token, &message, "_Static_assert()"); + if (!message) + cond = NULL; + } token = expect(token, ')', "after diagnostic message in _Static_assert"); - token = expect(token, ';', "after _Static_assert()"); - if (cond && !const_expression_value(cond) && cond->type == EXPR_VALUE) - sparse_error(cond->pos, "static assertion failed: %s", - show_string(message->string)); + if (cond && !const_expression_value(cond) && cond->type == EXPR_VALUE) { + const char *sep = "", *msg = ""; + + if (message) { + sep = ": "; + msg = show_string(message->string); + } + sparse_error(cond->pos, "static assertion failed%s%s", sep, msg); + } + return token; } diff --git a/predefine.c b/predefine.c index d05b1018..f898cdfa 100644 --- a/predefine.c +++ b/predefine.c @@ -25,12 +25,12 @@ static void predefined_sizeof(const char *name, const char *suffix, unsigned bit predefine(buf, 1, "%d", bits/8); } -static void predefined_width(const char *name, unsigned bits) +static void predefined_width(const char *name, struct symbol *type) { char buf[32]; snprintf(buf, sizeof(buf), "__%s_WIDTH__", name); - predefine(buf, 1, "%d", bits); + predefine(buf, 1, "%d", type->bit_size); } static void predefined_max(const char *name, struct symbol *type) @@ -78,7 +78,7 @@ static void predefined_ctype(const char *name, struct symbol *type, int flags) if (flags & PTYPE_TYPE) predefined_type(name, type); if (flags & PTYPE_WIDTH) - predefined_width(name, bits); + predefined_width(name, type); } void predefined_macros(void) @@ -145,13 +145,32 @@ void predefined_macros(void) predefined_ctype("INT64", int64_ctype, PTYPE_MAX|PTYPE_TYPE); predefined_ctype("UINT64", uint64_ctype, PTYPE_MAX|PTYPE_TYPE); + predefined_ctype("INT_LEAST8", &schar_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH); + predefined_ctype("UINT_LEAST8", &uchar_ctype, PTYPE_MAX|PTYPE_TYPE); + predefined_ctype("INT_LEAST16", &short_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH); + predefined_ctype("UINT_LEAST16",&ushort_ctype, PTYPE_MAX|PTYPE_TYPE); + predefined_ctype("INT_LEAST32", int32_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH); + predefined_ctype("UINT_LEAST32", uint32_ctype, PTYPE_MAX|PTYPE_TYPE); + predefined_ctype("INT_LEAST64", int64_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH); + predefined_ctype("UINT_LEAST64", uint64_ctype, PTYPE_MAX|PTYPE_TYPE); + + predefined_ctype("INT_FAST8", fast8_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH); + predefined_ctype("UINT_FAST8", ufast8_ctype, PTYPE_MAX|PTYPE_TYPE); + predefined_ctype("INT_FAST16", fast16_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH); + predefined_ctype("UINT_FAST16",ufast16_ctype, PTYPE_MAX|PTYPE_TYPE); + predefined_ctype("INT_FAST32", fast32_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH); + predefined_ctype("UINT_FAST32",ufast32_ctype, PTYPE_MAX|PTYPE_TYPE); + predefined_ctype("INT_FAST64", fast64_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH); + predefined_ctype("UINT_FAST64",ufast64_ctype, PTYPE_MAX|PTYPE_TYPE); + predefined_ctype("INTMAX", intmax_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH); predefined_ctype("UINTMAX", uintmax_ctype, PTYPE_MAX|PTYPE_TYPE); - predefined_ctype("INTPTR", ssize_t_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH); - predefined_ctype("UINTPTR", size_t_ctype, PTYPE_MAX|PTYPE_TYPE); - predefined_ctype("PTRDIFF", ssize_t_ctype, PTYPE_ALL_T|PTYPE_TYPE); + predefined_ctype("INTPTR", intptr_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH); + predefined_ctype("UINTPTR", uintptr_ctype, PTYPE_MAX|PTYPE_TYPE); + predefined_ctype("PTRDIFF", ptrdiff_ctype, PTYPE_ALL_T|PTYPE_TYPE); predefined_ctype("SIZE", size_t_ctype, PTYPE_ALL_T|PTYPE_TYPE); predefined_ctype("POINTER", &ptr_ctype, PTYPE_SIZEOF); + predefined_ctype("SIG_ATOMIC", sig_atomic_ctype, PTYPE_MAX|PTYPE_MIN|PTYPE_TYPE|PTYPE_WIDTH); predefined_sizeof("FLOAT", "", bits_in_float); predefined_sizeof("DOUBLE", "", bits_in_double); @@ -210,16 +229,50 @@ void predefined_macros(void) if (arch_target->predefine) arch_target->predefine(arch_target); - if (arch_os >= OS_UNIX) { + if (arch_os >= OS_UNIX && arch_os != OS_DARWIN) { predefine("__unix__", 1, "1"); predefine("__unix", 1, "1"); predefine_nostd("unix"); } - if (arch_os == OS_SUNOS) { + switch (arch_os) { + case OS_CYGWIN: + predefine("__CYGWIN__", 1, "1"); + if (arch_m64 == ARCH_LP32) + predefine("__CYGWIN32__", 1, "1"); + add_pre_buffer("#define __cdecl __attribute__((__cdecl__))\n"); + add_pre_buffer("#define __declspec(x) __attribute__((x))\n"); + add_pre_buffer("#define __fastcall __attribute__((__fastcall__))\n"); + add_pre_buffer("#define __stdcall __attribute__((__stdcall__))\n"); + add_pre_buffer("#define __thiscall __attribute__((__thiscall__))\n"); + add_pre_buffer("#define _cdecl __attribute__((__cdecl__))\n"); + add_pre_buffer("#define _fastcall __attribute__((__fastcall__))\n"); + add_pre_buffer("#define _stdcall __attribute__((__stdcall__))\n"); + add_pre_buffer("#define _thiscall __attribute__((__thiscall__))\n"); + break; + case OS_DARWIN: + predefine("__APPLE__", 1, "1"); + predefine("__APPLE_CC__", 1, "1"); + predefine("__MACH__", 1, "1"); + break; + case OS_FREEBSD: + predefine("__FreeBSD__", 1, "1"); + break; + case OS_LINUX: + predefine("__linux__", 1, "1"); + predefine("__linux", 1, "1"); + break; + case OS_NETBSD: + predefine("__NetBSD__", 1, "1"); + break; + case OS_OPENBSD: + predefine("__OpenBSD__", 1, "1"); + break; + case OS_SUNOS: predefine("__sun__", 1, "1"); predefine("__sun", 1, "1"); predefine_nostd("sun"); predefine("__svr4__", 1, "1"); + break; } } @@ -464,6 +464,16 @@ Look for system headers in the multiarch subdirectory \fIdir\fR. The \fIdir\fR name would normally take the form of the target's normalized GNU triplet. (e.g. i386-linux-gnu). . +.TP +.B --os=\fIOS\fR +Specify the target Operating System. +This only makes a few differences with the predefined types. +The accepted values are: linux, unix, freebsd, netbsd, opensd, sunos, darwin +and cygwin. + +The default OS is the one of the machine used to build Sparse if it can be +detected, otherwise some generic settings are used. +. .SH DEBUG OPTIONS .TP .B \-fmem-report @@ -899,4 +899,11 @@ void init_ctype(void) char_ctype.ctype.modifiers |= MOD_UNSIGNED; char_ctype.ctype.modifiers &= ~MOD_SIGNED; } + + if (!ptrdiff_ctype) + ptrdiff_ctype = ssize_t_ctype; + if (!intptr_ctype) + intptr_ctype = ssize_t_ctype; + if (!uintptr_ctype) + uintptr_ctype = size_t_ctype; } @@ -304,9 +304,6 @@ extern struct symbol float128_ctype; extern struct symbol const_void_ctype, const_char_ctype; extern struct symbol const_ptr_ctype, const_string_ctype; -#define uintptr_ctype size_t_ctype -#define intptr_ctype ssize_t_ctype - /* Special internal symbols */ extern struct symbol zero_int; diff --git a/target-alpha.c b/target-alpha.c index 3f582997..4c622aec 100644 --- a/target-alpha.c +++ b/target-alpha.c @@ -24,6 +24,9 @@ static const struct builtin_fn builtins_alpha[] = { const struct target target_alpha = { .mach = MACH_ALPHA, .bitness = ARCH_LP64, + .has_int128 = 1, + + .bits_in_longdouble = 64, .predefine = predefine_alpha, .builtins = builtins_alpha, diff --git a/target-arm.c b/target-arm.c index 0d7c6134..104c319b 100644 --- a/target-arm.c +++ b/target-arm.c @@ -3,6 +3,21 @@ #include "machine.h" +static void init_arm(const struct target *self) +{ + fast16_ctype = &int_ctype; + ufast16_ctype = &uint_ctype; + fast32_ctype = &int_ctype; + ufast32_ctype = &uint_ctype; + + if (arch_os == OS_NONE) { + int32_ctype = &long_ctype; + uint32_ctype = &ulong_ctype; + fast8_ctype = &int_ctype; + ufast8_ctype = &uint_ctype; + } +} + static void predefine_arm(const struct target *self) { predefine("__arm__", 1, "1"); @@ -19,6 +34,11 @@ static void predefine_arm(const struct target *self) predefine("__ARM_PCS", 1, "1"); break; } + + if (arch_big_endian) + predefine("__ARMEB__", 0, "1"); + else + predefine("__ARMEL__", 0, "1"); } const struct target target_arm = { @@ -32,5 +52,6 @@ const struct target target_arm = { .bits_in_longdouble = 64, .max_fp_alignment = 8, + .init = init_arm, .predefine = predefine_arm, }; diff --git a/target-arm64.c b/target-arm64.c index 8619bd84..d92ab16b 100644 --- a/target-arm64.c +++ b/target-arm64.c @@ -20,6 +20,11 @@ static void predefine_arm64(const struct target *self) predefine("__aarch64__", 1, "1"); + if (arch_big_endian) + predefine("__AARCH64EB__", 0, "1"); + else + predefine("__AARCH64EL__", 0, "1"); + if (cmodel) predefine_strong("__AARCH64_CMODEL_%s__", cmodel); } diff --git a/target-h8300.c b/target-h8300.c new file mode 100644 index 00000000..c3652350 --- /dev/null +++ b/target-h8300.c @@ -0,0 +1,34 @@ +#include "symbol.h" +#include "target.h" +#include "machine.h" + + +static void init_h8300(const struct target *self) +{ + intptr_ctype = &int_ctype; + uintptr_ctype = &uint_ctype; + ssize_t_ctype = &long_ctype; + size_t_ctype = &ulong_ctype; + wchar_ctype = &ushort_ctype; + + fast16_ctype = &int_ctype; + ufast16_ctype = &uint_ctype; + fast32_ctype = &int_ctype; + ufast32_ctype = &uint_ctype; +} + +static void predefine_h8300(const struct target *self) +{ + predefine("__H8300H__", 1, "1"); +} + +const struct target target_h8300 = { + .mach = MACH_H8300, + .bitness = ARCH_LP32, + .big_endian = true, + + .bits_in_longdouble = 64, + + .init = init_h8300, + .predefine = predefine_h8300, +}; diff --git a/target-m68k.c b/target-m68k.c index ed4a9273..0aed2eb3 100644 --- a/target-m68k.c +++ b/target-m68k.c @@ -3,6 +3,14 @@ #include "machine.h" +static void init_m68k(const struct target *self) +{ + fast16_ctype = &int_ctype; + ufast16_ctype = &uint_ctype; + fast32_ctype = &int_ctype; + ufast32_ctype = &uint_ctype; +} + static void predefine_m68k(const struct target *self) { predefine("__m68k__", 1, "1"); @@ -19,5 +27,6 @@ const struct target target_m68k = { .bits_in_longdouble = 96, .max_fp_alignment = 4, + .init = init_m68k, .predefine = predefine_m68k, }; diff --git a/target-microblaze.c b/target-microblaze.c index 1fbeef3c..3a4c3d58 100644 --- a/target-microblaze.c +++ b/target-microblaze.c @@ -3,6 +3,14 @@ #include "machine.h" +static void init_microblaze(const struct target *self) +{ + fast16_ctype = &int_ctype; + ufast16_ctype = &uint_ctype; + fast32_ctype = &int_ctype; + ufast32_ctype = &uint_ctype; +} + static void predefine_microblaze(const struct target *self) { predefine("__MICROBLAZE__", 1, "1"); @@ -21,5 +29,6 @@ const struct target target_microblaze = { .bits_in_longdouble = 64, + .init = init_microblaze, .predefine = predefine_microblaze, }; diff --git a/target-mips.c b/target-mips.c index 3d73236f..1ff0760c 100644 --- a/target-mips.c +++ b/target-mips.c @@ -10,6 +10,16 @@ static void predefine_mips(const struct target *self) predefine("_MIPS_SZINT", 1, "%d", int_ctype.bit_size); predefine("_MIPS_SZLONG", 1, "%d", long_ctype.bit_size); predefine("_MIPS_SZPTR", 1, "%d", ptr_ctype.bit_size); + + if (arch_big_endian) { + predefine("_MIPSEB", 1, "1"); + predefine("__MIPSEB", 1, "1"); + predefine("__MIPSEB__", 1, "1"); + } else { + predefine("_MIPSEL", 1, "1"); + predefine("__MIPSEL", 1, "1"); + predefine("__MIPSEL__", 1, "1"); + } } diff --git a/target-nds32.c b/target-nds32.c new file mode 100644 index 00000000..e3ed2e52 --- /dev/null +++ b/target-nds32.c @@ -0,0 +1,33 @@ +#include "symbol.h" +#include "target.h" +#include "machine.h" + + +static void init_nds32(const struct target *self) +{ + fast16_ctype = &int_ctype; + ufast16_ctype = &uint_ctype; + fast32_ctype = &int_ctype; + ufast32_ctype = &uint_ctype; + + wchar_ctype = &uint_ctype; +} + +static void predefine_nds32(const struct target *self) +{ + predefine("__NDS32__", 1, "1"); + predefine("__nds32__", 1, "1"); + + predefine_weak("__NDS32_E%c__", arch_big_endian ? 'B' : 'L'); +} + +const struct target target_nds32 = { + .mach = MACH_NDS32, + .bitness = ARCH_LP32, + .big_endian = false, + + .bits_in_longdouble = 64, + + .init = init_nds32, + .predefine = predefine_nds32, +}; diff --git a/target-nios2.c b/target-nios2.c index 05f0926e..c57b1719 100644 --- a/target-nios2.c +++ b/target-nios2.c @@ -4,15 +4,28 @@ #include "builtin.h" +static void init_nios2(const struct target *self) +{ + fast16_ctype = &int_ctype; + ufast16_ctype = &uint_ctype; + fast32_ctype = &int_ctype; + ufast32_ctype = &uint_ctype; +} + static void predefine_nios2(const struct target *self) { + predefine("__NIOS2", 1, "1"); predefine("__NIOS2__", 1, "1"); + predefine("__nios2", 1, "1"); predefine("__nios2__", 1, "1"); - if (arch_big_endian) + if (arch_big_endian) { + predefine("__nios2_big_endian", 1, "1"); predefine("__nios2_big_endian__", 1, "1"); - else + } else { + predefine("__nios2_little_endian", 1, "1"); predefine("__nios2_little_endian__", 1, "1"); + } } static const struct builtin_fn builtins_nios2[] = { @@ -26,6 +39,9 @@ const struct target target_nios2 = { .mach = MACH_NIOS2, .bitness = ARCH_LP32, + .bits_in_longdouble = 64, + + .init = init_nios2, .predefine = predefine_nios2, .builtins = builtins_nios2, }; diff --git a/target-openrisc.c b/target-openrisc.c new file mode 100644 index 00000000..ad25ff27 --- /dev/null +++ b/target-openrisc.c @@ -0,0 +1,31 @@ +#include "symbol.h" +#include "target.h" +#include "machine.h" + + +static void init_openrisc(const struct target *self) +{ + fast16_ctype = &int_ctype; + ufast16_ctype = &uint_ctype; + fast32_ctype = &int_ctype; + ufast32_ctype = &uint_ctype; + + wchar_ctype = &uint_ctype; +} + +static void predefine_openrisc(const struct target *self) +{ + predefine_weak("__OR1K__"); + predefine_weak("__or1k__"); +} + +const struct target target_openrisc = { + .mach = MACH_NDS32, + .bitness = ARCH_LP32, + .big_endian = true, + + .bits_in_longdouble = 64, + + .init = init_openrisc, + .predefine = predefine_openrisc, +}; diff --git a/target-ppc.c b/target-ppc.c index c0d6068f..6c0c0737 100644 --- a/target-ppc.c +++ b/target-ppc.c @@ -14,6 +14,10 @@ static void predefine_ppc(const struct target *self) predefine("_ARCH_PPC", 1, "1"); if (arch_big_endian) predefine("_BIG_ENDIAN", 1, "1"); + if (ldouble_ctype.bit_size == 128) { + predefine("__LONGDOUBLE128", 1, "1"); + predefine("__LONG_DOUBLE_128__", 1, "1"); + } } static const char *asm_constraint_ppc(struct asm_operand *op, int c, const char *str) @@ -27,6 +31,14 @@ static const char *asm_constraint_ppc(struct asm_operand *op, int c, const char } +static void init_ppc32(const struct target *self) +{ + fast16_ctype = &int_ctype; + ufast16_ctype = &uint_ctype; + fast32_ctype = &int_ctype; + ufast32_ctype = &uint_ctype; +} + static void predefine_ppc32(const struct target *self) { predefine_ppc(self); @@ -42,6 +54,7 @@ const struct target target_ppc32 = { .target_64bit = &target_ppc64, + .init = init_ppc32, .predefine = predefine_ppc32, .asm_constraint = asm_constraint_ppc, }; diff --git a/target-riscv.c b/target-riscv.c index d68fb585..6d9113c1 100644 --- a/target-riscv.c +++ b/target-riscv.c @@ -1,7 +1,80 @@ +#include "lib.h" #include "symbol.h" #include "target.h" #include "machine.h" +#include <string.h> +#define RISCV_32BIT (1 << 0) +#define RISCV_64BIT (1 << 1) +#define RISCV_MUL (1 << 2) +#define RISCV_DIV (1 << 3) +#define RISCV_ATOMIC (1 << 4) +#define RISCV_FLOAT (1 << 5) +#define RISCV_DOUBLE (1 << 6) +#define RISCV_FDIV (1 << 7) +#define RISCV_COMP (1 << 8) +#define RISCV_EMBD (1 << 9) +#define RISCV_FPU (RISCV_FLOAT|RISCV_DOUBLE|RISCV_FDIV) +#define RISCV_GENERIC (RISCV_MUL|RISCV_DIV|RISCV_ATOMIC|RISCV_FPU) + +static unsigned int riscv_flags; + +static void parse_march_riscv(const char *arg) +{ + static struct { + const char *pattern; + unsigned int flags; + } basic_sets[] = { + { "rv32i", RISCV_32BIT }, + { "rv32e", RISCV_32BIT|RISCV_EMBD }, + { "rv32g", RISCV_32BIT|RISCV_GENERIC }, + { "rv64i", RISCV_64BIT }, + { "rv64g", RISCV_64BIT|RISCV_GENERIC }, + }, extensions[] = { + { "m", RISCV_MUL|RISCV_DIV }, + { "a", RISCV_ATOMIC }, + { "f", RISCV_FLOAT|RISCV_FDIV }, + { "d", RISCV_DOUBLE|RISCV_FDIV }, + { "g", RISCV_GENERIC }, + { "q", 0 }, + { "l", 0 }, + { "c", RISCV_COMP }, + { "b", 0 }, + { "j", 0 }, + { "t", 0 }, + { "p", 0 }, + { "v", 0 }, + { "n", 0 }, + { "h", 0 }, + { "s", 0 }, + }; + int i; + + for (i = 0; i < ARRAY_SIZE(basic_sets); i++) { + const char *pat = basic_sets[i].pattern; + size_t len = strlen(pat); + + if (!strncmp(arg, pat, len)) { + riscv_flags |= basic_sets[i].flags; + arg += len; + goto ext; + } + } + die("invalid argument to '-march': '%s'\n", arg); + +ext: + for (i = 0; i < ARRAY_SIZE(extensions); i++) { + const char *pat = extensions[i].pattern; + size_t len = strlen(pat); + + if (!strncmp(arg, pat, len)) { + riscv_flags |= extensions[i].flags; + arg += len; + } + } + if (arg[0]) + die("invalid argument to '-march': '%s'\n", arg); +} static void init_riscv(const struct target *self) { @@ -9,6 +82,19 @@ static void init_riscv(const struct target *self) arch_cmodel = CMODEL_MEDLOW; if (fpic) arch_cmodel = CMODEL_PIC; + + if (riscv_flags == 0) + riscv_flags = self->flags; +} + +static void init_riscv32(const struct target *self) +{ + fast16_ctype = &int_ctype; + ufast16_ctype = &uint_ctype; + fast32_ctype = &int_ctype; + ufast32_ctype = &uint_ctype; + + init_riscv(self); } static void predefine_riscv(const struct target *self) @@ -23,6 +109,25 @@ static void predefine_riscv(const struct target *self) predefine("__riscv", 1, "1"); predefine("__riscv_xlen", 1, "%d", ptr_ctype.bit_size); + if (riscv_flags & RISCV_ATOMIC) + predefine("__riscv_atomic", 1, "1"); + if (riscv_flags & RISCV_COMP) + predefine("__riscv_compressed", 1, "1"); + if (riscv_flags & RISCV_DIV) + predefine("__riscv_div", 1, "1"); + if (riscv_flags & RISCV_EMBD) + predefine("__riscv_32e", 1, "1"); + if (riscv_flags & RISCV_FPU) + predefine("__riscv_flen", 1, "%d", (riscv_flags & RISCV_DOUBLE) ? 64 : 32); + if (riscv_flags & RISCV_FDIV) + predefine("__riscv_fdiv", 1, "1"); + if (riscv_flags & RISCV_FDIV) + predefine("__riscv_fsqrt", 1, "1"); + if (riscv_flags & RISCV_MUL) + predefine("__riscv_mul", 1, "1"); + if ((riscv_flags & RISCV_MUL) && (riscv_flags & RISCV_DIV)) + predefine("__riscv_muldiv", 1, "1"); + if (cmodel) predefine_strong("__riscv_cmodel_%s", cmodel); } @@ -32,11 +137,13 @@ const struct target target_riscv32 = { .bitness = ARCH_LP32, .big_endian = 0, .unsigned_char = 1, + .flags = RISCV_32BIT|RISCV_GENERIC|RISCV_COMP, .target_64bit = &target_riscv64, - .init = init_riscv, + .init = init_riscv32, .predefine = predefine_riscv, + .parse_march = parse_march_riscv, }; const struct target target_riscv64 = { @@ -45,9 +152,11 @@ const struct target target_riscv64 = { .big_endian = 0, .unsigned_char = 1, .has_int128 = 1, + .flags = RISCV_64BIT|RISCV_GENERIC|RISCV_COMP, .target_32bit = &target_riscv32, .init = init_riscv, .predefine = predefine_riscv, + .parse_march = parse_march_riscv, }; diff --git a/target-s390.c b/target-s390.c index 9dbc810e..84889c0a 100644 --- a/target-s390.c +++ b/target-s390.c @@ -4,6 +4,17 @@ #include "expression.h" +static void init_s390(const struct target *self) +{ + intptr_ctype = &int_ctype; + uintptr_ctype = &uint_ctype; + + fast16_ctype = &int_ctype; + ufast16_ctype = &uint_ctype; + fast32_ctype = &int_ctype; + ufast32_ctype = &uint_ctype; +} + static void predefine_s390(const struct target *self) { predefine("__s390__", 1, "1"); @@ -31,6 +42,7 @@ const struct target target_s390 = { .target_64bit = &target_s390x, + .init = init_s390, .predefine = predefine_s390, .asm_constraint = asm_constraint_s390, }; diff --git a/target-sh.c b/target-sh.c new file mode 100644 index 00000000..d3a66180 --- /dev/null +++ b/target-sh.c @@ -0,0 +1,36 @@ +#include "symbol.h" +#include "target.h" +#include "machine.h" + + +static void init_sh(const struct target *self) +{ + int64_ctype = &llong_ctype; + uint64_ctype = &ullong_ctype; + intptr_ctype = &int_ctype; + uintptr_ctype = &uint_ctype; + + fast16_ctype = &int_ctype; + ufast16_ctype = &uint_ctype; + fast32_ctype = &int_ctype; + ufast32_ctype = &uint_ctype; + + wchar_ctype = &long_ctype; +} + +static void predefine_sh(const struct target *self) +{ + predefine_weak("__SH4__"); + predefine_weak("__sh__"); +} + +const struct target target_sh = { + .mach = MACH_SH, + .bitness = ARCH_LP32, + .big_endian = false, + + .bits_in_longdouble = 64, + + .init = init_sh, + .predefine = predefine_sh, +}; diff --git a/target-sparc.c b/target-sparc.c index bd48effe..d830f6cb 100644 --- a/target-sparc.c +++ b/target-sparc.c @@ -3,22 +3,38 @@ #include "machine.h" +static int sparc_version; + static void predefine_sparc(const struct target *self) { predefine("__sparc__", 1, "1"); predefine("__sparc", 1, "1"); predefine_nostd("sparc"); + + predefine_weak("__sparc_v%d__", sparc_version); + predefine_weak("__sparcv%d__", sparc_version); + predefine_weak("__sparcv%d", sparc_version); } static void init_sparc32(const struct target *target) { + fast16_ctype = &int_ctype; + ufast16_ctype = &uint_ctype; + fast32_ctype = &int_ctype; + ufast32_ctype = &uint_ctype; + + if (!sparc_version) + sparc_version = 8; + if (arch_os == OS_SUNOS) { wint_ctype = &long_ctype; wchar_ctype = &long_ctype; bits_in_longdouble = 128; max_fp_alignment = 16; + + funsigned_char = 0; } } @@ -43,11 +59,14 @@ const struct target target_sparc32 = { }; +static void init_sparc64(const struct target *target) +{ + if (!sparc_version) + sparc_version = 9; +} + static void predefine_sparc64(const struct target *self) { - predefine("__sparc_v9__", 1, "1"); - predefine("__sparcv9__", 1, "1"); - predefine("__sparcv9", 1, "1"); predefine("__sparc64__", 1, "1"); predefine("__arch64__", 1, "1"); @@ -63,5 +82,6 @@ const struct target target_sparc64 = { .target_32bit = &target_sparc32, + .init = init_sparc64, .predefine = predefine_sparc64, }; diff --git a/target-x86.c b/target-x86.c index d770349c..b7ff8f2a 100644 --- a/target-x86.c +++ b/target-x86.c @@ -3,33 +3,51 @@ #include "machine.h" -static void init_x86(const struct target *target) +static void predefine_i386(const struct target *self) +{ + predefine("__i386__", 1, "1"); + predefine("__i386", 1, "1"); + predefine_nostd("i386"); +} + +static void predefine_x86_64(const struct target *self) +{ + predefine("__x86_64__", 1, "1"); + predefine("__x86_64", 1, "1"); + predefine("__amd64__", 1, "1"); + predefine("__amd64", 1, "1"); +} + + +static void init_x86_common(const struct target *target) { switch (arch_os) { case OS_CYGWIN: wchar_ctype = &ushort_ctype; break; - case OS_DARWIN: - int64_ctype = &llong_ctype; - uint64_ctype = &ullong_ctype; - wint_ctype = &int_ctype; - break; case OS_FREEBSD: wint_ctype = &int_ctype; break; case OS_OPENBSD: + size_t_ctype = &ulong_ctype; + ssize_t_ctype = &long_ctype; wchar_ctype = &int_ctype; wint_ctype = &int_ctype; + fast16_ctype = &short_ctype; + ufast16_ctype = &ushort_ctype; break; } } -static void predefine_i386(const struct target *self) +static void init_i386(const struct target *target) { - predefine("__i386__", 1, "1"); - predefine("__i386", 1, "1"); - predefine_nostd("i386"); + fast16_ctype = &int_ctype; + ufast16_ctype = &uint_ctype; + fast32_ctype = &int_ctype; + ufast32_ctype = &uint_ctype; + + init_x86_common(target); } const struct target target_i386 = { @@ -42,19 +60,88 @@ const struct target target_i386 = { .bits_in_longdouble = 96, .max_fp_alignment = 4, - .init = init_x86, .target_64bit = &target_x86_64, + .init = init_i386, .predefine = predefine_i386, }; -static void predefine_x86_64(const struct target *self) +static void init_x86_x32(const struct target *target) { - predefine("__x86_64__", 1, "1"); - predefine("__x86_64", 1, "1"); - predefine("__amd64__", 1, "1"); - predefine("__amd64", 1, "1"); + init_x86_common(target); + + max_int_alignment = 8; + + fast16_ctype = &int_ctype; + ufast16_ctype = &uint_ctype; + fast32_ctype = &int_ctype; + ufast32_ctype = &uint_ctype; + wchar_ctype = &long_ctype; +} + +static const struct target target_x86_x32 = { + .mach = MACH_X86_64, + .bitness = ARCH_X32, + .big_endian = 0, + .unsigned_char = 0, + .has_int128 = 1, + + .bits_in_longdouble = 128, + .max_fp_alignment = 16, + + .target_32bit = &target_i386, + .target_64bit = &target_x86_64, + + .init = init_x86_x32, + .predefine = predefine_x86_64, +}; + + +static void init_x86_64(const struct target *target) +{ + init_x86_common(target); + + switch (arch_os) { + case OS_CYGWIN: + break; + case OS_DARWIN: + int64_ctype = &llong_ctype; + uint64_ctype = &ullong_ctype; + wint_ctype = &int_ctype; + fast16_ctype = &short_ctype; + ufast16_ctype = &ushort_ctype; + fast32_ctype = &int_ctype; + ufast32_ctype = &uint_ctype; + fast64_ctype = &llong_ctype; + ufast64_ctype = &ullong_ctype; + break; + case OS_FREEBSD: + fast16_ctype = &short_ctype; + ufast16_ctype = &ushort_ctype; + fast32_ctype = &int_ctype; + ufast32_ctype = &uint_ctype; + break; + case OS_NETBSD: + fast8_ctype = &int_ctype; + ufast8_ctype = &uint_ctype; + fast16_ctype = &int_ctype; + ufast16_ctype = &uint_ctype; + fast32_ctype = &int_ctype; + ufast32_ctype = &uint_ctype; + wint_ctype = &int_ctype; + break; + case OS_OPENBSD: + fast32_ctype = &int_ctype; + ufast32_ctype = &uint_ctype; + int64_ctype = &llong_ctype; + uint64_ctype = &ullong_ctype; + intmax_ctype = &llong_ctype; + uintmax_ctype = &ullong_ctype; + least64_ctype = &long_ctype; + uleast64_ctype = &ulong_ctype; + break; + } } const struct target target_x86_64 = { @@ -67,8 +154,9 @@ const struct target target_x86_64 = { .bits_in_longdouble = 128, .max_fp_alignment = 16, - .init = init_x86, .target_32bit = &target_i386, + .target_x32bit = &target_x86_x32, + .init = init_x86_64, .predefine = predefine_x86_64, }; diff --git a/target-xtensa.c b/target-xtensa.c new file mode 100644 index 00000000..26bda47f --- /dev/null +++ b/target-xtensa.c @@ -0,0 +1,36 @@ +#include "symbol.h" +#include "target.h" +#include "machine.h" + + +static void init_xtensa(const struct target *self) +{ + fast16_ctype = &int_ctype; + ufast16_ctype = &uint_ctype; + fast32_ctype = &int_ctype; + ufast32_ctype = &uint_ctype; + + wchar_ctype = &long_ctype; +} + +static void predefine_xtensa(const struct target *self) +{ + predefine("__XTENSA__", 1, "1"); + predefine("__xtensa__", 1, "1"); + + if (arch_big_endian) + predefine("__XTENSA_EB__", 1, "1"); + else + predefine("__XTENSA_EL__", 1, "1"); +} + +const struct target target_xtensa = { + .mach = MACH_XTENSA, + .bitness = ARCH_LP32, + .big_endian = true, + + .bits_in_longdouble = 64, + + .init = init_xtensa, + .predefine = predefine_xtensa, +}; @@ -5,6 +5,9 @@ #include "target.h" #include "machine.h" +struct symbol *ptrdiff_ctype; +struct symbol *intptr_ctype; +struct symbol *uintptr_ctype; struct symbol *size_t_ctype = &ulong_ctype; struct symbol *ssize_t_ctype = &long_ctype; struct symbol *intmax_ctype = &long_ctype; @@ -15,6 +18,23 @@ struct symbol *int32_ctype = &int_ctype; struct symbol *uint32_ctype = &uint_ctype; struct symbol *wchar_ctype = &int_ctype; struct symbol *wint_ctype = &uint_ctype; +struct symbol *least8_ctype = &schar_ctype; +struct symbol *uleast8_ctype = &uchar_ctype; +struct symbol *least16_ctype = &short_ctype; +struct symbol *uleast16_ctype = &ushort_ctype; +struct symbol *least32_ctype = &int_ctype; +struct symbol *uleast32_ctype = &uint_ctype; +struct symbol *least64_ctype = &llong_ctype; +struct symbol *uleast64_ctype = &ullong_ctype; +struct symbol *fast8_ctype = &schar_ctype; +struct symbol *ufast8_ctype = &uchar_ctype; +struct symbol *fast16_ctype = &long_ctype; +struct symbol *ufast16_ctype = &ulong_ctype; +struct symbol *fast32_ctype = &long_ctype; +struct symbol *ufast32_ctype = &ulong_ctype; +struct symbol *fast64_ctype = &long_ctype; +struct symbol *ufast64_ctype = &ulong_ctype; +struct symbol *sig_atomic_ctype = &int_ctype; /* * For "__attribute__((aligned))" @@ -60,22 +80,27 @@ static const struct target *targets[] = { [MACH_ALPHA] = &target_alpha, [MACH_ARM] = &target_arm, [MACH_ARM64] = &target_arm64, - [MACH_I386] = &target_i386, [MACH_BFIN] = &target_bfin, - [MACH_X86_64] = &target_x86_64, + [MACH_H8300] = &target_h8300, + [MACH_I386] = &target_i386, + [MACH_M68K] = &target_m68k, [MACH_MICROBLAZE] = &target_microblaze, [MACH_MIPS32] = &target_mips32, [MACH_MIPS64] = &target_mips64, + [MACH_NDS32] = &target_nds32, [MACH_NIOS2] = &target_nios2, + [MACH_OPENRISC] = &target_openrisc, [MACH_PPC32] = &target_ppc32, [MACH_PPC64] = &target_ppc64, [MACH_RISCV32] = &target_riscv32, [MACH_RISCV64] = &target_riscv64, [MACH_S390] = &target_s390, [MACH_S390X] = &target_s390x, + [MACH_SH] = &target_sh, [MACH_SPARC32] = &target_sparc32, [MACH_SPARC64] = &target_sparc64, - [MACH_M68K] = &target_m68k, + [MACH_X86_64] = &target_x86_64, + [MACH_XTENSA] = &target_xtensa, [MACH_UNKNOWN] = &target_default, }; const struct target *arch_target = &target_default; @@ -91,12 +116,15 @@ enum machine target_parse(const char *name) { "aarch64", MACH_ARM64, 64, }, { "arm64", MACH_ARM64, 64, }, { "arm", MACH_ARM, 32, }, - { "i386", MACH_I386, 32, }, { "bfin", MACH_BFIN, 32, }, + { "h8300", MACH_H8300, 32, }, + { "i386", MACH_I386, 32, }, { "m68k", MACH_M68K, 32, }, { "microblaze", MACH_MICROBLAZE,32, }, { "mips", MACH_MIPS32, 0, }, + { "nds32", MACH_NDS32, 32, }, { "nios2", MACH_NIOS2, 32, }, + { "openrisc", MACH_OPENRISC, 32, }, { "powerpc", MACH_PPC32, 0, }, { "ppc", MACH_PPC32, 0, }, { "riscv", MACH_RISCV32, 0, }, @@ -105,6 +133,8 @@ enum machine target_parse(const char *name) { "sparc", MACH_SPARC32, 0, }, { "x86_64", MACH_X86_64, 64, }, { "x86-64", MACH_X86_64, 64, }, + { "sh", MACH_SH, 32, }, + { "xtensa", MACH_XTENSA, 32, }, { NULL }, }; const struct arch *p; @@ -136,6 +166,35 @@ enum machine target_parse(const char *name) return MACH_UNKNOWN; } +void target_os(const char *name) +{ + static const struct os { + const char *name; + int os; + } oses[] = { + { "cygwin", OS_CYGWIN }, + { "darwin", OS_DARWIN }, + { "freebsd", OS_FREEBSD }, + { "linux", OS_LINUX }, + { "native", OS_NATIVE, }, + { "netbsd", OS_NETBSD }, + { "none", OS_NONE }, + { "openbsd", OS_OPENBSD }, + { "sunos", OS_SUNOS }, + { "unix", OS_UNIX }, + { NULL }, + }, *p; + + for (p = &oses[0]; p->name; p++) { + if (!strcmp(p->name, name)) { + arch_os = p->os; + return; + } + } + + die("invalid os: %s", name); +} + void target_config(enum machine mach) { @@ -154,10 +213,17 @@ void target_init(void) const struct target *target = arch_target; switch (arch_m64) { + case ARCH_X32: + if (target->target_x32bit) + target = target->target_x32bit; + goto case_32bit; + case ARCH_LP32: max_int_alignment = 4; + if (target->target_32bit) + target = target->target_32bit; /* fallthrough */ - case ARCH_X32: + case_32bit: bits_in_long = 32; bits_in_pointer = 32; pointer_alignment = 4; @@ -167,8 +233,8 @@ void target_init(void) uint64_ctype = &ullong_ctype; intmax_ctype = &llong_ctype; uintmax_ctype = &ullong_ctype; - if (target->target_32bit) - target = target->target_32bit; + fast64_ctype = &llong_ctype; + ufast64_ctype = &ullong_ctype; break; case ARCH_LLP64: @@ -5,6 +5,9 @@ extern struct symbol *size_t_ctype; extern struct symbol *ssize_t_ctype; +extern struct symbol *ptrdiff_ctype; +extern struct symbol *intptr_ctype; +extern struct symbol *uintptr_ctype; extern struct symbol *intmax_ctype; extern struct symbol *uintmax_ctype; extern struct symbol *int64_ctype; @@ -13,6 +16,23 @@ extern struct symbol *int32_ctype; extern struct symbol *uint32_ctype; extern struct symbol *wchar_ctype; extern struct symbol *wint_ctype; +extern struct symbol *least8_ctype; +extern struct symbol *uleast8_ctype; +extern struct symbol *least16_ctype; +extern struct symbol *uleast16_ctype; +extern struct symbol *least32_ctype; +extern struct symbol *uleast32_ctype; +extern struct symbol *least64_ctype; +extern struct symbol *uleast64_ctype; +extern struct symbol *fast8_ctype; +extern struct symbol *ufast8_ctype; +extern struct symbol *fast16_ctype; +extern struct symbol *ufast16_ctype; +extern struct symbol *fast32_ctype; +extern struct symbol *ufast32_ctype; +extern struct symbol *fast64_ctype; +extern struct symbol *ufast64_ctype; +extern struct symbol *sig_atomic_ctype; /* * For "__attribute__((aligned))" @@ -63,6 +83,7 @@ struct target { unsigned int unsigned_char:1; unsigned int size_t_long:1; unsigned int has_int128:1; + unsigned long flags; struct symbol *wchar; struct symbol *wint; @@ -71,11 +92,13 @@ struct target { unsigned int max_fp_alignment; const struct target *target_32bit; + const struct target *target_x32bit; const struct target *target_64bit; const struct builtin_fn *builtins; void (*init)(const struct target *self); + void (*parse_march)(const char *arg); void (*predefine)(const struct target *self); const char *(*asm_constraint)(struct asm_operand *op, int c, const char *str); }; @@ -85,26 +108,32 @@ extern const struct target target_alpha; extern const struct target target_arm; extern const struct target target_arm64; extern const struct target target_bfin; +extern const struct target target_h8300; extern const struct target target_m68k; extern const struct target target_microblaze; extern const struct target target_mips32; extern const struct target target_mips64; +extern const struct target target_nds32; extern const struct target target_nios2; +extern const struct target target_openrisc; extern const struct target target_ppc32; extern const struct target target_ppc64; extern const struct target target_riscv32; extern const struct target target_riscv64; extern const struct target target_s390; extern const struct target target_s390x; +extern const struct target target_sh; extern const struct target target_sparc32; extern const struct target target_sparc64; extern const struct target target_i386; extern const struct target target_x86_64; +extern const struct target target_xtensa; /* target.c */ extern const struct target *arch_target; enum machine target_parse(const char *name); +void target_os(const char *name); void target_config(enum machine mach); void target_init(void); diff --git a/validation/eval/array-quals-node.c b/validation/eval/array-quals-node.c new file mode 100644 index 00000000..99a4db13 --- /dev/null +++ b/validation/eval/array-quals-node.c @@ -0,0 +1,29 @@ +struct s { + int a; + int b[3]; + int c[2][3]; +}; + +struct c { + const struct s s; +}; + +extern struct c v; + +void f(void) +{ + v.s.a = 0; + *v.s.b = 0; + **v.s.c = 0; +} + +/* + * check-name: array-quals-node + * check-known-to-fail + * + * check-error-start +eval/array-quals-node.c:15:14: error: assignment to const expression +eval/array-quals-node.c:16:14: error: assignment to const expression +eval/array-quals-node.c:17:14: error: assignment to const expression + * check-error-end + */ diff --git a/validation/eval/array-quals0.c b/validation/eval/array-quals0.c new file mode 100644 index 00000000..30727490 --- /dev/null +++ b/validation/eval/array-quals0.c @@ -0,0 +1,6 @@ +static int a[2][3]; +static const int (*p)[3] = a; + +/* + * check-name: array-quals0 + */ diff --git a/validation/eval/array-quals1.c b/validation/eval/array-quals1.c new file mode 100644 index 00000000..d3e54f3e --- /dev/null +++ b/validation/eval/array-quals1.c @@ -0,0 +1,49 @@ +typedef const int ci_t; +typedef int ia_t[2]; +typedef const int cia_t[2]; + +static const int ci__a[2]; +static ci_t cit_a[2]; +static const ia_t c_iat; +static cia_t ciat_; +static cia_t ciata[2]; + +static const void *const ok_ci__a = &ci__a; +static void *const ko_ci__a = &ci__a; +static const void *const ok_cit_a = &cit_a; +static void *const ko_cit_a = &cit_a; +static const void *const ok_c_iat = &c_iat; +static void *const ko_c_iat = &c_iat; +static const void *const ok_ciat_ = &ciat_; +static void *const ko_ciat_ = &ciat_; +static const void *const ok_ciata = &ciata; +static void *const ko_ciata = &ciata; + +static volatile int vi__a[2]; +static volatile void *const ok_vi__a = &vi__a; +static void *const ko_vi__a = &vi__a; + +/* + * check-name: array-quals1 + * + * check-error-start +eval/array-quals1.c:12:38: warning: incorrect type in initializer (different modifiers) +eval/array-quals1.c:12:38: expected void *static const [toplevel] ko_ci__a +eval/array-quals1.c:12:38: got int const ( * )[2] +eval/array-quals1.c:14:38: warning: incorrect type in initializer (different modifiers) +eval/array-quals1.c:14:38: expected void *static const [toplevel] ko_cit_a +eval/array-quals1.c:14:38: got int const [usertype] ( * )[2] +eval/array-quals1.c:16:38: warning: incorrect type in initializer (different modifiers) +eval/array-quals1.c:16:38: expected void *static const [toplevel] ko_c_iat +eval/array-quals1.c:16:38: got int const ( * )[2] +eval/array-quals1.c:18:38: warning: incorrect type in initializer (different modifiers) +eval/array-quals1.c:18:38: expected void *static const [toplevel] ko_ciat_ +eval/array-quals1.c:18:38: got int const ( * )[2] +eval/array-quals1.c:20:38: warning: incorrect type in initializer (different modifiers) +eval/array-quals1.c:20:38: expected void *static const [toplevel] ko_ciata +eval/array-quals1.c:20:38: got int const [usertype] ( * )[2][2] +eval/array-quals1.c:24:41: warning: incorrect type in initializer (different modifiers) +eval/array-quals1.c:24:41: expected void *static const [toplevel] ko_vi__a +eval/array-quals1.c:24:41: got int volatile ( * )[2] + * check-error-end + */ diff --git a/validation/linear/bug-assign-op0.c b/validation/linear/bug-assign-op0.c new file mode 100644 index 00000000..0cabc622 --- /dev/null +++ b/validation/linear/bug-assign-op0.c @@ -0,0 +1,115 @@ +int asr(int s) +{ + s >>= 11U; + return s; +} + +unsigned int lsr(unsigned int u) +{ + u >>= 11; + return u; +} + +int divr(int s, unsigned long u) +{ + extern int use(int, unsigned); + int t = s; + s = s / u; + u = u / t; + return use(s, u); +} + +int sdivul(int s, unsigned long u) +{ + s /= u; // divu + return s; +} + +unsigned int udivsl(unsigned int u, long s) +{ + u /= s; // divs + return u; +} + +int uldivs(int s, unsigned long u) +{ + u /= s; // divu + return u; +} + +unsigned int sldivu(unsigned int u, long s) +{ + s /= u; // divs + return s; +} + +/* + * check-name: bug-assign-op0 + * check-command: test-linearize -Wno-decl $file + * check-known-to-fail + * + * check-output-start +asr: +.L0: + <entry-point> + asr.32 %r2 <- %arg1, $11 + ret.32 %r2 + + +lsr: +.L2: + <entry-point> + lsr.32 %r6 <- %arg1, $11 + ret.32 %r6 + + +divr: +.L4: + <entry-point> + sext.64 %r11 <- (32) %arg1 + divu.64 %r13 <- %r11, %arg2 + trunc.32 %r14 <- (64) %r13 + divu.64 %r18 <- %arg2, %r11 + trunc.32 %r21 <- (64) %r18 + call.32 %r22 <- use, %r14, %r21 + ret.32 %r22 + + +sdivul: +.L6: + <entry-point> + sext.64 %r26 <- (32) %arg1 + divu.64 %r27 <- %r26, %arg2 + trunc.32 %r28 <- (64) %r27 + ret.32 %r28 + + +udivsl: +.L8: + <entry-point> + zext.64 %r33 <- (32) %arg1 + divs.64 %r34 <- %r33, %arg2 + trunc.32 %r35 <- (64) %r34 + ret.32 %r35 + + +uldivs: +.L10: + <entry-point> + sext.64 %r39 <- (32) %arg1 + divu.64 %r41 <- %arg2, %r39 + trunc.32 %r43 <- (64) %r41 + ret.32 %r43 + + +sldivu: +.L12: + <entry-point> + zext.64 %r46 <- (32) %arg1 + divs.64 %r48 <- %arg2, %r46 + trunc.32 %r50 <- (64) %r48 + ret.32 %r50 + + + * check-output-end + */ diff --git a/validation/static_assert.c b/validation/static_assert.c index dd5e0c08..0ab5844e 100644 --- a/validation/static_assert.c +++ b/validation/static_assert.c @@ -53,6 +53,10 @@ _Static_assert(1, ); _Static_assert(, ""); _Static_assert(,); +// C2x's version: without message +_Static_assert(1); +_Static_assert(0); + /* * check-name: static assertion * @@ -67,5 +71,6 @@ static_assert.c:52:19: error: string literal expected for _Static_assert() static_assert.c:53:16: error: Expected constant expression static_assert.c:54:16: error: Expected constant expression static_assert.c:54:17: error: string literal expected for _Static_assert() +static_assert.c:58:16: error: static assertion failed * check-error-end */ |