Ejemplo n.º 1
0
        public static Instruction Push(object value) {
            if (value == null) {
                return _null ?? (_null = new PushInstruction(null));
            }

            if (value is bool) {
                if ((bool)value) {
                    return _true ?? (_true = new PushInstruction(value));
                } else {
                    return _false ?? (_false = new PushInstruction(value));
                }
            }

            if (value is int) {
                int i = (int)value;
                if (i >= PushIntMinCachedValue && i <= PushIntMaxCachedValue) {
                    if (_ints == null) {
                        _ints = new Instruction[PushIntMaxCachedValue - PushIntMinCachedValue + 1];
                    }
                    i -= PushIntMinCachedValue;
                    return _ints[i] ?? (_ints[i] = new PushInstruction(value));
                }
            }

            return new PushInstruction(value);
        }
Ejemplo n.º 2
0
        private static CodeInfo DeserializeAssembly(string name, IEnumerable <Instruction> instructions, uint bcv,
                                                    StringsListBuilder strings, IDictionary <string, uint> objectIndices)
        {
            uint size   = 0;
            var  labels = new Dictionary <string, uint>();

            foreach (var inst in instructions)
            {
                if (inst is Label labelInst)
                {
                    if (labelInst.LabelValue is string label)
                    {
                        labels[label] = size * sizeof(int);
                    }
                }
                else
                {
                    size += InstSize(inst, bcv);
                }
            }

            IList <Tuple <ReferenceSignature, uint> > functionReferences = new List <Tuple <ReferenceSignature, uint> >();
            IList <Tuple <ReferenceSignature, uint> > variableReferences = new List <Tuple <ReferenceSignature, uint> >();

            var binaryInstructions = new List <AnyInstruction>();

            size = 0;
            foreach (var inst in instructions)
            {
                if (inst is Label)
                {
                    continue;
                }
                var op = new OpCodes {
                    VersionE = inst.OpCode.VersionE, VersionF = inst.OpCode.VersionF
                };
                var            type    = DisasmExt.Kind(op, bcv);
                AnyInstruction bininst = new AnyInstruction();
                switch (type)
                {
                case InstructionKind.Set:
                    var setinst = (Set)inst;
                    bininst.Set = new SetInstruction
                    {
                        DestVar  = new Reference(setinst.VariableType, 0),
                        Instance = GetInstanceType(setinst.InstanceType, setinst.InstanceName, objectIndices),
                        OpCode   = op,
                        Types    = new TypePair(setinst.Type1, setinst.Type2)
                    };
                    variableReferences.Add(new Tuple <ReferenceSignature, uint>(new ReferenceSignature
                    {
                        Name          = setinst.TargetVariable,
                        InstanceType  = setinst.InstanceType,
                        Instance      = setinst.InstanceType == InstanceType.Local ? name : null,
                        VariableType  = setinst.VariableType,
                        VariableIndex = setinst.VariableIndex
                    }, size));
                    break;

                case InstructionKind.Push:
                    var bp = new PushInstruction
                    {
                        OpCode = op,
                        Type   = ((Push)inst).Type
                    };
                    if (bp.Type == DataType.Variable)
                    {
                        var p = (PushVariable)inst;
                        bp.Value     = (short)GetInstanceType(p.InstanceType, p.InstanceName, objectIndices);
                        bp.ValueRest = new Reference(p.VariableType, 0).val;
                        variableReferences.Add(new Tuple <ReferenceSignature, uint>(new ReferenceSignature
                        {
                            Name          = p.VariableName,
                            InstanceType  = p.InstanceType,
                            Instance      = p.InstanceType == InstanceType.Local ? name : null,
                            VariableType  = p.VariableType,
                            VariableIndex = p.VariableIndex
                        }, size));
                    }
                    else
                    {
                        var p = (PushConst)inst;
                        switch (p.Type)
                        {
                        case DataType.Int16:
                            bp.Value = (short)(long)p.Value;
                            break;

                        case DataType.Boolean:
                            bp.ValueRest = (uint)(long)p.Value;
                            break;

                        case DataType.Double:
                        case DataType.Single:
                            bp.ValueRest = BitConverter.ToUInt64(BitConverter.GetBytes(Convert.ToDouble(p.Value)), 0);
                            break;

                        case DataType.Int32:
                        case DataType.Int64:
                            bp.ValueRest = BitConverter.ToUInt64(BitConverter.GetBytes(unchecked ((long)(p.Value))), 0);
                            break;

                        case DataType.String:
                            bp.ValueRest = strings.GetIndex((string)p.Value);
                            break;
                        }
                    }
                    bininst.Push = bp;
                    break;

                case InstructionKind.Call:
                    var callinst = (Call)inst;
                    bininst.Call = new CallInstruction
                    {
                        Arguments  = (ushort)callinst.Arguments,
                        Function   = new Reference(callinst.FunctionType, 0),
                        OpCode     = op,
                        ReturnType = callinst.ReturnType
                    };
                    functionReferences.Add(new Tuple <ReferenceSignature, uint>(new ReferenceSignature
                    {
                        Name          = callinst.FunctionName,
                        InstanceType  = InstanceType.StackTopOrGlobal,
                        VariableType  = callinst.FunctionType,
                        VariableIndex = -1
                    }, size));
                    break;

                case InstructionKind.Break:
                    var breakinst = (Break)inst;
                    bininst.Break = new BreakInstruction
                    {
                        OpCode = op,
                        Signal = (short)breakinst.Signal,
                        Type   = breakinst.Type
                    };
                    break;

                case InstructionKind.DoubleType:
                    var doubleinst = (DoubleType)inst;
                    bininst.DoubleType = new DoubleTypeInstruction
                    {
                        OpCode = op,
                        Types  = new TypePair(doubleinst.Type1, doubleinst.Type2)
                    };
                    if (inst is Compare cmpinst)
                    {
                        bininst.DoubleType.ComparisonType = cmpinst.ComparisonType;
                    }
                    break;

                case InstructionKind.SingleType:
                    var singleinst = (SingleType)inst;
                    bininst.SingleType = new SingleTypeInstruction
                    {
                        OpCode = op,
                        Type   = singleinst.Type
                    };
                    if (inst is Dup dupinst)
                    {
                        bininst.SingleType.DupExtra = dupinst.Extra;
                    }
                    break;

                case InstructionKind.Goto:
                    var  gotoinst  = (Branch)inst;
                    uint absTarget = 0;
                    if (gotoinst.Label is long)
                    {
                        absTarget = (uint)(long)(gotoinst.Label);
                    }
                    else if (gotoinst.Label is string)
                    {
                        absTarget = labels[(string)gotoinst.Label];
                    }
                    else if (gotoinst.Label == null)
                    {
                        bininst.Goto = new BranchInstruction
                        {
                            Offset = new Int24(0xF00000),
                            OpCode = op
                        };
                        break;
                    }
                    else
                    {
                        Console.Error.WriteLine($"Error in {name}: Can't use label {gotoinst.Label}");
                        break;
                    }
                    var  relTarget = (int)absTarget - (int)size;
                    uint offset    = unchecked ((uint)relTarget);
                    if (relTarget < 0)
                    {
                        offset &= 0xFFFFFF;
                        offset += 0x1000000;
                    }
                    offset      /= 4;
                    bininst.Goto = new BranchInstruction
                    {
                        Offset = new Int24(offset),
                        OpCode = op
                    };
                    break;

                default:
                    Console.Error.WriteLine($"Error in {name}: Unknown instruction type {type}!");
                    continue;
                }
                binaryInstructions.Add(bininst);
                unsafe
                {
                    size += DisasmExt.Size(&bininst, bcv) * 4;
                }
            }

            return(new CodeInfo
            {
                Size = (int)size,
                InstructionsCopy = binaryInstructions.ToArray(),
                functionReferences = functionReferences,
                variableReferences = variableReferences
            });
        }