源映射

作为 AST 输出的一部分,编译器提供了源代码的范围,该范围由 AST 中的相应节点表示。这可以用于各种目的,从基于 AST 报告错误的静态分析工具到突出显示局部变量及其使用的调试工具。

此外,编译器还可以生成从字节码到生成指令的源代码范围的映射。这对于在字节码级别操作的静态分析工具以及在调试器中显示源代码中的当前位置或处理断点非常重要。此映射还包含其他信息,如跳转类型和修改器深度(见下文)。

这两种源映射使用整数标识符来引用源文件。源文件的标识符存储在 output['sources'][sourceName]['id'] 中,其中 output 是解析为 JSON 的标准 JSON 编译器接口的输出。对于某些实用程序例程,编译器生成“内部”源文件,这些文件不是原始输入的一部分,但在源映射中被引用。这些源文件及其标识符可以通过 output['contracts'][sourceName][contractName]['evm']['bytecode']['generatedSources'] 获取。

备注

在与任何特定源文件无关的指令的情况下,源映射分配一个整数标识符 -1。这可能发生在源自编译器生成的内联汇编语句的字节码部分。

AST 中的源映射使用以下表示法:

s:l:f

其中 s 是源文件中范围开始的字节偏移量,l 是源范围的字节长度,f 是上述源索引。

字节码的源映射编码更为复杂: 它是一个由 s:l:f:j:m 组成的列表,以 ; 分隔。每个元素对应于一条指令,即不能使用字节偏移量,而必须使用指令偏移量(推送指令的长度超过一个字节)。字段 slf 与上述相同。j 可以是 io-,表示跳转指令是进入函数、从函数返回还是作为循环等的一部分的常规跳转。最后一个字段 m 是一个整数,表示“修改器深度”。每当在修改器中进入占位符语句(_)时,该深度增加,离开时减少。这使得调试器能够跟踪棘手的情况,例如同一修改器被使用两次或在单个修改器中使用多个占位符语句。

为了压缩这些源映射,特别是字节码,使用以下规则:

  • 如果字段为空,则使用前一个元素的值。

  • 如果缺少 :,则所有后续字段被视为空。

这意味着以下源映射表示相同的信息:

1:2:1;1:9:1;2:1:2;2:1:2;2:1:2

1:2:1;:9;2:1:2;;

重要的是要注意,当使用 verbatim 内置时,源映射将无效:该内置被视为单个指令,而不是可能的多个指令。