Imported Upstream version 5.2.0.175

Former-commit-id: bb0468d0f257ff100aa895eb5fe583fb5dfbf900
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2017-06-07 13:16:24 +00:00
parent 4bdbaf4a88
commit 966bba02bb
8776 changed files with 346420 additions and 149650 deletions

View File

@@ -27,38 +27,35 @@ namespace Mono.Cecil.Cil {
readonly RVA code_base;
internal readonly MetadataBuilder metadata;
readonly Dictionary<uint, MetadataToken> standalone_signatures;
readonly Dictionary<ByteBuffer, RVA> tiny_method_bodies;
RVA current;
MethodBody body;
public CodeWriter (MetadataBuilder metadata)
: base (0)
{
this.code_base = metadata.text_map.GetNextRVA (TextSegment.CLIHeader);
this.current = code_base;
this.metadata = metadata;
this.standalone_signatures = new Dictionary<uint, MetadataToken> ();
this.tiny_method_bodies = new Dictionary<ByteBuffer, RVA> (new ByteBufferEqualityComparer ());
}
public RVA WriteMethodBody (MethodDefinition method)
{
var rva = BeginMethod ();
RVA rva;
if (IsUnresolved (method)) {
if (method.rva == 0)
return 0;
WriteUnresolvedMethodBody (method);
rva = WriteUnresolvedMethodBody (method);
} else {
if (IsEmptyMethodBody (method.Body))
return 0;
WriteResolvedMethodBody (method);
rva = WriteResolvedMethodBody (method);
}
Align (4);
EndMethod ();
return rva;
}
@@ -73,18 +70,25 @@ namespace Mono.Cecil.Cil {
return method.HasBody && method.HasImage && method.body == null;
}
void WriteUnresolvedMethodBody (MethodDefinition method)
RVA WriteUnresolvedMethodBody (MethodDefinition method)
{
var code_reader = metadata.module.reader.code;
int code_size;
MetadataToken local_var_token;
var buffer = code_reader.PatchRawMethodBody (method, this, out code_size, out local_var_token);
var raw_body = code_reader.PatchRawMethodBody (method, this, out code_size, out local_var_token);
var fat_header = (raw_body.buffer [0] & 0x3) == 0x3;
if (fat_header)
Align (4);
WriteBytes (buffer);
var rva = BeginMethod ();
if (fat_header || !GetOrMapTinyMethodBody (raw_body, ref rva)) {
WriteBytes (raw_body);
}
if (method.debug_info == null)
return;
return rva;
var symbol_writer = metadata.symbol_writer;
if (symbol_writer != null) {
@@ -92,21 +96,38 @@ namespace Mono.Cecil.Cil {
method.debug_info.local_var_token = local_var_token;
symbol_writer.Write (method.debug_info);
}
return rva;
}
void WriteResolvedMethodBody (MethodDefinition method)
RVA WriteResolvedMethodBody(MethodDefinition method)
{
RVA rva;
body = method.Body;
ComputeHeader ();
if (RequiresFatHeader ())
if (RequiresFatHeader ()) {
Align (4);
rva = BeginMethod ();
WriteFatHeader ();
else
WriteInstructions ();
if (body.HasExceptionHandlers)
WriteExceptionHandlers ();
} else {
rva = BeginMethod ();
WriteByte ((byte) (0x2 | (body.CodeSize << 2))); // tiny
WriteInstructions ();
WriteInstructions ();
var start_position = (int) (rva - code_base);
var body_size = position - start_position;
var body_bytes = new byte [body_size];
if (body.HasExceptionHandlers)
WriteExceptionHandlers ();
Array.Copy (buffer, start_position, body_bytes, 0, body_size);
if (GetOrMapTinyMethodBody (new ByteBuffer (body_bytes), ref rva))
position = start_position;
}
var symbol_writer = metadata.symbol_writer;
if (symbol_writer != null && method.debug_info != null) {
@@ -114,6 +135,20 @@ namespace Mono.Cecil.Cil {
method.debug_info.local_var_token = body.local_var_token;
symbol_writer.Write (method.debug_info);
}
return rva;
}
bool GetOrMapTinyMethodBody (ByteBuffer body, ref RVA rva)
{
RVA existing_rva;
if (tiny_method_bodies.TryGetValue (body, out existing_rva)) {
rva = existing_rva;
return true;
}
tiny_method_bodies.Add (body, rva);
return false;
}
void WriteFatHeader ()
@@ -166,8 +201,9 @@ namespace Mono.Cecil.Cil {
return;
var operand = instruction.operand;
if (operand == null)
if (operand == null && !(operand_type == OperandType.InlineBrTarget || operand_type == OperandType.ShortInlineBrTarget)) {
throw new ArgumentException ();
}
switch (operand_type) {
case OperandType.InlineSwitch: {
@@ -179,11 +215,15 @@ namespace Mono.Cecil.Cil {
break;
}
case OperandType.ShortInlineBrTarget: {
WriteSByte ((sbyte) (GetTargetOffset (operand) - (instruction.Offset + opcode.Size + 1)));
var target = (Instruction) operand;
var offset = target != null ? GetTargetOffset (target) : body.code_size;
WriteSByte ((sbyte) (offset - (instruction.Offset + opcode.Size + 1)));
break;
}
case OperandType.InlineBrTarget: {
WriteInt32 (GetTargetOffset (operand) - (instruction.Offset + opcode.Size + 4));
var target = (Instruction) operand;
var offset = target != null ? GetTargetOffset (target) : body.code_size;
WriteInt32 (offset - (instruction.Offset + opcode.Size + 4));
break;
}
case OperandType.ShortInlineVar:
@@ -236,12 +276,8 @@ namespace Mono.Cecil.Cil {
}
}
int GetTargetOffset (object o)
int GetTargetOffset (Instruction instruction)
{
if (o is int)
return (int) o;
Instruction instruction = o as Instruction;
if (instruction == null) {
var last = body.instructions [body.instructions.size - 1];
return last.offset + last.GetSize ();
@@ -365,7 +401,7 @@ namespace Mono.Cecil.Cil {
CopyBranchStackSize (ref stack_sizes, (Instruction) instruction.operand, stack_size);
break;
case OperandType.InlineSwitch:
var targets = (Instruction[]) instruction.operand;
var targets = (Instruction []) instruction.operand;
for (int i = 0; i < targets.Length; i++)
CopyBranchStackSize (ref stack_sizes, targets [i], stack_size);
break;
@@ -604,7 +640,7 @@ namespace Mono.Cecil.Cil {
RVA BeginMethod ()
{
return current;
return (RVA)(code_base + position);
}
void WriteMetadataToken (MetadataToken token)
@@ -617,11 +653,6 @@ namespace Mono.Cecil.Cil {
align--;
WriteBytes (((position + align) & ~align) - position);
}
void EndMethod ()
{
current = (RVA) (code_base + position);
}
}
}