From: Michael Beck Date: Sat, 16 Aug 2008 11:36:17 +0000 (+0000) Subject: fixed support for calling conventions: X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=0fca11d25333e9156984a12a530d722a74018592;p=cparser fixed support for calling conventions: - add them to function type - issue error if more than one cc is used - show them in type info [r21216] --- diff --git a/ast2firm.c b/ast2firm.c index c3c471f..7261ac8 100644 --- a/ast2firm.c +++ b/ast2firm.c @@ -380,6 +380,34 @@ static ir_type *create_method_type(const function_type_t *function_type) set_method_variadicity(irtype, variadicity_variadic); } + unsigned cc; + switch (function_type->calling_convention) { + case CC_DEFAULT: /* unspecified calling convention, equal to one of the other, typical cdelc */ + case CC_CDECL: +is_cdecl: + cc = get_method_calling_convention(irtype); + set_method_calling_convention(irtype, SET_CDECL(cc)); + break; + case CC_STDCALL: + if (function_type->variadic || function_type->unspecified_parameters) + goto is_cdecl; + + /* only non-variadic function can use stdcall, else use cdecl */ + cc = get_method_calling_convention(irtype); + set_method_calling_convention(irtype, SET_STDCALL(cc)); + break; + case CC_FASTCALL: + if (function_type->variadic || function_type->unspecified_parameters) + goto is_cdecl; + /* only non-variadic function can use fastcall, else use cdecl */ + cc = get_method_calling_convention(irtype); + set_method_calling_convention(irtype, SET_FASTCALL(cc)); + break; + case CC_THISCALL: + /* Hmm, leave default, not accepted by the parser yet. */ + warningf(&function_type->base.source_position, "THISCALL calling convention not supported yet"); + break; + } return irtype; } @@ -1018,14 +1046,6 @@ static ir_entity *get_function_entity(declaration_t *declaration) ir_type *ir_type_method = get_ir_type(declaration->type); assert(is_Method_type(ir_type_method)); - if (declaration->modifiers & DM_CDECL) { - set_method_calling_convention(ir_type_method, cc_fixed | cc_cdecl_set); - } else if (declaration->modifiers & DM_FASTCALL) { - set_method_calling_convention(ir_type_method, cc_fixed | cc_fastcall_set); - } else if (declaration->modifiers & DM_STDCALL) { - set_method_calling_convention(ir_type_method, cc_fixed | cc_stdcall_set); - } - /* already an entity defined? */ ir_entity *entity = entitymap_get(&entitymap, symbol); if (entity != NULL) { diff --git a/parser.c b/parser.c index 5d554d6..524b039 100644 --- a/parser.c +++ b/parser.c @@ -391,6 +391,9 @@ static size_t get_type_struct_size(type_kind_t kind) /** * Allocate a type node of given kind and initialize all * fields with zero. + * + * @param kind type kind to allocate + * @param source_position the source position of the type definition */ static type_t *allocate_type_zero(type_kind_t kind, const source_position_t *source_position) { @@ -3607,6 +3610,40 @@ static construct_type_t *parse_function_declarator(declaration_t *declaration) type_t *type; if (declaration != NULL) { type = allocate_type_zero(TYPE_FUNCTION, &declaration->source_position); + + unsigned mask = declaration->modifiers & (DM_CDECL|DM_STDCALL|DM_FASTCALL|DM_THISCALL); + + if (mask & (mask-1)) { + const char *first = NULL, *second = NULL; + + /* more than one calling convention set */ + if (declaration->modifiers & DM_CDECL) { + if (first == NULL) first = "cdecl"; + else if (second == NULL) second = "cdecl"; + } + if (declaration->modifiers & DM_STDCALL) { + if (first == NULL) first = "stdcall"; + else if (second == NULL) second = "stdcall"; + } + if (declaration->modifiers & DM_FASTCALL) { + if (first == NULL) first = "faslcall"; + else if (second == NULL) second = "fastcall"; + } + if (declaration->modifiers & DM_THISCALL) { + if (first == NULL) first = "thiscall"; + else if (second == NULL) second = "thiscall"; + } + errorf(&declaration->source_position, "%s and %s attributes are not compatible", first, second); + } + + if (declaration->modifiers & DM_CDECL) + type->function.calling_convention = CC_CDECL; + else if (declaration->modifiers & DM_STDCALL) + type->function.calling_convention = CC_STDCALL; + else if (declaration->modifiers & DM_FASTCALL) + type->function.calling_convention = CC_FASTCALL; + else if (declaration->modifiers & DM_THISCALL) + type->function.calling_convention = CC_THISCALL; } else { type = allocate_type_zero(TYPE_FUNCTION, HERE); } @@ -3622,7 +3659,7 @@ static construct_type_t *parse_function_declarator(declaration_t *declaration) construct_function_type->construct_type.kind = CONSTRUCT_FUNCTION; construct_function_type->function_type = type; - return (construct_type_t*) construct_function_type; + return &construct_function_type->construct_type; } static void fix_declaration_type(declaration_t *declaration) diff --git a/type.c b/type.c index dfb83e7..37893b9 100644 --- a/type.c +++ b/type.c @@ -279,6 +279,23 @@ static void print_function_type_pre(const function_type_t *type, bool top) intern_print_type_pre(type->return_type, false); + switch (type->calling_convention) { + case CC_CDECL: + fputs(" __cdecl ", out); + break; + case CC_STDCALL: + fputs(" __stdcall ", out); + break; + case CC_FASTCALL: + fputs(" __fastcall ", out); + break; + case CC_THISCALL: + fputs(" __thiscall ", out); + break; + case CC_DEFAULT: + break; + } + /* don't emit braces if we're the toplevel type... */ if (!top) fputc('(', out); @@ -922,6 +939,9 @@ static bool function_types_compatible(const function_type_t *func1, if (func1->variadic != func2->variadic) return false; + if (func1->calling_convention != func2->calling_convention) + return false; + /* TODO: handling of unspecified parameters not correct yet */ /* all argument types must be compatible */