鲲鹏社区首页
中文
注册
编译入门那些事儿(6):LLVM Metadata System

编译入门那些事儿(6):LLVM Metadata System

DevKit

发表于 2023/08/30

0

Metadata 背景介绍

由于 LLVM IR Opcode 的表达能力有限,为了将额外的信息传递给优化器和代码生成器,LLVM 通常有三个解决方法,分别是 Attribute、Metadata 和 Intrinsic。如下图所示,三种方法各有优劣,使用哪种方法取决于需要传递的信息量。


Metadata 根据命名可知,代表元数据,它没有类型,也不是直接表示值,是用于描述 LLVM IR 的元数据格式。可以用来存储关于 LLVM IR 中各种实体(如:函数、变量、指令等)的附加信息,例如调试信息、优化提示、源代码位置等。

Metadata 组成

所有的 Metadata 都会用一个感叹号 ! 定义。在 LLVM 中 Metadata 的子类有四个:DistinctMDOperandPlaceholder、MDNode、MDString 和 ValueAsMetadata,Metadata 常见的组成可以是如下几种形态:


(1)DistinctMDOperandPlaceholder 是一个占位符,为了解决前置引用问题,在 Operand 创建后可以用 RAUW 函数替换,使用场景较少。

(2)MDNode 是一种复合的类型,可以随意组合各种 Metadata,比如:!{!"BiShengCompiler", i32 666666}。

(3)MDString 可以表示字符串,比如:!"BiShengCompiler"。

(4)ValueAsMetadata 是可以将 Value 类转化成 Metadata,通常会把 constant 类转为 Metadata,比如:i32 666666。

Metadata 使用场景

上一节我们知道了 Metadata 的组成元素,本节主要讲如何应用到 IR 中。

(1)作为函数的参数,比如:

call void @llvm.dbg.value(metadata !24, metadata !25, metadata !26)

(2)作为指令参数,比如:

%indvar.next = add i64 %indvar, 1, !dbg !21

(3)作为函数或者变量的参数,比如:

declare !dbg !22 void @f1()
define void @f2() !dbg !22 {
  ret void
}
@g1 = global i32 0, !dbg !22
@g2 = external global i32, !dbg !22

(4)Named Metadata,它是 Metadata 的集合,可以在 Module 的符号表中查找,比如:

!foo = !{!4, !3}

Metadata 存储

Metadata 在 IR 中存储的时候可能会有关键字限定,比如如下两个写法就会有很大的差异:

!0 = !{ !"test\00", i32 10}
!0 = distinct !{!"test\00", i32 10}

Metadata 的存储可分为如下三种模式:

(1)uniqued:顾名思义,表示 Metadata 唯一,在 Metadata 中不会显式打印,如果和其它的 Metadata 相同,会被合并。例如:已经有 !0 = !{ !"test\00", i32 10},需要再生成一个类似于 !1 = !{ !"test\00", i32 10} 的 Metadata 时,不会直接生成 !1,而是把使用 !1 的地方改成使用 !0。

(2)distinct:与 uniqued 相反,表示不唯一,不能和其他相同的合并,即上例中会生成新的 !1。

(3)temporary:表示临时存在,为了解决前置引用的问题,比如构建如下的 Metadata:


Metadata 总结与应用

LLVM Metadata 是 LLVM IR 中非常重要的一部分,它提供了丰富的信息,帮助开发人员更好地理解和优化 LLVM IR,因此 LLVM Metadata 在编译器中被广泛使用,特别是在调试和优化方面。常见的场景有:

(1)调试:可以保存源代码位置、变量名、类型等信息,用于调试器或其他工具的调试。

(2)优化:可以保存代码结构、数据流等信息,用于优化器的优化。

(3)其他:可以保存任何与 LLVM IR 相关的信息,例如源代码注释、版本信息等。

参考

1. https://llvm.org/docs/LangRef.html#range-metadata

本页内容