2 * inssel.brg: instruction selection
5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
8 * (C) 2002 Ximian, Inc.
15 #include <mono/metadata/marshal.h>
16 #include <mono/metadata/debug-helpers.h>
18 #define MBTREE_TYPE MonoInst
19 #define MBCGEN_TYPE MonoCompile
20 #define MBCOST_DATA MonoCompile
21 #define MBALLOC_STATE mono_mempool_alloc (data->state_pool, sizeof (MBState))
22 #define MBMAX_OPCODES OP_LAST
23 #define MBGET_OP_NAME(op) mono_inst_name (op)
25 #define MBTREE_OP(t) ((t)->opcode)
26 #define MBTREE_LEFT(t) ((t)->inst_left)
27 #define MBTREE_RIGHT(t) ((t)->inst_right)
29 #define MONO_EMIT_UNALU(cfg,inst,op,dr,sr1) do { \
30 (inst)->opcode = op; \
32 (inst)->sreg1 = sr1; \
33 mono_bblock_add_inst (cfg->cbb, inst); \
36 #define MONO_EMIT_NEW_UNALU(cfg,op,dr,sr1) do { \
38 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
42 mono_bblock_add_inst (cfg->cbb, inst); \
45 #define MONO_EMIT_BIALU(cfg,inst,op,dr,sr1,sr2) do { \
46 (inst)->opcode = op; \
48 (inst)->sreg1 = sr1; \
49 (inst)->sreg2 = sr2; \
50 mono_bblock_add_inst (cfg->cbb, inst); \
53 #define MONO_EMIT_NEW_BIALU(cfg,op,dr,sr1,sr2) do { \
55 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
60 mono_bblock_add_inst (cfg->cbb, inst); \
63 #define MONO_EMIT_BIALU_IMM(cfg,inst,op,dr,sr,imm) do { \
64 (inst)->opcode = op; \
67 (inst)->inst_p1 = (gpointer)imm; \
68 mono_bblock_add_inst (cfg->cbb, inst); \
71 #define MONO_EMIT_NEW_BIALU_IMM(cfg,op,dr,sr,imm) do { \
73 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
77 inst->inst_p1 = (gpointer)imm; \
78 mono_bblock_add_inst (cfg->cbb, inst); \
81 #define MONO_EMIT_LOAD_MEMBASE(cfg,inst,dr,base,offset) do { \
82 (inst)->opcode = OP_LOAD_MEMBASE; \
84 (inst)->inst_basereg = base; \
85 (inst)->inst_offset = offset; \
86 mono_bblock_add_inst (cfg->cbb, inst); \
89 #define MONO_EMIT_LOAD_MEMBASE_OP(cfg,inst,op,dr,base,offset) do { \
90 (inst)->opcode = op; \
92 (inst)->inst_basereg = base; \
93 (inst)->inst_offset = offset; \
94 mono_bblock_add_inst (cfg->cbb, inst); \
97 #define MONO_EMIT_NEW_LOAD_MEM(cfg,dr,addr) do { \
99 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
100 inst->opcode = OP_LOADU4_MEM; \
102 inst->inst_p0 = addr; \
103 mono_bblock_add_inst (cfg->cbb, inst); \
106 #define MONO_EMIT_NEW_LOAD_MEMBASE(cfg,dr,base,offset) do { \
108 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
109 inst->opcode = OP_LOAD_MEMBASE; \
111 inst->inst_basereg = base; \
112 inst->inst_offset = offset; \
113 mono_bblock_add_inst (cfg->cbb, inst); \
116 #define MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg,op,dr,base,offset) do { \
118 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
121 inst->inst_basereg = base; \
122 inst->inst_offset = offset; \
123 mono_bblock_add_inst (cfg->cbb, inst); \
126 #define MONO_EMIT_STORE_MEMBASE(cfg,inst,op,base,offset,sr) do { \
127 (inst)->opcode = op; \
128 (inst)->sreg1 = sr; \
129 (inst)->inst_destbasereg = base; \
130 (inst)->inst_offset = offset; \
131 mono_bblock_add_inst (cfg->cbb, inst); \
134 #define MONO_EMIT_NEW_STORE_MEMBASE(cfg,op,base,offset,sr) do { \
136 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
139 inst->inst_destbasereg = base; \
140 inst->inst_offset = offset; \
141 mono_bblock_add_inst (cfg->cbb, inst); \
144 #define MONO_EMIT_STORE_MEMBASE_IMM(cfg,inst,op,base,offset,imm) do { \
145 (inst)->opcode = op; \
146 (inst)->inst_destbasereg = base; \
147 (inst)->inst_offset = offset; \
148 (inst)->inst_p1 = (gpointer)imm; \
149 mono_bblock_add_inst (cfg->cbb, inst); \
152 #define MONO_EMIT_NEW_STORE_MEMBASE_IMM(cfg,op,base,offset,imm) do { \
154 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
156 inst->inst_destbasereg = base; \
157 inst->inst_offset = offset; \
158 inst->inst_p1 = (gpointer)imm; \
159 mono_bblock_add_inst (cfg->cbb, inst); \
162 #define MONO_EMIT_NEW_COMPARE_IMM(cfg,sr1,imm) do { \
164 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
165 inst->opcode = OP_COMPARE_IMM; \
167 inst->inst_p1 = (gpointer)imm; \
168 mono_bblock_add_inst ((cfg)->cbb, inst); \
171 #define MONO_EMIT_NEW_ICOMPARE_IMM(cfg,sr1,imm) do { \
173 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
174 inst->opcode = sizeof (void*) == 8 ? OP_ICOMPARE_IMM : OP_COMPARE_IMM; \
176 inst->inst_p1 = (gpointer)imm; \
177 mono_bblock_add_inst ((cfg)->cbb, inst); \
180 #define MONO_EMIT_NEW_COND_EXC(cfg,cond,name) do { \
182 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
183 inst->opcode = OP_COND_EXC_##cond; \
184 inst->inst_p1 = (char*)name; \
185 mono_bblock_add_inst ((cfg)->cbb, inst); \
188 #define MONO_EMIT_NEW_ICONST(cfg,dr,imm) do { \
190 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
191 inst->opcode = OP_ICONST; \
193 inst->inst_c0 = imm; \
194 mono_bblock_add_inst ((cfg)->cbb, inst); \
197 #define MONO_EMIT_NEW_I8CONST(cfg,dr,imm) do { \
199 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
200 inst->opcode = OP_I8CONST; \
202 inst->inst_l = imm; \
203 mono_bblock_add_inst ((cfg)->cbb, inst); \
206 #define MONO_EMIT_NEW_PCONST(cfg,dr,imm) do { \
208 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
209 inst->opcode = OP_ICONST; \
211 inst->inst_p0 = (gpointer) imm; \
212 mono_bblock_add_inst ((cfg)->cbb, inst); \
215 #define MONO_EMIT_NEW_AOTCONST(cfg,dr,imm,type) do { \
217 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
218 inst->opcode = OP_AOTCONST; \
220 inst->inst_p0 = imm; \
221 inst->inst_c1 = type; \
222 mono_bblock_add_inst ((cfg)->cbb, inst); \
225 #define MONO_EMIT_NEW_CLASSCONST(cfg,dr,imm) MONO_EMIT_NEW_AOTCONST(cfg,dr,imm,MONO_PATCH_INFO_CLASS)
227 #define MONO_EMIT_NEW_BRANCH_BLOCK(cfg,op,targetbb) do { \
229 MonoInst *target_label; \
230 target_label = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
231 target_label->opcode = OP_LABEL; \
232 target_label->next = (targetbb)->code; \
233 target_label->inst_c0 = (targetbb)->native_offset; \
234 (targetbb)->code = target_label; \
235 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
237 inst->inst_i0 = target_label; \
238 inst->flags = MONO_INST_BRLABEL; \
239 mono_bblock_add_inst ((cfg)->cbb, inst); \
242 #define MONO_EMIT_NEW_BRANCH_LABEL(cfg,op,label) do { \
244 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
246 inst->inst_i0 = label; \
247 inst->flags = MONO_INST_BRLABEL; \
248 mono_bblock_add_inst ((cfg)->cbb, inst); \
251 #define MONO_NEW_LABEL(cfg,inst) do { \
252 (inst) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
253 (inst)->opcode = OP_LABEL; \
256 #define MONO_EMIT_BOUNDS_CHECK(cfg, array_reg, array_type, array_length_field, index_reg) do { \
257 if (! (state->tree->flags & MONO_INST_NORANGECHECK)) { \
258 int _length_reg = mono_regstate_next_int (cfg->rs); \
259 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, _length_reg, array_reg, G_STRUCT_OFFSET (array_type, array_length_field)); \
260 MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, _length_reg, index_reg); \
261 MONO_EMIT_NEW_COND_EXC (cfg, LE_UN, "IndexOutOfRangeException"); \
265 #define MONO_EMIT_BOUNDS_CHECK_IMM(cfg, array_reg, array_type, array_length_field, index_imm) do { \
266 if (! (state->tree->flags & MONO_INST_NORANGECHECK)) { \
267 int _length_reg = mono_regstate_next_int (cfg->rs); \
268 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, _length_reg, array_reg, G_STRUCT_OFFSET (array_type, array_length_field)); \
269 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, _length_reg, index_imm); \
270 MONO_EMIT_NEW_COND_EXC (cfg, LE_UN, "IndexOutOfRangeException"); \
274 /* we need to kludge state because monoburg puts this stuff before the definition of MBState */
275 void mini_emit_virtual_call (MonoCompile *s, void *state, MonoInst *tree, int novirt_op, int virtop);
276 void mini_emit_isninst_cast (MonoCompile *s, int klass_reg, MonoClass *klass, MonoInst *false_target, MonoInst *true_target);
277 void mini_emit_isninst_iface_cast (MonoCompile *s, int vtable_reg, MonoClass *klass, MonoInst *false_target, MonoInst *true_target);
278 void mini_emit_isninst_iface_class_cast (MonoCompile *s, int klass_reg, MonoClass *klass, MonoInst *false_target, MonoInst *true_target);
279 void mini_emit_castclass (MonoCompile *s, int klass_reg, MonoClass *klass);
280 void mini_emit_castclass_iface (MonoCompile *s, int vtable_reg, MonoClass *klass);
281 void mini_emit_castclass_iface_class (MonoCompile *s, int klass_reg, MonoClass *klass);
283 void mini_emit_memcpy (MonoCompile *s, int destreg, int doffset, int srcreg, int soffset, int size, int align);
284 void mini_emit_memset (MonoCompile *s, int destreg, int offset, int size, int val, int align);
286 int ldind_to_load_membase (int opcode);
295 # base addressing mode
299 /* we create a new MonoInst in chain rules and set state->tree to it
300 * since a MBState (and hence state->tree) is reused in chain rules and
304 inst = mono_mempool_alloc0 (s->mempool, sizeof (MonoInst));
305 inst->opcode = OP_ICONST; /* doesn't matter */
306 inst->inst_basereg = state->reg1;
307 inst->inst_offset = 0;
309 //g_print ("mybase: (assigned R%d from R%d - R%d)\n", state->reg1, tree->dreg, state->reg2);
310 //tree->inst_offset = 0;
311 //tree->inst_basereg = state->reg1;
314 base: CEE_LDIND_I (OP_REGVAR) "0" {
315 tree->inst_offset = 0;
316 tree->inst_basereg = state->left->tree->dreg;
319 base: OP_REGOFFSET "0" {
323 base: OP_LDADDR (OP_REGOFFSET),
324 base: CEE_LDOBJ (OP_REGOFFSET) "0" {
325 tree->inst_offset = state->left->tree->inst_offset;
326 tree->inst_basereg = state->left->tree->inst_basereg;
329 base: CEE_ADD (base, OP_ICONST) "0" {
330 tree->inst_offset = state->left->tree->inst_offset + state->right->tree->inst_c0;
331 tree->inst_basereg = state->left->tree->inst_basereg;
334 base: CEE_ADD (CEE_LDIND_REF (OP_REGVAR), OP_ICONST),
335 base: CEE_ADD (CEE_LDIND_I (OP_REGVAR), OP_ICONST) "0" {
336 tree->inst_offset = state->right->tree->inst_c0;
337 tree->inst_basereg = state->left->left->tree->dreg;
345 MONO_EMIT_NEW_ICONST (s, state->reg1, tree->inst_c0);
349 MONO_EMIT_NEW_AOTCONST (s, state->reg1, tree->inst_p0, tree->inst_c1);
353 # load/store operations
356 reg: CEE_LDIND_I (base),
357 reg: CEE_LDIND_REF (base),
358 reg: CEE_LDIND_I1 (base),
359 reg: CEE_LDIND_U1 (base),
360 reg: CEE_LDIND_I2 (base),
361 reg: CEE_LDIND_U2 (base),
362 reg: CEE_LDIND_I4 (base),
363 reg: CEE_LDIND_U4 (base) {
364 MONO_EMIT_LOAD_MEMBASE_OP (s, tree, ldind_to_load_membase (tree->opcode),
365 state->reg1, state->left->tree->inst_basereg, state->left->tree->inst_offset);
368 reg: OP_LDADDR (OP_REGOFFSET),
369 reg: CEE_LDOBJ (OP_REGOFFSET) "2" {
371 tree->opcode = OP_MOVE;
372 tree->sreg1 = state->left->tree->inst_basereg;
373 tree->dreg = state->reg1;
374 mono_bblock_add_inst (s->cbb, tree);
375 if (state->left->tree->inst_offset)
376 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tree->dreg, tree->dreg, state->left->tree->inst_offset);
379 reg: CEE_LDOBJ (reg),
380 reg: OP_OBJADDR (reg),
381 reg: OP_VTADDR (reg) {
382 MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
385 reg: CEE_LDIND_U1 (OP_REGVAR) {
386 MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->tree->dreg, 0xff);
389 reg: CEE_LDIND_U2 (OP_REGVAR) {
390 MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->tree->dreg, 0xffff);
393 stmt: CEE_STIND_REF (base, CEE_LDIND_REF (OP_REGVAR)),
394 stmt: CEE_STIND_REF (base, CEE_LDIND_I (OP_REGVAR)),
395 stmt: CEE_STIND_I (base, CEE_LDIND_REF (OP_REGVAR)),
396 stmt: CEE_STIND_I (base, CEE_LDIND_I (OP_REGVAR)) {
397 MONO_EMIT_STORE_MEMBASE (s, tree, OP_STORE_MEMBASE_REG, state->left->tree->inst_basereg,
398 state->left->tree->inst_offset, state->right->left->tree->dreg);
401 stmt: CEE_STIND_REF (OP_REGVAR, CEE_LDIND_REF (OP_REGVAR)),
402 stmt: CEE_STIND_REF (OP_REGVAR, CEE_LDIND_I (OP_REGVAR)),
403 stmt: CEE_STIND_I (OP_REGVAR, CEE_LDIND_REF (OP_REGVAR)),
404 stmt: CEE_STIND_I (OP_REGVAR, CEE_LDIND_I (OP_REGVAR)),
405 stmt: CEE_STIND_I4 (OP_REGVAR, CEE_LDIND_I4 (OP_REGVAR)) {
406 MONO_EMIT_UNALU (s, tree, OP_MOVE, state->left->tree->dreg, state->right->left->tree->dreg);
410 stmt: CEE_STIND_I (base, reg),
411 stmt: CEE_STIND_REF (base, reg) {
412 MONO_EMIT_STORE_MEMBASE (s, tree, OP_STORE_MEMBASE_REG, state->left->tree->inst_basereg,
413 state->left->tree->inst_offset, state->right->reg1);
416 stmt: CEE_STIND_I (base, OP_ICONST),
417 stmt: CEE_STIND_REF (base, OP_ICONST) {
418 MONO_EMIT_STORE_MEMBASE_IMM (s, tree, OP_STORE_MEMBASE_IMM, state->left->tree->inst_basereg,
419 state->left->tree->inst_offset, state->right->tree->inst_c0);
422 reg: CEE_LDIND_REF (OP_REGVAR),
423 reg: CEE_LDIND_I (OP_REGVAR),
424 reg: CEE_LDIND_I4 (OP_REGVAR),
425 reg: CEE_LDIND_U4 (OP_REGVAR) {
426 MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->tree->dreg);
429 stmt: CEE_STIND_I4 (base, reg) {
430 MONO_EMIT_STORE_MEMBASE (s, tree, OP_STOREI4_MEMBASE_REG, state->left->tree->inst_basereg,
431 state->left->tree->inst_offset, state->right->reg1);
434 stmt: CEE_STIND_I4 (base, CEE_LDIND_I4 (OP_REGVAR)) {
435 MONO_EMIT_STORE_MEMBASE (s, tree, OP_STOREI4_MEMBASE_REG, state->left->tree->inst_basereg,
436 state->left->tree->inst_offset, state->right->left->tree->dreg);
439 stmt: CEE_STIND_I4 (base, OP_ICONST) {
440 MONO_EMIT_STORE_MEMBASE_IMM (s, tree, OP_STOREI4_MEMBASE_IMM, state->left->tree->inst_basereg,
441 state->left->tree->inst_offset, state->right->tree->inst_c0);
444 stmt: CEE_STIND_I4 (OP_REGVAR, CEE_LDIND_I4 (base)) {
445 MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI4_MEMBASE, state->left->tree->dreg,
446 state->right->left->tree->inst_basereg,
447 state->right->left->tree->inst_offset);
450 stmt: CEE_STIND_I1 (base, reg) {
451 MONO_EMIT_STORE_MEMBASE (s, tree, OP_STOREI1_MEMBASE_REG, state->left->tree->inst_basereg,
452 state->left->tree->inst_offset, state->right->reg1);
455 stmt: CEE_STIND_I1 (base, OP_ICONST) {
456 MONO_EMIT_STORE_MEMBASE_IMM (s, tree, OP_STOREI1_MEMBASE_IMM, state->left->tree->inst_basereg,
457 state->left->tree->inst_offset, state->right->tree->inst_c0);
460 stmt: CEE_STIND_I2 (base, reg) {
461 MONO_EMIT_STORE_MEMBASE (s, tree, OP_STOREI2_MEMBASE_REG, state->left->tree->inst_basereg,
462 state->left->tree->inst_offset, state->right->reg1);
465 stmt: CEE_STIND_I2 (base, OP_ICONST) {
466 MONO_EMIT_STORE_MEMBASE_IMM (s, tree, OP_STOREI2_MEMBASE_IMM, state->left->tree->inst_basereg,
467 state->left->tree->inst_offset, state->right->tree->inst_c0);
470 stmt: CEE_STIND_I2 (OP_REGVAR, reg) {
471 MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->left->tree->dreg, state->right->reg1, 0xffff);
474 stmt: CEE_STIND_I1 (OP_REGVAR, reg) {
475 MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->left->tree->dreg, state->right->reg1, 0xff);
478 stmt: CEE_STIND_I1 (OP_REGVAR, CEE_LDIND_U1 (OP_REGVAR)),
479 stmt: CEE_STIND_I1 (OP_REGVAR, CEE_LDIND_I1 (OP_REGVAR)) {
480 MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->left->tree->dreg, state->right->left->tree->dreg, 0xff);
483 stmt: CEE_STIND_I2 (OP_REGVAR, CEE_LDIND_U2 (OP_REGVAR)),
484 stmt: CEE_STIND_I2 (OP_REGVAR, CEE_LDIND_I2 (OP_REGVAR)) {
485 MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->left->tree->dreg, state->right->left->tree->dreg, 0xffff);
488 stmt: CEE_STIND_I4 (OP_REGVAR, OP_ICONST),
489 stmt: CEE_STIND_I2 (OP_REGVAR, OP_ICONST),
490 stmt: CEE_STIND_I1 (OP_REGVAR, OP_ICONST),
491 stmt: CEE_STIND_REF (OP_REGVAR, OP_ICONST),
492 stmt: CEE_STIND_I (OP_REGVAR, OP_ICONST) {
493 tree->inst_c0 = state->right->tree->inst_c0;
494 if (tree->opcode == CEE_STIND_I2)
495 tree->inst_c0 &= 0xffff;
496 if (tree->opcode == CEE_STIND_I1)
497 tree->inst_c0 &= 0xff;
499 tree->opcode = OP_ICONST;
500 tree->dreg = state->left->tree->dreg;
501 mono_bblock_add_inst (s->cbb, tree);
504 stmt: CEE_STIND_I4 (OP_REGVAR, reg),
505 stmt: CEE_STIND_REF (OP_REGVAR, reg),
506 stmt: CEE_STIND_I (OP_REGVAR, reg) {
507 MONO_EMIT_UNALU (s, tree, OP_MOVE, state->left->tree->dreg, state->right->reg1);
510 stmt: OP_MEMCPY (base, base) {
511 int size = tree->unused;
513 mini_emit_memcpy (s, state->left->tree->inst_basereg, state->left->tree->inst_offset,
514 state->right->tree->inst_basereg, state->right->tree->inst_offset, size, 0);
517 stmt: OP_MEMSET (base) {
518 int size = tree->unused;
520 mini_emit_memset (s, state->left->tree->inst_basereg, state->left->tree->inst_offset, size, tree->inst_imm, 0);
523 reg: OP_LDELEMA2D (reg, OP_GROUP (reg, reg)) "20" {
524 int bounds_reg = mono_regstate_next_int (s->rs);
525 int add_reg = mono_regstate_next_int (s->rs);
526 int mult_reg = mono_regstate_next_int (s->rs);
527 int mult2_reg = mono_regstate_next_int (s->rs);
528 int low1_reg = mono_regstate_next_int (s->rs);
529 int low2_reg = mono_regstate_next_int (s->rs);
530 int high1_reg = mono_regstate_next_int (s->rs);
531 int high2_reg = mono_regstate_next_int (s->rs);
532 int realidx1_reg = mono_regstate_next_int (s->rs);
533 int realidx2_reg = mono_regstate_next_int (s->rs);
534 int sum_reg = mono_regstate_next_int (s->rs);
536 guint32 size = mono_array_element_size (tree->klass);
538 index1 = state->right->left->reg1;
539 index2 = state->right->right->reg1;
542 MONO_EMIT_NEW_LOAD_MEMBASE (s, bounds_reg,
543 state->left->reg1, G_STRUCT_OFFSET (MonoArray, bounds));
545 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, low1_reg,
546 bounds_reg, G_STRUCT_OFFSET (MonoArrayBounds, lower_bound));
547 MONO_EMIT_NEW_BIALU (s, CEE_SUB, realidx1_reg, index1, low1_reg);
548 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, high1_reg,
549 bounds_reg, G_STRUCT_OFFSET (MonoArrayBounds, length));
550 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, high1_reg, realidx1_reg);
551 MONO_EMIT_NEW_COND_EXC (s, LE_UN, "IndexOutOfRangeException");
553 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, low2_reg,
554 bounds_reg, sizeof (MonoArrayBounds) + G_STRUCT_OFFSET (MonoArrayBounds, lower_bound));
555 MONO_EMIT_NEW_BIALU (s, CEE_SUB, realidx2_reg, index2, low2_reg);
556 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, high2_reg,
557 bounds_reg, sizeof (MonoArrayBounds) + G_STRUCT_OFFSET (MonoArrayBounds, length));
558 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, high2_reg, realidx2_reg);
559 MONO_EMIT_NEW_COND_EXC (s, LE_UN, "IndexOutOfRangeException");
561 MONO_EMIT_NEW_BIALU (s, CEE_MUL, mult_reg, high2_reg, realidx1_reg);
562 MONO_EMIT_NEW_BIALU (s, CEE_ADD, sum_reg, mult_reg, realidx2_reg);
563 MONO_EMIT_NEW_BIALU_IMM (s, OP_MUL_IMM, mult2_reg, sum_reg, size);
564 MONO_EMIT_NEW_BIALU (s, CEE_ADD, add_reg, mult2_reg, state->left->reg1);
565 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, add_reg, G_STRUCT_OFFSET (MonoArray, vector));
569 # conversions: conv_u can be implemented with AND, also all _ovf conversions?
572 reg: CEE_CONV_I1 (reg),
573 reg: CEE_CONV_I2 (reg),
574 reg: CEE_CONV_I4 (reg) {
575 MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
578 reg: CEE_CONV_U1 (reg) {
579 MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xff);
582 reg: CEE_CONV_U2 (reg) {
583 MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xffff);
586 reg: CEE_CONV_U4 (reg),
587 reg: CEE_CONV_U (reg),
588 reg: CEE_CONV_I (reg),
589 reg: CEE_CONV_OVF_I4 (reg) {
590 if (sizeof (void *) == 8)
591 MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
593 MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
596 reg: CEE_CONV_OVF_U4 (reg),
597 reg: CEE_CONV_OVF_I4_UN (reg) {
598 if (sizeof (void *) == 8) {
599 MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
601 MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0);
602 MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
603 MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
607 reg: CEE_CONV_OVF_I1 (reg) {
608 MONO_EMIT_NEW_ICOMPARE_IMM (s, state->left->reg1, 127);
609 MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
610 MONO_EMIT_NEW_ICOMPARE_IMM (s, state->left->reg1, -128);
611 MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
612 MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1);
615 reg: CEE_CONV_OVF_I1_UN (reg) {
616 /* probe values between 0 to 127 */
617 MONO_EMIT_NEW_ICOMPARE_IMM (s, state->left->reg1, 127);
618 MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
619 MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1);
622 reg: CEE_CONV_OVF_U1 (reg),
623 reg: CEE_CONV_OVF_U1_UN (reg) {
624 /* probe value to be within 0 to 255 */
625 MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 255);
626 MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
627 MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xff);
630 reg: CEE_CONV_OVF_I2 (reg) {
631 /* Probe value to be within -32768 and 32767 */
632 MONO_EMIT_NEW_ICOMPARE_IMM (s, state->left->reg1, 32767);
633 MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
634 MONO_EMIT_NEW_ICOMPARE_IMM (s, state->left->reg1, -32768);
635 MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
636 MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1);
639 reg: CEE_CONV_OVF_I2_UN (reg) {
640 /* Convert uint value into short, value within 0 and 32767 */
641 MONO_EMIT_NEW_ICOMPARE_IMM (s, state->left->reg1, 32767);
642 MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
643 MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1);
646 reg: CEE_CONV_OVF_U2 (reg),
647 reg: CEE_CONV_OVF_U2_UN (reg) {
648 /* Probe value to be within 0 and 65535 */
649 MONO_EMIT_NEW_ICOMPARE_IMM (s, state->left->reg1, 0xffff);
650 MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
651 MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xffff);
655 # other alu operations
658 reg: OP_CEQ (cflags),
659 reg: OP_CLT (cflags),
660 reg: OP_CLT_UN (cflags),
661 reg: OP_CGT (cflags),
662 reg: OP_CGT_UN (cflags) {
663 tree->dreg = state->reg1;
664 mono_bblock_add_inst (s->cbb, tree);
668 # control flow commands
672 mono_bblock_add_inst (s->cbb, tree);
678 stmt: CEE_BREAK "0" {
679 mono_bblock_add_inst (s->cbb, tree);
682 stmt: CEE_SWITCH (reg) {
684 int offset_reg = mono_regstate_next_int (s->rs);
685 int target_reg = mono_regstate_next_int (s->rs);
686 int n = GPOINTER_TO_INT (tree->klass);
688 MONO_NEW_LABEL (s, label);
689 mono_create_jump_table (s, label, tree->inst_many_bb, n);
691 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg1, n);
692 MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGE_UN, tree->inst_many_bb [n]);
693 if (sizeof (gpointer) == 8)
694 MONO_EMIT_NEW_BIALU_IMM (s, OP_SHL_IMM, offset_reg, state->left->reg1, 3);
696 MONO_EMIT_NEW_BIALU_IMM (s, OP_SHL_IMM, offset_reg, state->left->reg1, 2);
697 mono_bblock_add_inst (s->cbb, label);
698 /* the backend must patch the address. we use 0xf0f0f0f0 to avoid the usage
699 * of special (short) opcodes on x86 */
700 if (sizeof (gpointer) == 8) {
701 MONO_EMIT_NEW_LOAD_MEMBASE (s, target_reg, offset_reg, (long)0xf0f0f0f0f0f0f0f1LL);
704 MONO_EMIT_NEW_LOAD_MEMBASE (s, target_reg, offset_reg, 0xf0f0f0f0);
706 MONO_EMIT_UNALU (s, tree, OP_BR_REG, -1, target_reg);
710 mono_bblock_add_inst (s->cbb, tree);
713 stmt: OP_ARGLIST (reg) {
714 tree->sreg1 = state->left->reg1;
715 mono_bblock_add_inst (s->cbb, tree);
719 tree->dreg = state->reg1;
720 mono_bblock_add_inst (s->cbb, tree);
723 reg: CEE_CALLVIRT (reg) {
724 mini_emit_virtual_call (s, state, tree, CEE_CALL, OP_CALL_MEMBASE);
727 stmt: OP_VOIDCALLVIRT (reg) {
728 mini_emit_virtual_call (s, state, tree, OP_VOIDCALL, OP_VOIDCALL_MEMBASE);
731 freg: OP_FCALLVIRT (reg) {
732 mini_emit_virtual_call (s, state, tree, OP_FCALL, OP_FCALL_MEMBASE);
735 stmt: OP_VCALLVIRT (reg, reg) {
736 mini_emit_virtual_call (s, state, tree, OP_VCALL, OP_VCALL_MEMBASE);
739 reg: OP_CALL_REG (reg) {
740 tree->sreg1 = state->left->reg1;
741 tree->dreg = state->reg1;
742 mono_bblock_add_inst (s->cbb, tree);
746 mono_bblock_add_inst (s->cbb, tree);
749 stmt: OP_VOIDCALL_REG (reg) {
750 tree->sreg1 = state->left->reg1;
751 mono_bblock_add_inst (s->cbb, tree);
755 tree->dreg = state->reg1;
756 mono_bblock_add_inst (s->cbb, tree);
759 freg: OP_FCALL_REG (reg) {
760 tree->sreg1 = state->left->reg1;
761 tree->dreg = state->reg1;
762 mono_bblock_add_inst (s->cbb, tree);
765 stmt: OP_VCALL (reg) {
766 mono_arch_emit_this_vret_args (s, (MonoCallInst*)tree, -1, -1, state->left->reg1);
767 mono_bblock_add_inst (s->cbb, tree);
770 stmt: OP_VCALL_REG (reg, reg) {
771 mono_arch_emit_this_vret_args (s, (MonoCallInst*)tree, -1, -1, state->right->reg1);
773 tree->sreg1 = state->left->reg1;
774 mono_bblock_add_inst (s->cbb, tree);
778 stmt: OP_RESTORE_LMF {
779 mono_bblock_add_inst (s->cbb, tree);
783 # Optimized call instructions
786 reg: OP_CALL_REG (OP_ICONST),
787 reg: OP_CALL_REG (OP_I8CONST) {
788 tree->opcode = CEE_CALL;
789 ((MonoCallInst*)tree)->fptr = state->left->tree->inst_p0;
790 tree->dreg = state->reg1;
791 mono_bblock_add_inst (s->cbb, tree);
794 stmt: OP_VOIDCALL_REG (OP_ICONST),
795 stmt: OP_VOIDCALL_REG (OP_I8CONST) {
796 tree->opcode = OP_VOIDCALL;
797 ((MonoCallInst*)tree)->fptr = state->left->tree->inst_p0;
798 mono_bblock_add_inst (s->cbb, tree);
801 freg: OP_FCALL_REG (OP_ICONST),
802 freg: OP_FCALL_REG (OP_I8CONST) {
803 tree->opcode = OP_FCALL;
804 ((MonoCallInst*)tree)->fptr = state->left->tree->inst_p0;
805 tree->dreg = state->reg1;
806 mono_bblock_add_inst (s->cbb, tree);
810 mono_bblock_add_inst (s->cbb, tree);
815 # remove some common pops without side effects
816 stmt: CEE_POP (OP_ICONST)
817 stmt: CEE_POP (CEE_LDIND_I1 (base))
818 stmt: CEE_POP (CEE_LDIND_U1 (base))
819 stmt: CEE_POP (CEE_LDIND_I2 (base))
820 stmt: CEE_POP (CEE_LDIND_U2 (base))
821 stmt: CEE_POP (CEE_LDIND_I4 (base))
822 stmt: CEE_POP (CEE_LDIND_U4 (base))
823 stmt: CEE_POP (CEE_LDIND_I (base))
824 stmt: CEE_POP (CEE_LDIND_REF (base))
825 stmt: CEE_POP (CEE_LDIND_I1 (OP_REGVAR))
826 stmt: CEE_POP (CEE_LDIND_U1 (OP_REGVAR))
827 stmt: CEE_POP (CEE_LDIND_I2 (OP_REGVAR))
828 stmt: CEE_POP (CEE_LDIND_U2 (OP_REGVAR))
829 stmt: CEE_POP (CEE_LDIND_I4 (OP_REGVAR))
830 stmt: CEE_POP (CEE_LDIND_U4 (OP_REGVAR))
831 stmt: CEE_POP (CEE_LDIND_I (OP_REGVAR))
832 stmt: CEE_POP (CEE_LDIND_REF (OP_REGVAR))
835 mono_bblock_add_inst (s->cbb, tree);
840 stmt: CEE_THROW (reg) {
841 MONO_EMIT_UNALU (s, tree, CEE_THROW, -1, state->left->reg1);
844 stmt: OP_RETHROW (reg) {
845 MONO_EMIT_UNALU (s, tree, OP_RETHROW, -1, state->left->reg1);
848 stmt: OP_THROW_OR_NULL (reg) {
849 MonoInst *object_is_null;
851 MONO_NEW_LABEL (s, object_is_null);
853 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, 0, state->left->reg1, 0);
854 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, object_is_null);
855 MONO_EMIT_UNALU (s, tree, CEE_THROW, -1, state->left->reg1);
856 mono_bblock_add_inst (s->cbb, object_is_null);
859 stmt: CEE_THROW (CEE_LDIND_REF (OP_REGVAR)) {
860 MONO_EMIT_UNALU (s, tree, CEE_THROW, -1, state->left->left->tree->dreg);
863 stmt: OP_CALL_HANDLER {
864 mono_bblock_add_inst (s->cbb, tree);
867 stmt: OP_START_HANDLER "2" {
868 mono_bblock_add_inst (s->cbb, tree);
871 stmt: CEE_ENDFINALLY "2" {
872 mono_bblock_add_inst (s->cbb, tree);
875 stmt: OP_ENDFILTER (reg) "2" {
876 MONO_EMIT_UNALU (s, tree, OP_ENDFILTER, -1, state->left->reg1);
879 stmt: OP_CHECK_THIS (reg) {
880 tree->sreg1 = state->left->reg1;
881 tree->dreg = state->reg1;
882 mono_bblock_add_inst (s->cbb, tree);
885 # object related opcodes
887 reg: CEE_ISINST (reg) {
888 MonoClass *klass = tree->inst_newa_class;
889 MonoInst *object_is_null, *end_label, *false_label;
890 int obj_reg = state->left->reg1;
891 int vtable_reg = mono_regstate_next_int (s->rs);
893 MONO_NEW_LABEL (s, object_is_null);
894 MONO_NEW_LABEL (s, end_label);
895 MONO_NEW_LABEL (s, false_label);
897 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, obj_reg, 0);
898 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, object_is_null);
900 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
901 MONO_EMIT_NEW_LOAD_MEMBASE (s, vtable_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
902 /* the object_is_null target simply copies the input register to the output */
903 mini_emit_isninst_iface_cast (s, vtable_reg, klass, false_label, object_is_null);
905 int klass_reg = mono_regstate_next_int (s->rs);
907 MONO_EMIT_NEW_LOAD_MEMBASE (s, vtable_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
908 MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, klass));
911 int rank_reg = mono_regstate_next_int (s->rs);
912 int eclass_reg = mono_regstate_next_int (s->rs);
914 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, rank_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, rank));
915 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, rank_reg, klass->rank);
916 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, false_label);
917 MONO_EMIT_NEW_LOAD_MEMBASE (s, eclass_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, cast_class));
918 if (klass->cast_class == mono_defaults.object_class) {
919 int parent_reg = mono_regstate_next_int (s->rs);
921 MONO_EMIT_NEW_LOAD_MEMBASE (s, parent_reg, eclass_reg, G_STRUCT_OFFSET (MonoClass, parent));
922 if (mono_compile_aot) {
923 const_reg = mono_regstate_next_int (s->rs);
924 MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class->parent);
925 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, parent_reg, const_reg);
927 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, parent_reg, mono_defaults.enum_class->parent);
929 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, object_is_null);
930 if (mono_compile_aot) {
931 MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class);
932 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
934 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class);
936 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, object_is_null);
937 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, false_label);
938 } else if (klass->cast_class == mono_defaults.enum_class->parent) {
941 if (mono_compile_aot) {
942 const_reg = mono_regstate_next_int (s->rs);
943 MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class->parent);
944 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
946 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class->parent);
948 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, object_is_null);
949 if (mono_compile_aot) {
950 MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class);
951 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
953 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class);
955 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, object_is_null);
956 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, false_label);
957 } else if (klass->cast_class == mono_defaults.enum_class) {
958 if (mono_compile_aot) {
959 int const_reg = mono_regstate_next_int (s->rs);
960 MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class);
961 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
963 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class);
965 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, object_is_null);
966 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, false_label);
967 } else if (klass->cast_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
968 mini_emit_isninst_iface_class_cast (s, eclass_reg, klass->cast_class, false_label, object_is_null);
970 if ((klass->rank == 1) && (klass->byval_arg.type == MONO_TYPE_SZARRAY)) {
971 /* Check that the object is a vector too */
972 int bounds_reg = mono_regstate_next_int (s->rs);
973 MONO_EMIT_NEW_LOAD_MEMBASE (s, bounds_reg, obj_reg, G_STRUCT_OFFSET (MonoArray, bounds));
974 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, bounds_reg, 0);
975 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, false_label);
978 /* the object_is_null target simply copies the input register to the output */
979 mini_emit_isninst_cast (s, eclass_reg, klass->cast_class, false_label, object_is_null);
982 /* the object_is_null target simply copies the input register to the output */
983 mini_emit_isninst_cast (s, klass_reg, klass, false_label, object_is_null);
987 mono_bblock_add_inst (s->cbb, false_label);
988 MONO_EMIT_NEW_ICONST (s, state->reg1, 0);
989 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, end_label);
990 mono_bblock_add_inst (s->cbb, object_is_null);
991 MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, obj_reg);
992 mono_bblock_add_inst (s->cbb, end_label);
995 reg: OP_CISINST (reg) {
996 /* This opcode takes as input an object reference and a class, and returns:
997 0) if the object is an instance of the class,
998 1) if the object is not instance of the class,
999 2) if the object is a proxy whose type cannot be determined */
1001 MonoClass *klass = tree->inst_newa_class;
1002 MonoInst *end_label, *true_label, *false_label, *false2_label;
1003 MonoInst *no_proxy_label, *interface_fail_label;
1004 int obj_reg = state->left->reg1;
1005 int tmp_reg = mono_regstate_next_int (s->rs);
1006 int klass_reg = mono_regstate_next_int (s->rs);
1008 MONO_NEW_LABEL (s, end_label);
1009 MONO_NEW_LABEL (s, true_label);
1010 MONO_NEW_LABEL (s, false_label);
1011 MONO_NEW_LABEL (s, false2_label);
1013 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, obj_reg, 0);
1014 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, false_label);
1016 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1017 MONO_NEW_LABEL (s, interface_fail_label);
1018 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
1019 mini_emit_isninst_iface_cast (s, tmp_reg, klass, interface_fail_label, true_label);
1021 mono_bblock_add_inst (s->cbb, interface_fail_label);
1022 MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, tmp_reg, G_STRUCT_OFFSET (MonoVTable, klass));
1024 if (mono_compile_aot) {
1025 int tproxy_reg = mono_regstate_next_int (s->rs);
1026 MONO_EMIT_NEW_CLASSCONST (s, tproxy_reg, mono_defaults.transparent_proxy_class);
1027 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, klass_reg, tproxy_reg);
1029 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, klass_reg, mono_defaults.transparent_proxy_class);
1031 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, false_label);
1033 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info));
1034 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, tmp_reg, 0);
1035 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, false2_label);
1038 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
1039 MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, tmp_reg, G_STRUCT_OFFSET (MonoVTable, klass));
1041 MONO_NEW_LABEL (s, no_proxy_label);
1043 if (mono_compile_aot) {
1044 int tproxy_reg = mono_regstate_next_int (s->rs);
1045 MONO_EMIT_NEW_CLASSCONST (s, tproxy_reg, mono_defaults.transparent_proxy_class);
1046 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, klass_reg, tproxy_reg);
1048 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, klass_reg, mono_defaults.transparent_proxy_class);
1050 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, no_proxy_label);
1051 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, remote_class));
1052 MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, tmp_reg, G_STRUCT_OFFSET (MonoRemoteClass, proxy_class));
1054 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info));
1055 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, tmp_reg, 0);
1056 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, no_proxy_label);
1058 mini_emit_isninst_cast (s, klass_reg, klass, false2_label, true_label);
1059 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, false2_label);
1061 mono_bblock_add_inst (s->cbb, no_proxy_label);
1062 mini_emit_isninst_cast (s, klass_reg, klass, false_label, true_label);
1065 mono_bblock_add_inst (s->cbb, false_label);
1066 MONO_EMIT_NEW_ICONST (s, state->reg1, 1);
1067 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, end_label);
1068 mono_bblock_add_inst (s->cbb, false2_label);
1069 MONO_EMIT_NEW_ICONST (s, state->reg1, 2);
1070 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, end_label);
1071 mono_bblock_add_inst (s->cbb, true_label);
1072 MONO_EMIT_NEW_ICONST (s, state->reg1, 0);
1073 mono_bblock_add_inst (s->cbb, end_label);
1076 reg: OP_UNBOXCAST (reg) {
1077 MonoClass *klass = tree->inst_newa_class;
1078 int obj_reg = state->left->reg1;
1079 int vtable_reg = mono_regstate_next_int (s->rs);
1080 int klass_reg = mono_regstate_next_int (s->rs);
1081 int eclass_reg = mono_regstate_next_int (s->rs);
1082 int rank_reg = mono_regstate_next_int (s->rs);
1084 MONO_EMIT_NEW_LOAD_MEMBASE (s, vtable_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
1085 MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, klass));
1086 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, rank_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, rank));
1087 MONO_EMIT_NEW_LOAD_MEMBASE (s, eclass_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, element_class));
1089 /* FIXME: generics */
1090 g_assert (klass->rank == 0);
1093 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, rank_reg, 0);
1094 MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1096 if (mono_compile_aot) {
1097 int const_reg = mono_regstate_next_int (s->rs);
1098 MONO_EMIT_NEW_CLASSCONST (s, const_reg, klass->element_class);
1099 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
1102 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, klass->element_class);
1105 MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1106 MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, obj_reg);
1109 reg: CEE_CASTCLASS (reg) {
1110 MonoClass *klass = tree->inst_newa_class;
1111 MonoInst *object_is_null;
1112 int obj_reg = state->left->reg1;
1113 int vtable_reg = mono_regstate_next_int (s->rs);
1115 MONO_NEW_LABEL (s, object_is_null);
1117 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, obj_reg, 0);
1118 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, object_is_null);
1120 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1121 MONO_EMIT_NEW_LOAD_MEMBASE (s, vtable_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
1122 mini_emit_castclass_iface (s, vtable_reg, klass);
1124 int klass_reg = mono_regstate_next_int (s->rs);
1126 MONO_EMIT_NEW_LOAD_MEMBASE (s, vtable_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
1127 MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, klass));
1130 int rank_reg = mono_regstate_next_int (s->rs);
1131 int eclass_reg = mono_regstate_next_int (s->rs);
1133 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, rank_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, rank));
1134 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, rank_reg, klass->rank);
1135 MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1136 MONO_EMIT_NEW_LOAD_MEMBASE (s, eclass_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, cast_class));
1137 if (klass->cast_class == mono_defaults.object_class) {
1138 int parent_reg = mono_regstate_next_int (s->rs);
1140 MONO_EMIT_NEW_LOAD_MEMBASE (s, parent_reg, eclass_reg, G_STRUCT_OFFSET (MonoClass, parent));
1141 if (mono_compile_aot) {
1142 const_reg = mono_regstate_next_int (s->rs);
1143 MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class->parent);
1144 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, parent_reg, const_reg);
1146 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, parent_reg, mono_defaults.enum_class->parent);
1148 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, object_is_null);
1149 if (mono_compile_aot) {
1150 MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class);
1151 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
1153 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class);
1155 MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1156 } else if (klass->cast_class == mono_defaults.enum_class->parent) {
1157 int const_reg = mono_regstate_next_int (s->rs);
1158 if (mono_compile_aot) {
1159 MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class->parent);
1160 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
1162 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class->parent);
1164 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, object_is_null);
1165 if (mono_compile_aot) {
1166 MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class);
1167 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
1169 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class);
1171 MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1172 } else if (klass->cast_class == mono_defaults.enum_class) {
1173 if (mono_compile_aot) {
1174 int const_reg = mono_regstate_next_int (s->rs);
1175 MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class);
1176 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
1178 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class);
1180 MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1181 } else if (klass->cast_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
1182 mini_emit_castclass_iface_class (s, eclass_reg, klass->cast_class);
1184 mini_emit_castclass (s, eclass_reg, klass->cast_class);
1187 if ((klass->rank == 1) && (klass->byval_arg.type == MONO_TYPE_SZARRAY)) {
1188 /* Check that the object is a vector too */
1189 int bounds_reg = mono_regstate_next_int (s->rs);
1190 MONO_EMIT_NEW_LOAD_MEMBASE (s, bounds_reg, obj_reg, G_STRUCT_OFFSET (MonoArray, bounds));
1191 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, bounds_reg, 0);
1192 MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1195 mini_emit_castclass (s, klass_reg, klass);
1199 mono_bblock_add_inst (s->cbb, object_is_null);
1200 MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, obj_reg);
1203 reg: OP_CCASTCLASS (reg) {
1204 /* This opcode takes as input an object reference and a class, and returns:
1205 0) if the object is an instance of the class,
1206 1) if the object is a proxy whose type cannot be determined
1207 an InvalidCastException exception is thrown otherwhise*/
1209 MonoClass *klass = tree->inst_newa_class;
1210 MonoInst *end_label, *fail_label, *no_proxy_label, *ok_result_label;
1211 int obj_reg = state->left->reg1;
1212 int tmp_reg = mono_regstate_next_int (s->rs);
1213 int klass_reg = mono_regstate_next_int (s->rs);
1215 MONO_NEW_LABEL (s, end_label);
1216 MONO_NEW_LABEL (s, ok_result_label);
1218 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, obj_reg, 0);
1219 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, ok_result_label);
1221 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1223 MONO_NEW_LABEL (s, fail_label);
1225 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
1226 mini_emit_isninst_iface_cast (s, tmp_reg, klass, fail_label, ok_result_label);
1228 mono_bblock_add_inst (s->cbb, fail_label);
1229 MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, tmp_reg, G_STRUCT_OFFSET (MonoVTable, klass));
1231 if (mono_compile_aot) {
1232 int tproxy_reg = mono_regstate_next_int (s->rs);
1233 MONO_EMIT_NEW_CLASSCONST (s, tproxy_reg, mono_defaults.transparent_proxy_class);
1234 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, klass_reg, tproxy_reg);
1236 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, klass_reg, mono_defaults.transparent_proxy_class);
1239 MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1241 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, remote_class));
1242 MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, tmp_reg, G_STRUCT_OFFSET (MonoRemoteClass, proxy_class));
1244 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info));
1245 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, tmp_reg, 0);
1246 MONO_EMIT_NEW_COND_EXC (s, EQ, "InvalidCastException");
1248 MONO_EMIT_NEW_ICONST (s, state->reg1, 1);
1249 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, end_label);
1253 MONO_NEW_LABEL (s, no_proxy_label);
1254 MONO_NEW_LABEL (s, fail_label);
1256 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
1257 MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, tmp_reg, G_STRUCT_OFFSET (MonoVTable, klass));
1259 if (mono_compile_aot) {
1260 int tproxy_reg = mono_regstate_next_int (s->rs);
1261 MONO_EMIT_NEW_CLASSCONST (s, tproxy_reg, mono_defaults.transparent_proxy_class);
1262 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, klass_reg, tproxy_reg);
1264 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, klass_reg, mono_defaults.transparent_proxy_class);
1266 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, no_proxy_label);
1268 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, remote_class));
1269 MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, tmp_reg, G_STRUCT_OFFSET (MonoRemoteClass, proxy_class));
1271 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info));
1272 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, tmp_reg, 0);
1273 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, no_proxy_label);
1275 mini_emit_isninst_cast (s, klass_reg, klass, fail_label, ok_result_label);
1276 mono_bblock_add_inst (s->cbb, fail_label);
1277 MONO_EMIT_NEW_ICONST (s, state->reg1, 1);
1278 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, end_label);
1280 mono_bblock_add_inst (s->cbb, no_proxy_label);
1281 mini_emit_castclass (s, klass_reg, klass);
1284 mono_bblock_add_inst (s->cbb, ok_result_label);
1285 MONO_EMIT_NEW_ICONST (s, state->reg1, 0);
1286 mono_bblock_add_inst (s->cbb, end_label);
1289 stmt: CEE_STELEM_REF (OP_GROUP (reg, reg), reg),
1290 reg: OP_GROUP (reg, reg),
1291 reg: CEE_NEWARR (reg),
1292 lreg: OP_LMUL (lreg, lreg),
1293 lreg: OP_LMUL_OVF (lreg, lreg),
1294 lreg: OP_LMUL_OVF_UN (lreg, lreg),
1295 lreg: OP_LDIV (lreg, lreg),
1296 lreg: OP_LDIV_UN (lreg, lreg),
1297 lreg: OP_LREM (lreg, lreg),
1298 lreg: OP_LREM_UN (lreg, lreg),
1299 lreg: OP_LSHL (lreg, reg),
1300 lreg: OP_LSHR (lreg, reg),
1301 lreg: OP_LSHR_UN (lreg, reg) {
1302 g_assert_not_reached ();
1308 reg: OP_GETCHR (reg, reg) {
1309 int mult_reg = mono_regstate_next_int (s->rs);
1310 int add_reg = mono_regstate_next_int (s->rs);
1312 MONO_EMIT_BOUNDS_CHECK (s, state->left->reg1, MonoString, length, state->right->reg1);
1313 MONO_EMIT_NEW_BIALU_IMM (s, OP_SHL_IMM, mult_reg, state->right->reg1, 1);
1314 MONO_EMIT_NEW_BIALU (s, CEE_ADD, add_reg, mult_reg, state->left->reg1);
1315 MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADU2_MEMBASE, state->reg1,
1316 add_reg, G_STRUCT_OFFSET (MonoString, chars));
1319 reg: OP_GETCHR (reg, OP_ICONST) {
1320 int ind = 2 * state->right->tree->inst_c0 + G_STRUCT_OFFSET (MonoString, chars);
1322 MONO_EMIT_BOUNDS_CHECK_IMM (s, state->left->reg1, MonoString, length, state->right->tree->inst_c0);
1323 MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADU2_MEMBASE, state->reg1, state->left->reg1, ind);
1326 reg: OP_STRLEN (reg) {
1327 MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI4_MEMBASE, state->reg1,
1328 state->left->reg1, G_STRUCT_OFFSET (MonoString, length));
1331 reg: OP_GETTYPE (reg) {
1332 int vt_reg = mono_regstate_next_int (s->rs);
1333 MONO_EMIT_NEW_LOAD_MEMBASE (s, vt_reg, state->left->reg1, G_STRUCT_OFFSET (MonoObject, vtable));
1334 MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOAD_MEMBASE, state->reg1, vt_reg, G_STRUCT_OFFSET (MonoVTable, type));
1340 reg: CEE_LDLEN (reg) {
1341 MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI4_MEMBASE, state->reg1,
1342 state->left->reg1, G_STRUCT_OFFSET (MonoArray, max_length));
1345 reg: OP_ARRAY_RANK (reg) {
1346 int vtable_reg = mono_regstate_next_int (s->rs);
1347 int class_reg = mono_regstate_next_int (s->rs);
1348 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOAD_MEMBASE, vtable_reg,
1349 state->left->reg1, G_STRUCT_OFFSET (MonoObject, vtable));
1350 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOAD_MEMBASE, class_reg,
1351 vtable_reg, G_STRUCT_OFFSET (MonoVTable, klass));
1352 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, state->reg1,
1353 class_reg, G_STRUCT_OFFSET (MonoClass, rank));
1356 reg: OP_CHECK_ARRAY_TYPE (reg) {
1357 int vtable_reg = mono_regstate_next_int (s->rs);
1358 int class_reg = mono_regstate_next_int (s->rs);
1359 int elclass_reg = mono_regstate_next_int (s->rs);
1361 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOAD_MEMBASE, vtable_reg,
1362 state->left->reg1, G_STRUCT_OFFSET (MonoObject, vtable));
1363 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOAD_MEMBASE, class_reg,
1364 vtable_reg, G_STRUCT_OFFSET (MonoVTable, klass));
1365 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOAD_MEMBASE, elclass_reg,
1366 class_reg, G_STRUCT_OFFSET (MonoClass, element_class));
1367 if (mono_compile_aot) {
1368 int klass_reg = mono_regstate_next_int (s->rs);
1369 MONO_EMIT_NEW_CLASSCONST (s, klass_reg, tree->klass);
1370 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, elclass_reg, klass_reg);
1372 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, elclass_reg, tree->klass);
1375 MONO_EMIT_NEW_COND_EXC (s, NE_UN, "ArrayTypeMismatchException");
1376 MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
1379 reg: CEE_LDELEMA (reg, OP_ICONST) "15" {
1380 guint32 size = mono_class_array_element_size (tree->klass);
1382 int ind = size * state->right->tree->inst_c0 + G_STRUCT_OFFSET (MonoArray, vector);
1384 MONO_EMIT_BOUNDS_CHECK_IMM (s, state->left->reg1, MonoArray, max_length, state->right->tree->inst_c0);
1385 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, state->left->reg1, ind);
1388 reg: CEE_LDELEMA (reg, reg) "20" {
1389 int mult_reg = mono_regstate_next_int (s->rs);
1390 int add_reg = mono_regstate_next_int (s->rs);
1391 guint32 size = mono_class_array_element_size (tree->klass);
1393 MONO_EMIT_BOUNDS_CHECK (s, state->left->reg1, MonoArray, max_length, state->right->reg1);
1394 MONO_EMIT_NEW_BIALU_IMM (s, OP_MUL_IMM, mult_reg, state->right->reg1, size);
1395 MONO_EMIT_NEW_BIALU (s, CEE_ADD, add_reg, mult_reg, state->left->reg1);
1396 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, add_reg, G_STRUCT_OFFSET (MonoArray, vector));
1399 reg: CEE_REFANYVAL (reg) {
1400 int klass_reg = mono_regstate_next_int (s->rs);
1401 MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, state->left->reg1, G_STRUCT_OFFSET (MonoTypedRef, klass));
1402 if (mono_compile_aot) {
1403 int const_reg = mono_regstate_next_int (s->rs);
1404 MONO_EMIT_NEW_CLASSCONST (s, const_reg, tree->inst_newa_class);
1405 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, klass_reg, const_reg);
1407 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, klass_reg, tree->inst_newa_class);
1409 MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1410 MONO_EMIT_NEW_LOAD_MEMBASE (s, state->reg1, state->left->reg1, G_STRUCT_OFFSET (MonoTypedRef, value));
1413 reg: OP_REFANYTYPE (reg) {
1414 MONO_EMIT_NEW_LOAD_MEMBASE (s, state->reg1, state->left->reg1, G_STRUCT_OFFSET (MonoTypedRef, type));
1417 stmt: CEE_MKREFANY (OP_GROUP (reg, OP_ICONST), reg),
1418 stmt: CEE_MKREFANY (OP_GROUP (reg, OP_I8CONST), reg) {
1419 MonoClass *klass = (MonoClass*)(tree->inst_left->inst_right->inst_p0);
1420 if (mono_compile_aot) {
1421 int const_reg = mono_regstate_next_int (s->rs);
1422 int type_reg = mono_regstate_next_int (s->rs);
1423 MONO_EMIT_NEW_CLASSCONST (s, const_reg, klass);
1424 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREP_MEMBASE_REG, state->right->reg1, G_STRUCT_OFFSET (MonoTypedRef, klass), const_reg);
1425 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, type_reg, const_reg, G_STRUCT_OFFSET (MonoClass, byval_arg));
1426 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREP_MEMBASE_REG, state->right->reg1, G_STRUCT_OFFSET (MonoTypedRef, type), type_reg);
1429 MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STOREP_MEMBASE_IMM, state->right->reg1, G_STRUCT_OFFSET (MonoTypedRef, type), &klass->byval_arg);
1430 MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STOREP_MEMBASE_IMM, state->right->reg1, G_STRUCT_OFFSET (MonoTypedRef, klass), klass);
1432 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREP_MEMBASE_REG, state->right->reg1, G_STRUCT_OFFSET (MonoTypedRef, value), state->left->left->reg1);
1438 * Emit code which checks whenever the interface id of @klass is smaller than
1439 * than the value given by max_iid_reg.
1442 mini_emit_max_iid_check (MonoCompile *s, int max_iid_reg, MonoClass *klass,
1443 MonoInst *false_target)
1445 if (mono_compile_aot) {
1446 int iid_reg = mono_regstate_next_int (s->rs);
1447 MONO_EMIT_NEW_AOTCONST (s, iid_reg, klass, MONO_PATCH_INFO_IID);
1448 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, max_iid_reg, iid_reg);
1451 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, max_iid_reg, klass->interface_id);
1453 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BLT_UN, false_target);
1455 MONO_EMIT_NEW_COND_EXC (s, LT_UN, "InvalidCastException");
1458 /* Same as above, but obtains max_iid from a vtable */
1460 mini_emit_max_iid_check_vtable (MonoCompile *s, int vtable_reg, MonoClass *klass,
1461 MonoInst *false_target)
1463 int max_iid_reg = mono_regstate_next_int (s->rs);
1465 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, max_iid_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, max_interface_id));
1466 mini_emit_max_iid_check (s, max_iid_reg, klass, false_target);
1469 /* Same as above, but obtains max_iid from a klass */
1471 mini_emit_max_iid_check_class (MonoCompile *s, int klass_reg, MonoClass *klass,
1472 MonoInst *false_target)
1474 int max_iid_reg = mono_regstate_next_int (s->rs);
1476 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, max_iid_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, max_interface_id));
1477 mini_emit_max_iid_check (s, max_iid_reg, klass, false_target);
1481 mini_emit_load_intf_reg (MonoCompile *s, int intf_reg, int ioffset_reg, MonoClass *klass)
1483 if (mono_compile_aot) {
1484 int iid_reg = mono_regstate_next_int (s->rs);
1485 MONO_EMIT_NEW_AOTCONST (s, iid_reg, klass, MONO_PATCH_INFO_IID);
1486 /* FIXME: Do a shift instead */
1487 #if SIZEOF_VOID_P == 8
1488 MONO_EMIT_NEW_BIALU_IMM (s, OP_SHL_IMM, iid_reg, iid_reg, 3);
1490 MONO_EMIT_NEW_BIALU_IMM (s, OP_SHL_IMM, iid_reg, iid_reg, 2);
1492 MONO_EMIT_NEW_BIALU (s, CEE_ADD, ioffset_reg, ioffset_reg, iid_reg);
1493 MONO_EMIT_NEW_LOAD_MEMBASE (s, intf_reg, ioffset_reg, 0);
1496 MONO_EMIT_NEW_LOAD_MEMBASE (s, intf_reg, ioffset_reg, klass->interface_id * SIZEOF_VOID_P);
1499 /* Emit code which loads <vtable_reg>->interface_offsets [klass->interface_id] */
1501 mini_emit_load_intf_reg_vtable (MonoCompile *s, int intf_reg, int vtable_reg, MonoClass *klass)
1503 int ioffset_reg = mono_regstate_next_int (s->rs);
1505 MONO_EMIT_NEW_LOAD_MEMBASE (s, ioffset_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, interface_offsets));
1506 mini_emit_load_intf_reg (s, intf_reg, ioffset_reg, klass);
1509 /* Emit code which loads <klass_reg>->interface_offsets [klass->interface_id] */
1511 mini_emit_load_intf_reg_class (MonoCompile *s, int intf_reg, int klass_reg, MonoClass *klass)
1513 int ioffset_reg = mono_regstate_next_int (s->rs);
1515 MONO_EMIT_NEW_LOAD_MEMBASE (s, ioffset_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, interface_offsets));
1516 mini_emit_load_intf_reg (s, intf_reg, ioffset_reg, klass);
1520 mini_emit_virtual_call (MonoCompile *cfg, void *st, MonoInst *tree, int novirtop, int virtop)
1522 MonoMethod *method = ((MonoCallInst*)tree)->method;
1523 int vtable_reg, slot_reg, this_reg;
1524 MBState *state = st;
1526 this_reg = state->left->reg1;
1527 mono_arch_emit_this_vret_args (cfg, (MonoCallInst*)tree, this_reg, state->left->tree->type, novirtop == OP_VCALL? state->right->reg1: -1);
1529 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
1530 ((method->flags & METHOD_ATTRIBUTE_FINAL) &&
1531 method->wrapper_type != MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)) {
1533 * the method is not virtual, we just need to ensure this is not null
1534 * and then we can call the method directly.
1536 if (method->klass->marshalbyref || method->klass == mono_defaults.object_class) {
1537 method = ((MonoCallInst*)tree)->method = mono_marshal_get_remoting_invoke_with_check (method);
1540 if (!method->string_ctor)
1541 MONO_EMIT_NEW_UNALU (cfg, OP_CHECK_THIS, -1, this_reg);
1543 tree->dreg = state->reg1;
1544 tree->opcode = novirtop;
1545 mono_bblock_add_inst (cfg->cbb, tree);
1549 vtable_reg = mono_regstate_next_int (cfg->rs);
1550 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, this_reg, G_STRUCT_OFFSET (MonoObject, vtable));
1551 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1552 slot_reg = mono_regstate_next_int (cfg->rs);
1553 mini_emit_load_intf_reg_vtable (cfg, slot_reg, vtable_reg, method->klass);
1554 tree->inst_offset = method->slot * SIZEOF_VOID_P;
1556 slot_reg = vtable_reg;
1557 tree->inst_offset = G_STRUCT_OFFSET (MonoVTable, vtable) + (method->slot * SIZEOF_VOID_P);
1560 tree->dreg = state->reg1;
1561 tree->opcode = virtop;
1562 tree->sreg1 = slot_reg;
1563 ((MonoCallInst*)tree)->virtual = TRUE;
1564 mono_bblock_add_inst (cfg->cbb, tree);
1568 mini_emit_isninst_cast (MonoCompile *s, int klass_reg, MonoClass *klass, MonoInst *false_target, MonoInst *true_target)
1570 int idepth_reg = mono_regstate_next_int (s->rs);
1571 int stypes_reg = mono_regstate_next_int (s->rs);
1572 int stype = mono_regstate_next_int (s->rs);
1574 if (klass->idepth > MONO_DEFAULT_SUPERTABLE_SIZE) {
1575 MONO_EMIT_NEW_LOAD_MEMBASE (s, idepth_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, idepth));
1576 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, idepth_reg, klass->idepth);
1577 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BLT_UN, false_target);
1579 MONO_EMIT_NEW_LOAD_MEMBASE (s, stypes_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, supertypes));
1580 MONO_EMIT_NEW_LOAD_MEMBASE (s, stype, stypes_reg, ((klass->idepth - 1) * SIZEOF_VOID_P));
1581 if (mono_compile_aot) {
1582 int const_reg = mono_regstate_next_int (s->rs);
1583 MONO_EMIT_NEW_CLASSCONST (s, const_reg, klass);
1584 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, stype, const_reg);
1586 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, stype, klass);
1588 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, true_target);
1592 mini_emit_isninst_iface_cast (MonoCompile *s, int vtable_reg, MonoClass *klass, MonoInst *false_target, MonoInst *true_target)
1594 int intf_reg = mono_regstate_next_int (s->rs);
1596 mini_emit_max_iid_check_vtable (s, vtable_reg, klass, false_target);
1597 mini_emit_load_intf_reg_vtable (s, intf_reg, vtable_reg, klass);
1598 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, intf_reg, 0);
1599 /* the object_is_null target simply copies the input register to the output */
1600 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, true_target);
1604 * Variant of the above that takes a register to the class, not the vtable.
1605 * Note that inside interfaces_offsets the empty value is -1, not NULL, in this case.
1608 mini_emit_isninst_iface_class_cast (MonoCompile *s, int klass_reg, MonoClass *klass, MonoInst *false_target, MonoInst *true_target)
1610 int intf_reg = mono_regstate_next_int (s->rs);
1612 mini_emit_max_iid_check_class (s, klass_reg, klass, false_target);
1613 mini_emit_load_intf_reg_class (s, intf_reg, klass_reg, klass);
1614 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, intf_reg, -1);
1615 /* the object_is_null target simply copies the input register to the output */
1616 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BGE, true_target);
1620 mini_emit_castclass (MonoCompile *s, int klass_reg, MonoClass *klass)
1622 int idepth_reg = mono_regstate_next_int (s->rs);
1623 int stypes_reg = mono_regstate_next_int (s->rs);
1624 int stype = mono_regstate_next_int (s->rs);
1626 if (klass->idepth > MONO_DEFAULT_SUPERTABLE_SIZE) {
1627 MONO_EMIT_NEW_LOAD_MEMBASE (s, idepth_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, idepth));
1628 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, idepth_reg, klass->idepth);
1629 MONO_EMIT_NEW_COND_EXC (s, LT_UN, "InvalidCastException");
1631 MONO_EMIT_NEW_LOAD_MEMBASE (s, stypes_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, supertypes));
1632 MONO_EMIT_NEW_LOAD_MEMBASE (s, stype, stypes_reg, ((klass->idepth - 1) * SIZEOF_VOID_P));
1633 if (mono_compile_aot) {
1634 int const_reg = mono_regstate_next_int (s->rs);
1635 MONO_EMIT_NEW_CLASSCONST (s, const_reg, klass);
1636 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, stype, const_reg);
1638 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, stype, klass);
1640 MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1644 mini_emit_castclass_iface (MonoCompile *s, int vtable_reg, MonoClass *klass)
1646 int intf_reg = mono_regstate_next_int (s->rs);
1648 mini_emit_max_iid_check_vtable (s, vtable_reg, klass, NULL);
1649 mini_emit_load_intf_reg_vtable (s, intf_reg, vtable_reg, klass);
1650 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, intf_reg, 0);
1651 MONO_EMIT_NEW_COND_EXC (s, EQ, "InvalidCastException");
1655 * Variant of the aboce that takes a register to the class, not the vtable.
1656 * Note that inside interfaces_offsets the empty value is -1, not NULL, in this case.
1659 mini_emit_castclass_iface_class (MonoCompile *s, int klass_reg, MonoClass *klass)
1661 int intf_reg = mono_regstate_next_int (s->rs);
1663 mini_emit_max_iid_check_class (s, klass_reg, klass, NULL);
1664 mini_emit_load_intf_reg_class (s, intf_reg, klass_reg, klass);
1665 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, intf_reg, -1);
1666 MONO_EMIT_NEW_COND_EXC (s, EQ, "InvalidCastException");
1670 mini_emit_memcpy (MonoCompile *s, int destreg, int doffset, int srcreg, int soffset, int size, int align)
1674 /* FIXME: consider alignment for archs that need it. */
1675 #if !NO_UNALIGNED_ACCESS
1676 if (sizeof (gpointer) == 8) {
1678 cur_reg = mono_regstate_next_int (s->rs);
1679 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI8_MEMBASE, cur_reg, srcreg, soffset);
1680 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI8_MEMBASE_REG, destreg, doffset, cur_reg);
1689 cur_reg = mono_regstate_next_int (s->rs);
1690 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, cur_reg, srcreg, soffset);
1691 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, destreg, doffset, cur_reg);
1697 cur_reg = mono_regstate_next_int (s->rs);
1698 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI2_MEMBASE, cur_reg, srcreg, soffset);
1699 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI2_MEMBASE_REG, destreg, doffset, cur_reg);
1705 cur_reg = mono_regstate_next_int (s->rs);
1706 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI1_MEMBASE, cur_reg, srcreg, soffset);
1707 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI1_MEMBASE_REG, destreg, doffset, cur_reg);
1715 mini_emit_memset (MonoCompile *s, int destreg, int offset, int size, int val, int alignl)
1717 int val_reg = mono_regstate_next_int (s->rs);
1719 if (sizeof (gpointer) == 8)
1720 MONO_EMIT_NEW_I8CONST (s, val_reg, val);
1722 MONO_EMIT_NEW_ICONST (s, val_reg, val);
1724 if (sizeof (gpointer) == 8) {
1726 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI8_MEMBASE_REG, destreg, offset, val_reg);
1733 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, destreg, offset, val_reg);
1738 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI2_MEMBASE_REG, destreg, offset, val_reg);
1743 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI1_MEMBASE_REG, destreg, offset, val_reg);
1750 ldind_to_load_membase (int opcode)
1754 return OP_LOADI1_MEMBASE;
1756 return OP_LOADU1_MEMBASE;
1758 return OP_LOADI2_MEMBASE;
1760 return OP_LOADU2_MEMBASE;
1762 return OP_LOADI4_MEMBASE;
1764 return OP_LOADU4_MEMBASE;
1766 return OP_LOAD_MEMBASE;
1768 return OP_LOAD_MEMBASE;
1770 g_assert_not_reached ();