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); }
void CheckIL(AbcMethodBody body) { foreach (var instr in body.IL) { CheckInstruction(instr); } }
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); }
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); } }
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(); }
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); }
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); }