gpt4 book ai didi

arrays - CIL 的 stelem 指令的 typeTok 参数的目的是什么?

转载 作者:行者123 更新时间:2023-12-04 05:04:17 25 4
gpt4 key购买 nike

CIL stelem指令(ECMA 335 [pdf] 中的 III.4.26)指定为

Format      Assembly Format     DescriptionA4 <T>      stelem typeTok      Replace array element at index with the                                value on the stackStack Transition:…, array, index, value,  ->  …

我不明白 typeTok 参数的目的是什么。

原始规范

以下是规范中提到的所有typeTok:

  • 在描述中:

    The type of value must be array-element-compatible-with typeTok in the instruction.

  • 在“正确性”部分:

    typeTok shall be a valid typedef, typeref, or typespec metadata token.

  • 在“可验证性”部分:

    • the tracked type of array is T[], for some T;

    • the tracked type of value is array-element-compatible-with typeTok;

    • typeTok is array-element-compatible-with T

因此 typeTok 没有用于任何用途;它只是必须提供。换句话说,我看到的唯一要求是满足条件的 typeTok 必须存在

修改规范

然而,仅要求存在这样一个typeTok 等同于1 将上述规范部分更改为

  • 在描述中:

    The type of value must be array-element-compatible-with the element type of array

  • 在“正确性”部分,删除上面的部分。

  • 在“可验证性”部分:

    • the tracked type of array is T[], for some T;

    • the tracked type of value is array-element-compatible-with T


1 如果 valuea-e-c-with array 的元素类型,那么因为a-e-c-with 关系的自反性,value 的类型或数组的元素类型都可以选择为满足要求的 typeTok的“原始规范”。相反,如果存在具有给定要求的 typeTok,则 a-e-c-with 关系的传递性会立即产生“修改后的规范”的要求。


那我错过了什么?为什么存在 typeTok 参数(因此为什么存在 stelem.<type> 指令,但 stelem.ref 除外)?

最佳答案

Stelem TypeToken 的存在是为了支持非原始值类型。如果此操作码不存在,唯一的其他选择是将这些结构装箱。

有一个 stelem.* 元素家族。对于原语 [i,i1,i2,i4,i8,r4,r8,and ref]

原始的告诉它期望堆栈上有一个特定大小的元素并且应该读取它,ref 表示有一个对象引用。现在,如果不是基元的 struct 呢?您可能会说只使用相同大小的那些基元之一。毕竟,这就是它对 Enum 数组的作用。考虑 DateTimeOffSet。它是 12 个字节,因此您不能使用现有的原语之一。必须装箱来存储这些元素的数组是不好的。

存在的另一个操作码是stelem.any,它用于通用代码。这只是一个短代码,以防 TypeToken 可能是对 class 类型的引用。您始终可以使用 stelem.any,但如果类型标记由基元处理,则使用 4 个额外字节是一种浪费。

需要类型信息的

CIL 操作码 始终将它们作为操作数,即使基于堆栈上的其他元素应该是显而易见的。这可能只是为了让 CLR 团队的生活更轻松。 (考虑 box 需要一个操作码)。这也可能有助于发射器避免犯错误。例如

ldc.i4.8
box typetoken(long)
//whoops we clearly need to conv.i8 before we can box this as a long.

为什么存在速记版本(例如 Stelem.i4 只是 stelem typetoken(int32)?它们的存在是为了少 4 个字节。更短的方法有更好的机会被内联。过去,如果一个方法超过 32 字节的 IL,它就不会被内联。

编辑:我错了。似乎 C# 通常会获取结构地址元素的地址并存储它们。从技术上讲,您可以使用 stelem TypeToken(因为这是在一般情况下发出的),但 VS 团队似乎没有。

var dynmethod = new DynamicMethod("test", typeof(void), new[] { typeof(DateTimeOffset[]), typeof(DateTimeOffset) });
var gen = dynmethod.GetILGenerator();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldc_I4_0);
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Stelem, typeof(DateTimeOffset));
gen.Emit(OpCodes.Ret);
var d=dynmethod.CreateDelegate(typeof(Action<DateTimeOffset[], DateTimeOffset>)) as Action<DateTimeOffset[],DateTimeOffset>;

这个序列按预期工作,所以我不知道他们为什么选择另一条路线。

关于arrays - CIL 的 stelem 指令的 typeTok 参数的目的是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19950849/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com