-
Notifications
You must be signed in to change notification settings - Fork 86
/
Copy pathNewarr.cs
81 lines (67 loc) · 3.73 KB
/
Newarr.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/*
* PROJECT: Atomix Development
* LICENSE: BSD 3-Clause (LICENSE.md)
* PURPOSE: Newarr MSIL
* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com)
*/
using System;
using System.Reflection;
using Atomixilc.Machine;
using Atomixilc.Attributes;
using Atomixilc.Machine.x86;
using Atomixilc.IL.CodeType;
namespace Atomixilc.IL
{
[ILImpl(ILCode.Newarr)]
internal class Newarr_il : MSIL
{
public Newarr_il()
: base(ILCode.Newarr)
{
}
/*
* URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Newarr(v=vs.110).aspx
* Description : Pushes an object reference to a new zero-based, one-dimensional array whose elements are of a specific type onto the evaluation stack.
*/
internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer)
{
if (Optimizer.vStack.Count < 1)
throw new Exception("Internal Compiler Error: vStack.Count < 1");
var type = ((OpType)xOp).Value;
var size = Helper.GetTypeSize(type, Config.TargetPlatform);
/* The stack transitional behavior, in sequential order, is:
* The number of elements in the array is pushed onto the stack.
* The number of elements is popped from the stack and the array is created.
* An object reference to the new array is pushed onto the stack.
*/
var item = Optimizer.vStack.Pop();
switch (Config.TargetPlatform)
{
case Architecture.x86:
{
if (!item.SystemStack)
throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL));
new Mov { DestinationReg = Register.ESI, SourceReg = Register.ESP, SourceIndirect = true };
new Mov { DestinationReg = Register.EAX, SourceRef = "0x" + size.ToString() };
new Mul { DestinationReg = Register.ESI };
new Add { DestinationReg = Register.EAX, SourceRef = "0x10" };
new Push { DestinationReg = Register.EAX };
new Call { DestinationRef = Helper.Heap_Label, IsLabel = true };
new Test { DestinationReg = Register.ECX, SourceRef = "0xFFFFFFFF" };
new Jmp { Condition = ConditionalJump.JNZ, DestinationRef = xOp.HandlerRef };
new Pop { DestinationReg = Register.ESI };
new Mov { DestinationReg = Register.EAX, DestinationIndirect = true, SourceRef = "0x" + type.GetHashCode().ToString("X") };
new Mov { DestinationReg = Register.EAX, DestinationIndirect = true, DestinationDisplacement = 4, SourceRef = "0x" + (0x2 | (type.IsClass ? 0x1 : 0x0)).ToString("X") };
new Mov { DestinationReg = Register.EAX, DestinationIndirect = true, DestinationDisplacement = 8, SourceReg = Register.ESI };
new Mov { DestinationReg = Register.EAX, DestinationIndirect = true, DestinationDisplacement = 12, SourceRef = "0x" + size.ToString("X") };
new Push { DestinationReg = Register.EAX };
Optimizer.vStack.Push(new StackItem(typeof(Array)));
Optimizer.SaveStack(xOp.NextPosition);
}
break;
default:
throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL));
}
}
}
}