Closed
Description
Background and Motivation
It doesn't look like there's a way to use InstructionEncoder.DefineLabel
's LabelHandle
s with a switch
instruction. I'm mainly asking if there is a way to do it that I'm missing, but if not here's a basic API proposal to enable it.
Proposed API
namespace System.Reflection.Metadata.Ecma335
{
public readonly struct InstructionEncoder
{
+ public void Switch(params LabelHandle[] label);
}
}
Usage Examples
var ie = new InstructionEncoder(new BlobBuilder(), new ControlFlowBuilder());
var case0 = ie.DefineLabel();
var case1 = ie.DefineLabel();
var case2 = ie.DefineLabel();
var afterCases = ie.DefineLabel();
ie.OpCode(ILOpCode.Ldc_i4_0);
ie.Switch(case0, case1, case2);
ie.Branch(ILOpCode.Br_s, afterCases);
ie.MarkLabel(case0);
ie.OpCode(ILOpCode.Ldc_i4_0);
ie.OpCode(ILOpCode.Ret);
ie.MarkLabel(case1);
ie.OpCode(ILOpCode.Ldc_i4_1);
ie.OpCode(ILOpCode.Ret);
ie.MarkLabel(case2);
ie.OpCode(ILOpCode.Ldc_i4_2);
ie.OpCode(ILOpCode.Ret);
ie.MarkLabel(afterCases);
ie.OpCode(ILOpCode.Ldc_i4_s);
ie.CodeBuilder.WriteCompressedSignedInteger(10);
ie.OpCode(ILOpCode.Ret);
new MethodBodyStreamEncoder(new BlobBuilder())
.AddMethodBody(ie, maxStack: 8, localVariablesSignature: default, MethodBodyAttributes.None);
Alternative Designs
Originally this proposal was based on emitting the label by itself:
namespace System.Reflection.Metadata.Ecma335
{
public readonly struct InstructionEncoder
{
+ public void Label(LabelHandle label);
}
}
This won't work because the target offset is based on the end of the switch
instruction, not the offset of the label.
Also for it to work with switch like intended, it would need to only emit int32 offsets. That's not super clear from the name and would generate bad IL if someone were to do OpCode(ILOpCode.Br_s); Label(label);
, even if it were based on the label's offset.