public static void WriteParameterReference(ITextOutput writer, MetadataReader metadata, MethodDefinitionHandle handle, int sequence) { var methodDefinition = metadata.GetMethodDefinition(handle); var signature = methodDefinition.DecodeSignature(new FullTypeNameSignatureDecoder(metadata), default); var parameters = methodDefinition.GetParameters().Select(p => metadata.GetParameter(p)).ToArray(); var signatureHeader = signature.Header; int index = sequence; if (signatureHeader.IsInstance && signature.ParameterTypes.Length == parameters.Length) { index--; } if (index < 0 || index >= parameters.Length) { writer.WriteLocalReference(sequence.ToString(), "param_" + index); } else { var param = parameters[index]; if (param.Name.IsNil) { writer.WriteLocalReference(sequence.ToString(), "param_" + index); } else { writer.WriteLocalReference(Escape(metadata.GetString(param.Name)), "param_" + index); } } }
public override void WriteIdentifier(Identifier identifier) { if (identifier.IsVerbatim || CSharpOutputVisitor.IsKeyword(identifier.Name, identifier)) { output.Write('@'); } var definition = GetCurrentDefinition(); string name = TextWriterTokenWriter.EscapeIdentifier(identifier.Name); switch (definition) { case IType t: output.WriteReference(t, name, true); return; case IMember m: output.WriteReference(m, name, true); return; } var member = GetCurrentMemberReference(); switch (member) { case IType t: output.WriteReference(t, name, false); return; case IMember m: output.WriteReference(m, name, false); return; } var localDefinition = GetCurrentLocalDefinition(); if (localDefinition != null) { output.WriteLocalReference(name, localDefinition, isDefinition: true); return; } var localRef = GetCurrentLocalReference(); if (localRef != null) { output.WriteLocalReference(name, localRef); return; } if (firstUsingDeclaration && !lastUsingDeclaration) { output.MarkFoldStart(defaultCollapsed: !settings.ExpandUsingDeclarations); firstUsingDeclaration = false; } output.Write(name); }
void DisassembleLocalsBlock(MethodDefinitionHandle method, MethodBodyBlock body) { if (body.LocalSignature.IsNil) { return; } output.Write(".locals"); WriteMetadataToken(body.LocalSignature, spaceBefore: true); if (body.LocalVariablesInitialized) { output.Write(" init"); } var blob = metadata.GetStandaloneSignature(body.LocalSignature); var signature = ImmutableArray <Action <ILNameSyntax> > .Empty; try { if (blob.GetKind() == StandaloneSignatureKind.LocalVariables) { signature = blob.DecodeLocalSignature(signatureDecoder, genericContext); } else { output.Write(" /* wrong signature kind */"); } } catch (BadImageFormatException ex) { output.Write($" /* {ex.Message} */"); } output.Write(' '); output.WriteLine("("); output.Indent(); int index = 0; foreach (var v in signature) { output.WriteLocalReference("[" + index + "]", "loc_" + index, isDefinition: true); output.Write(' '); v(ILNameSyntax.TypeName); if (DebugInfo != null && DebugInfo.TryGetName(method, index, out var name)) { output.Write(" " + DisassemblerHelpers.Escape(name)); } if (index + 1 < signature.Length) { output.Write(','); } output.WriteLine(); index++; } output.Unindent(); output.WriteLine(")"); }
public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { WriteILRange(output, options); output.Write(OpCode); output.Write(' '); output.WriteLocalReference(TargetLabel, (object)targetBlock ?? TargetILOffset); }
public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { ILRange.WriteTo(output, options); output.Write("Block "); output.WriteLocalReference(Label, this, isDefinition: true); if (Kind != BlockKind.ControlFlow) { output.Write($" ({Kind})"); } if (Parent is BlockContainer) { output.Write(" (incoming: {0})", IncomingEdgeCount); } output.Write(' '); output.MarkFoldStart("{...}"); output.WriteLine("{"); output.Indent(); foreach (var inst in Instructions) { inst.WriteTo(output, options); output.WriteLine(); } if (finalInstruction.OpCode != OpCode.Nop) { output.Write("final: "); finalInstruction.WriteTo(output, options); output.WriteLine(); } output.Unindent(); output.Write("}"); output.MarkFoldEnd(); }
public static void WriteOffsetReference(ITextOutput writer, int?offset) { if (offset == null) { writer.Write("null"); } else { writer.WriteLocalReference(OffsetToString(offset.Value), offset); } }
public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { WriteILRange(output, options); output.Write(OpCode); if (targetContainer != null) { output.Write(' '); output.WriteLocalReference(TargetLabel, targetContainer); output.Write(" ("); value.WriteTo(output, options); output.Write(')'); } }
public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { WriteILRange(output, options); output.Write("catch "); if (variable != null) { output.WriteLocalReference(variable.Name, variable, isDefinition: true); output.Write(" : "); Disassembler.DisassemblerHelpers.WriteOperand(output, variable.Type); } output.Write(" when ("); filter.WriteTo(output, options); output.Write(')'); output.Write(' '); body.WriteTo(output, options); }
public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { WriteILRange(output, options); output.WriteLocalReference("case", this, isDefinition: true); output.Write(' '); if (HasNullLabel) { output.Write("null"); if (!Labels.IsEmpty) { output.Write(", "); output.Write(Labels.ToString()); } } else { output.Write(Labels.ToString()); } output.Write(": "); body.WriteTo(output, options); }
public static void WriteVariableReference(ITextOutput writer, MetadataReader metadata, MethodDefinitionHandle handle, int index) { writer.WriteLocalReference(index.ToString(), "loc_" + index); }
protected virtual void WriteInstruction(ITextOutput output, MetadataReader metadata, MethodDefinitionHandle methodDefinition, ref BlobReader blob) { int offset = blob.Offset; if (ShowSequencePoints && nextSequencePointIndex < sequencePoints?.Count) { var sp = sequencePoints[nextSequencePointIndex]; if (sp.Offset <= offset) { output.Write("// sequence point: "); if (sp.Offset != offset) { output.Write("!! at " + DisassemblerHelpers.OffsetToString(sp.Offset) + " !!"); } if (sp.IsHidden) { output.WriteLine("hidden"); } else { output.WriteLine($"(line {sp.StartLine}, col {sp.StartColumn}) to (line {sp.EndLine}, col {sp.EndColumn}) in {sp.DocumentUrl}"); } nextSequencePointIndex++; } } ILOpCode opCode = ILParser.DecodeOpCode(ref blob); output.WriteLocalReference(DisassemblerHelpers.OffsetToString(offset), offset, isDefinition: true); output.Write(": "); if (opCode.IsDefined()) { output.WriteReference(new OpCodeInfo(opCode, opCode.GetDisplayName())); switch (opCode.GetOperandType()) { case OperandType.BrTarget: case OperandType.ShortBrTarget: output.Write(' '); int targetOffset = ILParser.DecodeBranchTarget(ref blob, opCode); output.WriteLocalReference($"IL_{targetOffset:x4}", targetOffset); break; case OperandType.Field: case OperandType.Method: case OperandType.Sig: case OperandType.Type: output.Write(' '); int metadataToken = blob.ReadInt32(); EntityHandle?handle = MetadataTokenHelpers.TryAsEntityHandle(metadataToken); try { handle?.WriteTo(module, output, genericContext); } catch (BadImageFormatException) { handle = null; } WriteMetadataToken(handle, metadataToken, spaceBefore: true); break; case OperandType.Tok: output.Write(' '); metadataToken = blob.ReadInt32(); handle = MetadataTokenHelpers.TryAsEntityHandle(metadataToken); switch (handle?.Kind) { case HandleKind.MemberReference: switch (metadata.GetMemberReference((MemberReferenceHandle)handle).GetKind()) { case MemberReferenceKind.Method: output.Write("method "); break; case MemberReferenceKind.Field: output.Write("field "); break; } break; case HandleKind.FieldDefinition: output.Write("field "); break; case HandleKind.MethodDefinition: output.Write("method "); break; } try { handle?.WriteTo(module, output, genericContext); } catch (BadImageFormatException) { handle = null; } WriteMetadataToken(handle, metadataToken, spaceBefore: true); break; case OperandType.ShortI: output.Write(' '); DisassemblerHelpers.WriteOperand(output, blob.ReadSByte()); break; case OperandType.I: output.Write(' '); DisassemblerHelpers.WriteOperand(output, blob.ReadInt32()); break; case OperandType.I8: output.Write(' '); DisassemblerHelpers.WriteOperand(output, blob.ReadInt64()); break; case OperandType.ShortR: output.Write(' '); DisassemblerHelpers.WriteOperand(output, blob.ReadSingle()); break; case OperandType.R: output.Write(' '); DisassemblerHelpers.WriteOperand(output, blob.ReadDouble()); break; case OperandType.String: metadataToken = blob.ReadInt32(); output.Write(' '); UserStringHandle?userString; string text; try { userString = MetadataTokens.UserStringHandle(metadataToken); text = metadata.GetUserString(userString.Value); } catch (BadImageFormatException) { userString = null; text = null; } if (userString != null) { DisassemblerHelpers.WriteOperand(output, text); } WriteMetadataToken(userString, metadataToken, spaceBefore: true); break; case OperandType.Switch: int[] targets = ILParser.DecodeSwitchTargets(ref blob); output.Write(" ("); for (int i = 0; i < targets.Length; i++) { if (i > 0) { output.Write(", "); } output.WriteLocalReference($"IL_{targets[i]:x4}", targets[i]); } output.Write(")"); break; case OperandType.Variable: output.Write(' '); int index = blob.ReadUInt16(); if (opCode == ILOpCode.Ldloc || opCode == ILOpCode.Ldloca || opCode == ILOpCode.Stloc) { DisassemblerHelpers.WriteVariableReference(output, metadata, methodDefinition, index); } else { DisassemblerHelpers.WriteParameterReference(output, metadata, methodDefinition, index); } break; case OperandType.ShortVariable: output.Write(' '); index = blob.ReadByte(); if (opCode == ILOpCode.Ldloc_s || opCode == ILOpCode.Ldloca_s || opCode == ILOpCode.Stloc_s) { DisassemblerHelpers.WriteVariableReference(output, metadata, methodDefinition, index); } else { DisassemblerHelpers.WriteParameterReference(output, metadata, methodDefinition, index); } break; } } else { ushort opCodeValue = (ushort)opCode; if (opCodeValue > 0xFF) { // split 16-bit value into two emitbyte directives output.WriteLine($".emitbyte 0x{(byte)(opCodeValue >> 8):x}"); // add label output.WriteLocalReference(DisassemblerHelpers.OffsetToString(offset + 1), offset + 1, isDefinition: true); output.Write(": "); output.Write($".emitbyte 0x{(byte)(opCodeValue & 0xFF):x}"); } else { output.Write($".emitbyte 0x{(byte)opCodeValue:x}"); } } output.WriteLine(); }
internal void WriteTo(ITextOutput output) { output.WriteLocalReference(this.Name, this); }
internal void WriteDefinitionTo(ITextOutput output) { switch (Kind) { case VariableKind.Local: output.Write("local "); break; case VariableKind.PinnedLocal: output.Write("pinned local "); break; case VariableKind.Parameter: output.Write("param "); break; case VariableKind.Exception: output.Write("exception "); break; case VariableKind.StackSlot: output.Write("stack "); break; case VariableKind.InitializerTarget: output.Write("initializer "); break; case VariableKind.ForeachLocal: output.Write("foreach "); break; case VariableKind.UsingLocal: output.Write("using "); break; case VariableKind.NamedArgument: output.Write("named_arg "); break; default: throw new ArgumentOutOfRangeException(); } output.WriteLocalReference(this.Name, this, isDefinition: true); output.Write(" : "); Type.WriteTo(output); output.Write('('); if (Kind == VariableKind.Parameter || Kind == VariableKind.Local || Kind == VariableKind.PinnedLocal) { output.Write("Index={0}, ", Index); } output.Write("LoadCount={0}, AddressCount={1}, StoreCount={2})", LoadCount, AddressCount, StoreCount); if (hasInitialValue && Kind != VariableKind.Parameter) { output.Write(" init"); } if (CaptureScope != null) { output.Write(" captured in " + CaptureScope.EntryPoint.Label); } if (StateMachineField != null) { output.Write(" from state-machine"); } }
public void WriteLocalReference(string text, object reference, bool isDefinition = false) { actions.Add(target => target.WriteLocalReference(text, reference, isDefinition)); }