Beispiel #1
0
        internal AbcMethod DefineMethod(Sig sig, AbcCoder coder)
        {
            var method = new AbcMethod
            {
                ReturnType = sig.ReturnType != null
                                                         ? DefineTypeNameSafe(sig.ReturnType)
                                                         : null
            };

            if (sig.Args != null)
            {
                AddParameters(method.Parameters, sig.Args);
            }

            var body = new AbcMethodBody(method);

            AddMethod(method);

            if (coder != null)
            {
                var code = new AbcCode(this);
                coder(code);
                body.Finish(code);
            }

            return(method);
        }
Beispiel #2
0
 void CheckIL(AbcMethodBody body)
 {
     foreach (var instr in body.IL)
     {
         CheckInstruction(instr);
     }
 }
Beispiel #3
0
        private Instruction ImportInstruction(AbcMethodBody body, Instruction i)
        {
            var i2 = i.Clone();

            if (!i2.HasOperands)
            {
                return(i2);
            }
            foreach (var op in i2.Operands)
            {
                if (op.Value == null)
                {
                    continue;
                }

                switch (op.Type)
                {
                case OperandType.MethodIndex:
                {
                    var m = (AbcMethod)op.Value;
                    op.Value = ImportMethod(m);
                }
                break;

                case OperandType.ClassIndex:
                {
                    var klass    = (AbcClass)op.Value;
                    var instance = ImportInstance(klass.Instance);
                    op.Value = instance.Class;
                }
                break;

                case OperandType.ExceptionIndex:
                {
                    var h = (AbcExceptionHandler)op.Value;
                    op.Value = body.Exceptions[h.Index];
                }
                break;

                default:
                {
                    var c = op.Value as IAbcConst;
                    if (c != null)
                    {
                        var nc = ImportConst(c);
                        if (nc == null)
                        {
                            throw new InvalidOperationException(string.Format(
                                                                    "Unable to import const: {0}", c));
                        }
                        op.Value = nc;
                    }
                }
                break;
                }
            }
            return(i2);
        }
Beispiel #4
0
        private void ImportExceptions(AbcMethodBody body, AbcMethodBody from)
        {
            var code = from.IL;

            foreach (var h in from.Exceptions)
            {
                var h2 = new AbcExceptionHandler
                {
                    From         = GetOffsetIndex(code, h.From),
                    To           = GetOffsetIndex(code, h.To),
                    Target       = GetOffsetIndex(code, h.Target),
                    Index        = h.Index,
                    VariableName = ImportConst(h.VariableName),
                    Type         = ImportType(h.Type)
                };
                body.Exceptions.Add(h2);
            }
        }
Beispiel #5
0
        private void ImportIL(AbcMethodBody body, AbcMethodBody from)
        {
            var code = from.IL;

            //NOTE: Size of instructions can be changed and therefore we should retranslate branch offsets.
            code.TranslateOffsets();
            int  n           = code.Count;
            bool hasBranches = false;

            for (int i = 0; i < n; ++i)
            {
                var instr = ImportInstruction(body, code[i]);
                body.IL.Add(instr);
                if (!hasBranches && (instr.IsBranch || instr.IsSwitch))
                {
                    hasBranches = true;
                }
            }
            //if (from.Exceptions.Count == 0 && !hasBranches)
            //    body.IL.Optimize();
        }
Beispiel #6
0
        private AbcMethodBody ImportMethodBody(AbcMethodBody from, AbcMethod method)
        {
            if (from.ImportedBody != null)
            {
                return(from.ImportedBody);
            }

            var body = new AbcMethodBody(method);

            from.ImportedBody  = body;
            body.MaxStackDepth = from.MaxStackDepth;
            body.LocalCount    = from.LocalCount;
            body.MinScopeDepth = from.MinScopeDepth;
            body.MaxScopeDepth = from.MaxScopeDepth;
            MethodBodies.Add(body);

            ImportTraits(from, body);
            ImportExceptions(body, from);
            ImportIL(body, from);
            body.TranslateIndices();
            body.ResolveExceptionOffsets(this);

            return(body);
        }
Beispiel #7
0
        internal AbcMethod DefineMethod(Sig sig, AbcCoder coder, Action <AbcMethod> complete)
        {
            if (sig == null)
            {
                throw new ArgumentNullException("sig");
            }

            if (!sig.IsInitilizer && sig.Name == null)
            {
                throw new InvalidOperationException();
            }

            var klass = Class;

            if (klass == null)
            {
                throw new InvalidOperationException(string.Format("Class is not defined yet for Instance {0}", FullName));
            }

            AbcMultiname traitName = null;
            AbcTrait     trait;

            bool isStatic = (sig.Semantics & MethodSemantics.Static) != 0;
            var  traits   = isStatic ? klass.Traits : Traits;

            if (sig.IsInitilizer)
            {
                if (Initializer != null)
                {
                    throw new InvalidOperationException();
                }
            }
            else
            {
                traitName = Abc.DefineName(sig.Name);
                trait     = traits.Find(traitName, sig.Kind);
                if (trait != null)
                {
                    return(trait.Method);
                }
            }

            var method = new AbcMethod
            {
                Method = sig.Source
            };

            var generator = Abc.Generator;

            if (sig.Source != null)
            {
                generator.SetData(sig.Source, method);
            }

            AbcMethodBody body = null;

            if (sig.IsAbstract)
            {
                if (coder != null)
                {
                    throw new InvalidOperationException();
                }
            }
            else
            {
                body = new AbcMethodBody(method);
            }

            Abc.AddMethod(method);

            if (sig.IsInitilizer)
            {
                Initializer = method;
            }
            else
            {
                //for non initializer method we must define trait and return type
                method.ReturnType = BuildReturnType(sig.ReturnType, method);

                trait      = AbcTrait.CreateMethod(method, traitName);
                trait.Kind = sig.Kind;

                if (!isStatic)
                {
                    trait.IsVirtual  = (sig.Semantics & MethodSemantics.Virtual) != 0;
                    trait.IsOverride = (sig.Semantics & MethodSemantics.Override) != 0;
                }

                traits.Add(trait);
            }

            if (sig.Args != null)
            {
                if (sig.Args.Length == 1 && sig.Args[0] is IMethod)
                {
                    var m = (IMethod)sig.Args[0];
                    if (generator == null)
                    {
                        throw new InvalidOperationException();
                    }
                    generator.MethodBuilder.BuildParameters(method, m);
                }
                else
                {
                    Abc.AddParameters(method.Parameters, sig.Args);
                }
            }

            if (body != null && coder != null)
            {
                var code = new AbcCode(Abc);
                coder(code);
                body.Finish(code);
            }

            if (complete != null)
            {
                complete(method);
            }

            return(method);
        }