EMIT_NEW_UNALU (cfg, ins, OP_ICGT, dreg, -1);
ins->type = STACK_I4;
return ins;
+ } else if (!strcmp (cmethod->name, "CreateSpan") && fsig->param_count == 1) {
+ MonoGenericContext* ctx = mono_method_get_context (cmethod);
+ g_assert (ctx);
+ g_assert (ctx->method_inst);
+ g_assert (ctx->method_inst->type_argc == 1);
+ MonoType* arg_type = ctx->method_inst->type_argv [0];
+ MonoType* t = mini_get_underlying_type (arg_type);
+ g_assert (!MONO_TYPE_IS_REFERENCE (t) && t->type != MONO_TYPE_VALUETYPE);
+
+ // This OP_LDTOKEN_FIELD later changes into a OP_VMOVE.
+ MonoClassField* field = (MonoClassField*) args [0]->inst_p1;
+ if (args [0]->opcode != OP_LDTOKEN_FIELD)
+ return NULL;
+
+ int alignment = 0;
+ const int element_size = mono_type_size (t, &alignment);
+ const int num_elements = mono_type_size (field->type, &alignment) / element_size;
+ const int obj_size = MONO_ABI_SIZEOF (MonoObject);
+
+ MonoInst* span = mono_compile_create_var (cfg, fsig->ret, OP_LOCAL);
+ MonoInst* span_addr;
+ EMIT_NEW_TEMPLOADA (cfg, span_addr, span->inst_c0);
+
+ MonoInst* ptr_inst;
+ if (cfg->compile_aot) {
+ NEW_RVACONST (cfg, ptr_inst, mono_class_get_image (mono_field_get_parent (field)), args [0]->inst_c0);
+ MONO_ADD_INS (cfg->cbb, ptr_inst);
+ } else {
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ const int swizzle = 1;
+#else
+ const int swizzle = element_size;
+#endif
+ gpointer data_ptr = (gpointer)mono_field_get_rva (field, swizzle);
+ EMIT_NEW_PCONST (cfg, ptr_inst, data_ptr);
+ }
+
+ MonoClassField* field_ref = mono_class_get_field_from_name_full (span->klass, "_reference", NULL);
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, span_addr->dreg, field_ref->offset - obj_size, ptr_inst->dreg);
+ MonoClassField* field_len = mono_class_get_field_from_name_full (span->klass, "_length", NULL);
+ MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STOREI4_MEMBASE_IMM, span_addr->dreg, field_len->offset - obj_size, num_elements);
+ EMIT_NEW_TEMPLOAD (cfg, ins, span->inst_c0);
+ return ins;
} else
return NULL;
} else if (cmethod->klass == mono_class_try_get_memory_marshal_class ()) {
#define NEW_LDSTRCONST(cfg,dest,image,token) NEW_AOTCONST_TOKEN ((cfg), (dest), MONO_PATCH_INFO_LDSTR, (image), (token), NULL, STACK_OBJ, mono_defaults.string_class)
+#define NEW_RVACONST(cfg,dest,image,token) NEW_AOTCONST_TOKEN ((cfg), (dest), MONO_PATCH_INFO_RVA, (image), (token), NULL, STACK_MP, NULL)
+
#define NEW_LDSTRLITCONST(cfg,dest,val) NEW_AOTCONST ((cfg), (dest), MONO_PATCH_INFO_LDSTR_LIT, (val))
#define NEW_TYPE_FROM_HANDLE_CONST(cfg,dest,image,token,generic_context) NEW_AOTCONST_TOKEN ((cfg), (dest), MONO_PATCH_INFO_TYPE_FROM_HANDLE, (image), (token), (generic_context), STACK_OBJ, mono_defaults.runtimetype_class)
} else {
EMIT_NEW_PCONST (cfg, ins, handle);
}
+
EMIT_NEW_TEMPLOADA (cfg, addr, vtvar->inst_c0);
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, addr->dreg, 0, ins->dreg);
EMIT_NEW_TEMPLOAD (cfg, ins, vtvar->inst_c0);
+ ins->opcode = OP_LDTOKEN_FIELD;
+ ins->inst_c0 = n;
+ ins->inst_p1 = handle;
+
+ cfg->flags |= MONO_CFG_NEEDS_DECOMPOSE;
+ cfg->cbb->needs_decompose = TRUE;
}
}
MINI_OP(OP_DUMMY_USE, "dummy_use", NONE, IREG, NONE)
MINI_OP(OP_NOT_REACHED, "not_reached", NONE, NONE, NONE)
MINI_OP(OP_NOT_NULL, "not_null", NONE, IREG, NONE)
+MINI_OP(OP_LDTOKEN_FIELD, "ldtoken_field", VREG, VREG, NONE)
/* SIMD opcodes. */