klass = mono_class_from_mono_type (type);
size = mini_type_stack_size_full (&klass->byval_arg, NULL, sig->pinvoke);
- ainfo->pass_empty_struct = FALSE;
-#ifndef __GNUC__
/*
* Standard C and C++ doesn't allow empty structs, empty structs will always have a size of 1 byte.
* GCC have an extension to allow empty structs, https://gcc.gnu.org/onlinedocs/gcc/Empty-Structures.html.
*/
if (0 == size && MONO_TYPE_ISSTRUCT (type) && sig->pinvoke)
ainfo->pass_empty_struct = TRUE;
-#endif
if (!sig->pinvoke)
pass_on_stack = TRUE;
klass = mono_class_from_mono_type (type);
size = mini_type_stack_size_full (&klass->byval_arg, NULL, sig->pinvoke);
- ainfo->pass_empty_struct = FALSE;
-
if (!sig->pinvoke && ((is_return && (size == 8)) || (!is_return && (size <= 16)))) {
/* We pass and return vtypes of size 8 in a register */
} else if (!sig->pinvoke || (size == 0) || (size > 16)) {
/* Continue normally */
}
- if (size > 0 || (ainfo->pass_empty_struct)) {
+ if (size > 0 || ainfo->pass_empty_struct) {
MONO_INST_NEW (cfg, arg, OP_OUTARG_VT);
arg->sreg1 = in->dreg;
arg->klass = mono_class_from_mono_type (t);
if (ainfo->pass_empty_struct) {
//Pass empty struct value as 0 on platforms representing empty structs as 1 byte.
- MONO_INST_NEW (cfg, load, OP_ICONST);
- load->inst_c0 = 0;
+ NEW_ICONST (cfg, load, 0);
}
- else
- {
+ else {
MONO_INST_NEW (cfg, load, arg_storage_to_load_membase (ainfo->pair_storage [part]));
load->inst_basereg = src->dreg;
load->inst_offset = part * sizeof(mgreg_t);
- }
- switch (ainfo->pair_storage [part]) {
- case ArgInIReg:
- load->dreg = mono_alloc_ireg (cfg);
- break;
- case ArgInDoubleSSEReg:
- case ArgInFloatSSEReg:
- load->dreg = mono_alloc_freg (cfg);
- break;
- default:
- g_assert_not_reached ();
+ switch (ainfo->pair_storage [part]) {
+ case ArgInIReg:
+ load->dreg = mono_alloc_ireg (cfg);
+ break;
+ case ArgInDoubleSSEReg:
+ case ArgInFloatSSEReg:
+ load->dreg = mono_alloc_freg (cfg);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
}
+
MONO_ADD_INS (cfg->cbb, load);
add_outarg_reg (cfg, call, ainfo->pair_storage [part], ainfo->pair_regs [part], load);
return 0;
}
+#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wc++-compat"
+#endif
+
+/*
+* Standard C and C++ doesn't allow empty structs, empty structs will always have a size of 1 byte.
+* GCC have an extension to allow empty structs, https://gcc.gnu.org/onlinedocs/gcc/Empty-Structures.html.
+* This cause a little dilemma since runtime build using none GCC compiler will not be compatible with
+* GCC build C libraries and the other way around. On platforms where empty structs has size of 1 byte
+* it must be represented in call and cannot be dropped. On Windows x64 structs will always be represented in the call
+* meaning that an empty struct must have a representation in the callee in order to correctly follow the ABI used by the
+* C/C++ standard and the runtime.
+*/
typedef struct {
-#ifndef __GNUC__
+#if !defined(__GNUC__) || (defined(TARGET_WIN32) && defined(TARGET_AMD64))
char a;
#endif
} EmptyStruct;
+
+#ifdef __GNUC__
#pragma GCC diagnostic pop
+#endif
LIBTEST_API int STDCALL
mono_test_marshal_empty_string_array (char **array)