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;
}
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) {
/**
* 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)
{
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);
}
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)
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);
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 */