X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=fdb9ee0a896627df2d66d18215eb9671f243d930;hb=f109471af0f1a95e840a66c9e136409d0973021c;hp=c5eddfcb354e14306e7548c5c4447a4a21e609fd;hpb=e719b76791b19aaf3264cc8505172c655bff22b4;p=cparser diff --git a/parser.c b/parser.c index c5eddfc..fdb9ee0 100644 --- a/parser.c +++ b/parser.c @@ -98,14 +98,6 @@ typedef struct parse_initializer_env_t { bool must_be_constant; } parse_initializer_env_t; -/** - * Capture a MS __base extension. - */ -typedef struct based_spec_t { - source_position_t source_position; - variable_t *base_variable; -} based_spec_t; - typedef entity_t* (*parsed_declaration_func) (entity_t *declaration, bool is_definition); /** The current token. */ @@ -539,6 +531,14 @@ static type_t *allocate_type_zero(type_kind_t kind) return res; } +static function_parameter_t *allocate_parameter(type_t *const type) +{ + function_parameter_t *const param = obstack_alloc(type_obst, sizeof(*param)); + memset(param, 0, sizeof(*param)); + param->type = type; + return param; +} + /** * Returns the size of an initializer node. * @@ -1550,7 +1550,7 @@ static void check_no_argument(gnu_attribute_t *attribute, const char *name) errorf(HERE, "wrong number of arguments specified for '%s' attribute", name); eat_until_matching_token('('); /* we have already consumed '(', so we stop before ')', eat it */ - eat(')'); + next_token(); attribute->invalid = true; } @@ -1683,6 +1683,7 @@ static decl_modifiers_t parse_gnu_attribute(gnu_attribute_t **attributes) /* skip possible arguments */ if (token.type == '(') { eat_until_matching_token(')'); + next_token(); /* skip the ')' */ } } else { /* check for arguments */ @@ -3030,6 +3031,7 @@ static compound_t *parse_compound_type_specifier(bool is_struct) parse_compound_type_entries(compound); modifiers |= parse_attributes(&attributes); + /* ISO/IEC 14882:1998(E) §7.1.3:5 */ if (symbol == NULL) { assert(anonymous_entity == NULL); anonymous_entity = (entity_t*)compound; @@ -3144,6 +3146,7 @@ static type_t *parse_enum_specifier(void) parse_enum_entries(type); parse_attributes(&attributes); + /* ISO/IEC 14882:1998(E) §7.1.3:5 */ if (symbol == NULL) { assert(anonymous_entity == NULL); anonymous_entity = entity; @@ -3442,29 +3445,23 @@ static entity_t *create_error_entity(symbol_t *symbol, entity_kind_tag_t kind) return entity; } -static void parse_microsoft_based(based_spec_t *based_spec) +static variable_t *parse_microsoft_based(void) { if (token.type != T_IDENTIFIER) { parse_error_expected("while parsing __based", T_IDENTIFIER, NULL); - return; + return NULL; } symbol_t *symbol = token.v.symbol; entity_t *entity = get_entity(symbol, NAMESPACE_NORMAL); + variable_t *variable; if (entity == NULL || entity->base.kind != ENTITY_VARIABLE) { errorf(HERE, "'%Y' is not a variable name.", symbol); - entity = create_error_entity(symbol, ENTITY_VARIABLE); + variable = &create_error_entity(symbol, ENTITY_VARIABLE)->variable; } else { - variable_t *variable = &entity->variable; - - if (based_spec->base_variable != NULL) { - errorf(HERE, "__based type qualifier specified more than once"); - } - based_spec->source_position = token.source_position; - based_spec->base_variable = variable; + variable = &entity->variable; type_t *const type = variable->base.type; - if (is_type_valid(type)) { if (! is_type_pointer(skip_typeref(type))) { errorf(HERE, "variable in __based modifier must have pointer type instead of '%T'", type); @@ -3475,6 +3472,7 @@ static void parse_microsoft_based(based_spec_t *based_spec) } } next_token(); + return variable; } /** @@ -4164,9 +4162,27 @@ static void semantic_parameter_incomplete(const entity_t *entity) type_t *type = skip_typeref(entity->declaration.type); if (is_type_incomplete(type)) { errorf(&entity->base.source_position, - "parameter '%Y' has incomplete type '%T'", entity->base.symbol, - entity->declaration.type); + "parameter '%#T' has incomplete type", + entity->declaration.type, entity->base.symbol); + } +} + +static bool has_parameters(void) +{ + /* func(void) is not a parameter */ + if (token.type == T_IDENTIFIER) { + entity_t const *const entity = get_entity(token.v.symbol, NAMESPACE_NORMAL); + if (entity->kind != ENTITY_TYPEDEF) + return true; + if (skip_typeref(entity->typedefe.type) != type_void) + return true; + } else if (token.type != T_void) { + return true; } + if (look_ahead(1)->type != ')') + return true; + next_token(); + return false; } /** @@ -4197,61 +4213,49 @@ static void parse_parameters(function_type_t *type, scope_t *scope) goto parameters_finished; } - function_parameter_t *parameter; - function_parameter_t *last_parameter = NULL; + if (has_parameters()) { + function_parameter_t **anchor = &type->parameters; + for (;;) { + switch (token.type) { + case T_DOTDOTDOT: + next_token(); + type->variadic = true; + goto parameters_finished; - while (true) { - switch (token.type) { - case T_DOTDOTDOT: - next_token(); - type->variadic = true; - goto parameters_finished; + case T_IDENTIFIER: + case T___extension__: + DECLARATION_START + { + entity_t *entity = parse_parameter(); + if (entity->kind == ENTITY_TYPEDEF) { + errorf(&entity->base.source_position, + "typedef not allowed as function parameter"); + break; + } + assert(is_declaration(entity)); - case T_IDENTIFIER: - case T___extension__: - DECLARATION_START - { - entity_t *entity = parse_parameter(); - if (entity->kind == ENTITY_TYPEDEF) { - errorf(&entity->base.source_position, - "typedef not allowed as function parameter"); - break; - } - assert(is_declaration(entity)); + semantic_parameter_incomplete(entity); - /* func(void) is not a parameter */ - if (last_parameter == NULL - && token.type == ')' - && entity->base.symbol == NULL - && skip_typeref(entity->declaration.type) == type_void) { - goto parameters_finished; - } - semantic_parameter_incomplete(entity); + function_parameter_t *const parameter = + allocate_parameter(entity->declaration.type); - parameter = obstack_alloc(type_obst, sizeof(parameter[0])); - memset(parameter, 0, sizeof(parameter[0])); - parameter->type = entity->declaration.type; + if (scope != NULL) { + append_entity(scope, entity); + } - if (scope != NULL) { - append_entity(scope, entity); + *anchor = parameter; + anchor = ¶meter->next; + break; } - if (last_parameter != NULL) { - last_parameter->next = parameter; - } else { - type->parameters = parameter; + default: + goto parameters_finished; } - last_parameter = parameter; - break; - } - - default: - goto parameters_finished; - } - if (token.type != ',') { - goto parameters_finished; + if (token.type != ',') { + goto parameters_finished; + } + next_token(); } - next_token(); } @@ -4271,67 +4275,69 @@ typedef enum construct_type_kind_t { CONSTRUCT_ARRAY } construct_type_kind_t; -typedef struct construct_type_t construct_type_t; -struct construct_type_t { +typedef union construct_type_t construct_type_t; + +typedef struct construct_type_base_t { construct_type_kind_t kind; construct_type_t *next; -}; - -typedef struct parsed_pointer_t parsed_pointer_t; -struct parsed_pointer_t { - construct_type_t construct_type; - type_qualifiers_t type_qualifiers; - variable_t *base_variable; /**< MS __based extension. */ -}; - -typedef struct parsed_reference_t parsed_reference_t; -struct parsed_reference_t { - construct_type_t construct_type; -}; - -typedef struct construct_function_type_t construct_function_type_t; -struct construct_function_type_t { - construct_type_t construct_type; - type_t *function_type; -}; - -typedef struct parsed_array_t parsed_array_t; -struct parsed_array_t { - construct_type_t construct_type; - type_qualifiers_t type_qualifiers; - bool is_static; - bool is_variable; - expression_t *size; -}; - -typedef struct construct_base_type_t construct_base_type_t; -struct construct_base_type_t { - construct_type_t construct_type; - type_t *type; +} construct_type_base_t; + +typedef struct parsed_pointer_t { + construct_type_base_t base; + type_qualifiers_t type_qualifiers; + variable_t *base_variable; /**< MS __based extension. */ +} parsed_pointer_t; + +typedef struct parsed_reference_t { + construct_type_base_t base; +} parsed_reference_t; + +typedef struct construct_function_type_t { + construct_type_base_t base; + type_t *function_type; +} construct_function_type_t; + +typedef struct parsed_array_t { + construct_type_base_t base; + type_qualifiers_t type_qualifiers; + bool is_static; + bool is_variable; + expression_t *size; +} parsed_array_t; + +union construct_type_t { + construct_type_kind_t kind; + construct_type_base_t base; + parsed_pointer_t pointer; + parsed_reference_t reference; + construct_function_type_t function; + parsed_array_t array; }; static construct_type_t *parse_pointer_declarator(variable_t *base_variable) { eat('*'); - parsed_pointer_t *pointer = obstack_alloc(&temp_obst, sizeof(pointer[0])); - memset(pointer, 0, sizeof(pointer[0])); - pointer->construct_type.kind = CONSTRUCT_POINTER; - pointer->type_qualifiers = parse_type_qualifiers(); - pointer->base_variable = base_variable; + construct_type_t *cons = obstack_alloc(&temp_obst, sizeof(cons->pointer)); + parsed_pointer_t *pointer = &cons->pointer; + memset(pointer, 0, sizeof(*pointer)); + cons->kind = CONSTRUCT_POINTER; + pointer->type_qualifiers = parse_type_qualifiers(); + pointer->base_variable = base_variable; - return &pointer->construct_type; + return cons; } static construct_type_t *parse_reference_declarator(void) { eat('&'); - parsed_reference_t *reference = obstack_alloc(&temp_obst, sizeof(reference[0])); - memset(reference, 0, sizeof(reference[0])); - reference->construct_type.kind = CONSTRUCT_REFERENCE; + construct_type_t *cons = obstack_alloc(&temp_obst, sizeof(cons->reference)); + parsed_reference_t *reference = &cons->reference; + memset(reference, 0, sizeof(*reference)); + cons->kind = CONSTRUCT_REFERENCE; - return (construct_type_t*)reference; + return cons; } static construct_type_t *parse_array_declarator(void) @@ -4339,9 +4345,10 @@ static construct_type_t *parse_array_declarator(void) eat('['); add_anchor_token(']'); - parsed_array_t *array = obstack_alloc(&temp_obst, sizeof(array[0])); - memset(array, 0, sizeof(array[0])); - array->construct_type.kind = CONSTRUCT_ARRAY; + construct_type_t *cons = obstack_alloc(&temp_obst, sizeof(cons->array)); + parsed_array_t *array = &cons->array; + memset(array, 0, sizeof(*array)); + cons->kind = CONSTRUCT_ARRAY; if (token.type == T_static) { array->is_static = true; @@ -4370,7 +4377,7 @@ static construct_type_t *parse_array_declarator(void) expect(']', end_error); end_error: - return &array->construct_type; + return cons; } static construct_type_t *parse_function_declarator(scope_t *scope, @@ -4395,13 +4402,13 @@ static construct_type_t *parse_function_declarator(scope_t *scope, parse_parameters(ftype, scope); - construct_function_type_t *construct_function_type = - obstack_alloc(&temp_obst, sizeof(construct_function_type[0])); - memset(construct_function_type, 0, sizeof(construct_function_type[0])); - construct_function_type->construct_type.kind = CONSTRUCT_FUNCTION; - construct_function_type->function_type = type; + construct_type_t *cons = obstack_alloc(&temp_obst, sizeof(cons->function)); + construct_function_type_t *function = &cons->function; + memset(function, 0, sizeof(*function)); + cons->kind = CONSTRUCT_FUNCTION; + function->function_type = type; - return &construct_function_type->construct_type; + return cons; } typedef struct parse_declarator_env_t { @@ -4416,66 +4423,57 @@ static construct_type_t *parse_inner_declarator(parse_declarator_env_t *env, { /* construct a single linked list of construct_type_t's which describe * how to construct the final declarator type */ - construct_type_t *first = NULL; - construct_type_t *last = NULL; - gnu_attribute_t *attributes = NULL; + construct_type_t *first = NULL; + construct_type_t **anchor = &first; + gnu_attribute_t *attributes = NULL; decl_modifiers_t modifiers = parse_attributes(&attributes); - /* MS __based extension */ - based_spec_t base_spec; - base_spec.base_variable = NULL; - for (;;) { construct_type_t *type; + variable_t *based = NULL; /* MS __based extension */ switch (token.type) { case '&': if (!(c_mode & _CXX)) errorf(HERE, "references are only available for C++"); - if (base_spec.base_variable != NULL && warning.other) { - warningf(&base_spec.source_position, - "__based does not precede a pointer operator, ignored"); - } type = parse_reference_declarator(); - /* consumed */ - base_spec.base_variable = NULL; - break; - - case '*': - type = parse_pointer_declarator(base_spec.base_variable); - /* consumed */ - base_spec.base_variable = NULL; break; - case T__based: + case T__based: { + source_position_t const pos = *HERE; next_token(); expect('(', end_error); add_anchor_token(')'); - parse_microsoft_based(&base_spec); + based = parse_microsoft_based(); rem_anchor_token(')'); expect(')', end_error); - continue; + if (token.type != '*') { + if (token.type == T__based) { + errorf(&pos, "__based type modifier specified more than once"); + } else if (warning.other) { + warningf(&pos, + "__based does not precede a pointer declarator, ignored"); + } + continue; + } + /* FALLTHROUGH */ + } + + case '*': + type = parse_pointer_declarator(based); + break; default: goto ptr_operator_end; } - if (last == NULL) { - first = type; - last = type; - } else { - last->next = type; - last = type; - } + *anchor = type; + anchor = &type->base.next; /* TODO: find out if this is correct */ modifiers |= parse_attributes(&attributes); } ptr_operator_end: - if (base_spec.base_variable != NULL && warning.other) { - warningf(&base_spec.source_position, - "__based does not precede a pointer operator, ignored"); - } if (env != NULL) { modifiers |= env->modifiers; @@ -4518,9 +4516,9 @@ ptr_operator_end: return NULL; } - construct_type_t *p = last; + construct_type_t **const p = anchor; - while (true) { + for (;;) { construct_type_t *type; switch (token.type) { case '(': { @@ -4538,28 +4536,17 @@ ptr_operator_end: goto declarator_finished; } - /* insert in the middle of the list (behind p) */ - if (p != NULL) { - type->next = p->next; - p->next = type; - } else { - type->next = first; - first = type; - } - if (last == p) { - last = type; - } + /* insert in the middle of the list (at p) */ + type->base.next = *p; + *p = type; + if (anchor == p) + anchor = &type->base.next; } declarator_finished: - /* append inner_types at the end of the list, we don't to set last anymore + /* append inner_types at the end of the list, we don't to set anchor anymore * as it's not needed anymore */ - if (last == NULL) { - assert(first == NULL); - first = inner_types; - } else { - last->next = inner_types; - } + *anchor = inner_types; return first; end_error: @@ -4632,15 +4619,13 @@ static void parse_declaration_attributes(entity_t *entity) static type_t *construct_declarator_type(construct_type_t *construct_list, type_t *type) { construct_type_t *iter = construct_list; - for (; iter != NULL; iter = iter->next) { + for (; iter != NULL; iter = iter->base.next) { switch (iter->kind) { case CONSTRUCT_INVALID: - internal_errorf(HERE, "invalid type construction found"); + break; case CONSTRUCT_FUNCTION: { - construct_function_type_t *construct_function_type - = (construct_function_type_t*) iter; - - type_t *function_type = construct_function_type->function_type; + construct_function_type_t *function = &iter->function; + type_t *function_type = function->function_type; function_type->function.return_type = type; @@ -4657,16 +4642,18 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, type_ } } - type = function_type; - break; + /* The function type was constructed earlier. Freeing it here will + * destroy other types. */ + type = typehash_insert(function_type); + continue; } case CONSTRUCT_POINTER: { if (is_type_reference(skip_typeref(type))) errorf(HERE, "cannot declare a pointer to reference"); - parsed_pointer_t *parsed_pointer = (parsed_pointer_t*) iter; - type = make_based_pointer_type(type, parsed_pointer->type_qualifiers, parsed_pointer->base_variable); + parsed_pointer_t *pointer = &iter->pointer; + type = make_based_pointer_type(type, pointer->type_qualifiers, pointer->base_variable); continue; } @@ -4681,26 +4668,37 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, type_ if (is_type_reference(skip_typeref(type))) errorf(HERE, "cannot declare an array of references"); - parsed_array_t *parsed_array = (parsed_array_t*) iter; - type_t *array_type = allocate_type_zero(TYPE_ARRAY); + parsed_array_t *array = &iter->array; + type_t *array_type = allocate_type_zero(TYPE_ARRAY); - expression_t *size_expression = parsed_array->size; + expression_t *size_expression = array->size; if (size_expression != NULL) { size_expression = create_implicit_cast(size_expression, type_size_t); } - array_type->base.qualifiers = parsed_array->type_qualifiers; + array_type->base.qualifiers = array->type_qualifiers; array_type->array.element_type = type; - array_type->array.is_static = parsed_array->is_static; - array_type->array.is_variable = parsed_array->is_variable; + array_type->array.is_static = array->is_static; + array_type->array.is_variable = array->is_variable; array_type->array.size_expression = size_expression; if (size_expression != NULL) { if (is_constant_expression(size_expression)) { + long const size = fold_constant(size_expression); + array_type->array.size = size; array_type->array.size_constant = true; - array_type->array.size - = fold_constant(size_expression); + /* §6.7.5.2:1 If the expression is a constant expression, it shall + * have a value greater than zero. */ + if (size <= 0) { + if (size < 0 || !GNU_MODE) { + errorf(&size_expression->base.source_position, + "size of array must be greater than zero"); + } else if (warning.other) { + warningf(&size_expression->base.source_position, + "zero length arrays are a GCC extension"); + } + } } else { array_type->array.is_vla = true; } @@ -4713,18 +4711,11 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, type_ } else if (is_type_function(skipped_type)) { errorf(HERE, "array of functions is not allowed"); } - type = array_type; - break; - } + type = identify_new_type(array_type); + continue; } - - /* The function type was constructed earlier. Freeing it here will - * destroy other types. */ - if (iter->kind == CONSTRUCT_FUNCTION) { - type = typehash_insert(type); - } else { - type = identify_new_type(type); } + internal_errorf(HERE, "invalid type construction found"); } return type; @@ -4746,7 +4737,7 @@ static type_t *semantic_parameter(const source_position_t *pos, type = automatic_type_conversion(type); if (specifiers->is_inline && is_type_valid(type)) { - errorf(pos, "parameter '%Y' declared 'inline'", symbol); + errorf(pos, "parameter '%#T' declared 'inline'", type, symbol); } /* §6.9.1:6 The declarations in the declaration list shall contain @@ -4756,7 +4747,7 @@ static type_t *semantic_parameter(const source_position_t *pos, specifiers->storage_class != STORAGE_CLASS_NONE && specifiers->storage_class != STORAGE_CLASS_REGISTER) ) { - errorf(pos, "invalid storage class for parameter '%Y'", symbol); + errorf(pos, "invalid storage class for parameter '%#T'", type, symbol); } /* delay test for incomplete type, because we might have (void) @@ -5353,7 +5344,8 @@ static void check_variable_type_complete(entity_t *ent) /* §6.7:7 If an identifier for an object is declared with no linkage, the * type for the object shall be complete [...] */ declaration_t *decl = &ent->declaration; - if (decl->storage_class != STORAGE_CLASS_NONE) + if (decl->storage_class == STORAGE_CLASS_EXTERN || + decl->storage_class == STORAGE_CLASS_STATIC) return; type_t *const orig_type = decl->type; @@ -5522,8 +5514,8 @@ decl_list_end: /* update function type */ type_t *new_type = duplicate_type(type); - function_parameter_t *parameters = NULL; - function_parameter_t *last_parameter = NULL; + function_parameter_t *parameters = NULL; + function_parameter_t **anchor = ¶meters; parameter = entity->function.parameters.entities; for (; parameter != NULL; parameter = parameter->base.next) { @@ -5553,17 +5545,11 @@ decl_list_end: */ parameter_type = get_default_promoted_type(parameter_type); - function_parameter_t *function_parameter - = obstack_alloc(type_obst, sizeof(function_parameter[0])); - memset(function_parameter, 0, sizeof(function_parameter[0])); + function_parameter_t *const parameter = + allocate_parameter(parameter_type); - function_parameter->type = parameter_type; - if (last_parameter != NULL) { - last_parameter->next = function_parameter; - } else { - parameters = function_parameter; - } - last_parameter = function_parameter; + *anchor = parameter; + anchor = ¶meter->next; } /* §6.9.1.7: A K&R style parameter list does NOT act as a function @@ -6600,11 +6586,9 @@ static void parse_compound_declarators(compound_t *compound, entity->base.symbol, orig_type); } else if (is_type_incomplete(type)) { /* §6.7.2.1:16 flexible array member */ - if (is_type_array(type) && - token.type == ';' && - look_ahead(1)->type == '}') { - compound->has_flexible_member = true; - } else { + if (!is_type_array(type) || + token.type != ';' || + look_ahead(1)->type != '}') { errorf(&entity->base.source_position, "compound member '%Y' has incomplete type '%T'", entity->base.symbol, orig_type); @@ -6862,15 +6846,8 @@ static entity_t *create_implicit_function(symbol_t *symbol, static type_t *make_function_2_type(type_t *return_type, type_t *argument_type1, type_t *argument_type2) { - function_parameter_t *parameter2 - = obstack_alloc(type_obst, sizeof(parameter2[0])); - memset(parameter2, 0, sizeof(parameter2[0])); - parameter2->type = argument_type2; - - function_parameter_t *parameter1 - = obstack_alloc(type_obst, sizeof(parameter1[0])); - memset(parameter1, 0, sizeof(parameter1[0])); - parameter1->type = argument_type1; + function_parameter_t *const parameter2 = allocate_parameter(argument_type2); + function_parameter_t *const parameter1 = allocate_parameter(argument_type1); parameter1->next = parameter2; type_t *type = allocate_type_zero(TYPE_FUNCTION); @@ -6889,10 +6866,7 @@ static type_t *make_function_2_type(type_t *return_type, type_t *argument_type1, */ static type_t *make_function_1_type(type_t *return_type, type_t *argument_type) { - function_parameter_t *parameter - = obstack_alloc(type_obst, sizeof(parameter[0])); - memset(parameter, 0, sizeof(parameter[0])); - parameter->type = argument_type; + function_parameter_t *const parameter = allocate_parameter(argument_type); type_t *type = allocate_type_zero(TYPE_FUNCTION); type->function.return_type = return_type; @@ -8141,18 +8115,13 @@ static expression_t *parse_call_expression(expression_t *expression) add_anchor_token(','); if (token.type != ')') { - call_argument_t *last_argument = NULL; - - while (true) { - call_argument_t *argument = allocate_ast_zero(sizeof(argument[0])); - + call_argument_t **anchor = &call->arguments; + for (;;) { + call_argument_t *argument = allocate_ast_zero(sizeof(*argument)); argument->expression = parse_assignment_expression(); - if (last_argument == NULL) { - call->arguments = argument; - } else { - last_argument->next = argument; - } - last_argument = argument; + + *anchor = argument; + anchor = &argument->next; if (token.type != ',') break; @@ -11459,12 +11428,9 @@ static entity_t *create_builtin_function(builtin_kind_t kind, const char *name, /** * Create predefined gnu builtins. */ -static void create_gnu_builtins(void) { -#define _STR(a) #a -#define STR(a) _STR(a) -#define CONCAT(a,b) a##b -#define GNU_BUILTIN_NAME(a) STR(CONCAT(__builtin_, a)) -#define GNU_BUILTIN(a, b) create_builtin_function(CONCAT(bk_gnu_builtin_, a), GNU_BUILTIN_NAME(a), b) +static void create_gnu_builtins(void) +{ +#define GNU_BUILTIN(a, b) create_builtin_function(bk_gnu_builtin_##a, "__builtin_" #a, b) GNU_BUILTIN(alloca, make_function_1_type(type_void_ptr, type_size_t)); GNU_BUILTIN(huge_val, make_function_0_type(type_double)); @@ -11487,20 +11453,14 @@ static void create_gnu_builtins(void) { GNU_BUILTIN(trap, make_function_0_type_noreturn(type_void)); #undef GNU_BUILTIN -#undef GNU_BUILTIN_NAME -#undef CONCAT -#undef STR -#undef _STR } /** * Create predefined MS intrinsics. */ -static void create_microsoft_intrinsics(void) { -#define _STR(a) #a -#define STR(a) _STR(a) -#define CONCAT(a,b) a##b -#define MS_BUILTIN(a, b) create_builtin_function(CONCAT(bk_ms, a), STR(a), b) +static void create_microsoft_intrinsics(void) +{ +#define MS_BUILTIN(a, b) create_builtin_function(bk_ms##a, #a, b) /* intrinsics for all architectures */ MS_BUILTIN(_rotl, make_function_2_type(type_unsigned_int, type_unsigned_int, type_int)); @@ -11516,16 +11476,29 @@ static void create_microsoft_intrinsics(void) { MS_BUILTIN(__popcount, make_function_1_type(type_unsigned_int, type_unsigned_int)); /* x86/x64 only */ + MS_BUILTIN(_enable, make_function_0_type(type_void)); + MS_BUILTIN(_disable, make_function_0_type(type_void)); + MS_BUILTIN(__inbyte, make_function_1_type(type_unsigned_char, type_unsigned_short)); + MS_BUILTIN(__inword, make_function_1_type(type_unsigned_short, type_unsigned_short)); + MS_BUILTIN(__indword, make_function_1_type(type_unsigned_long, type_unsigned_short)); + MS_BUILTIN(__outbyte, make_function_2_type(type_void, type_unsigned_short, type_unsigned_char)); + MS_BUILTIN(__outword, make_function_2_type(type_void, type_unsigned_short, type_unsigned_short)); + MS_BUILTIN(__outdword, make_function_2_type(type_void, type_unsigned_short, type_unsigned_long)); MS_BUILTIN(__ud2, make_function_0_type_noreturn(type_void)); MS_BUILTIN(_BitScanForward, make_function_2_type(type_unsigned_char, type_unsigned_long_ptr, type_unsigned_long)); MS_BUILTIN(_BitScanReverse, make_function_2_type(type_unsigned_char, type_unsigned_long_ptr, type_unsigned_long)); MS_BUILTIN(_InterlockedExchange, make_function_2_type(type_long, type_long_ptr, type_long)); MS_BUILTIN(_InterlockedExchange64, make_function_2_type(type_int64, type_int64_ptr, type_int64)); + if (machine_size <= 32) { + MS_BUILTIN(__readeflags, make_function_0_type(type_unsigned_int)); + MS_BUILTIN(__writeeflags, make_function_1_type(type_void, type_unsigned_int)); + } else { + MS_BUILTIN(__readeflags, make_function_0_type(type_unsigned_int64)); + MS_BUILTIN(__writeeflags, make_function_1_type(type_void, type_unsigned_int64)); + } + #undef MS_BUILTIN -#undef CONCAT -#undef STR -#undef _STR } /**