llvmincludellvmIRFunction.h
llvm Function class在llvm中,使用Function class表示函数,Function class的定义如下:
class Function : public GlobalObject, public ilist_node{ ... };
首先,Function继承自GlobalObject,是一个全局独立对象。
其次,Function继承ilist_node
Module *M = ...;
for (Module::iterator I=M.begin(),E=M.end(); I != E; ++I) {
Function &F = *I;
...
}
Function Declaration & definition
Function声明的语法如下:
declare [linkage] [visibility] [DLLStorageClass]
[cconv] [ret attrs]
@ ([argument list])
[(unnamed_addr|local_unnamed_addr)] [AddrSpace]
[partition "name"] [align N]
[gc] [prefix Constant] [prologue Constant]
Function定义的语法如下:
define [linkage] [PreemptionSpecifier] [visibility] [DLLStorageClass]
[cconv] [ret attrs]
@ ([argument list])
[(unnamed_addr|local_unnamed_addr)] [AddrSpace] [fn Attrs]
[section "name"] [partition "name"] [comdat [($name)]] [align N]
[gc] [prefix Constant] [prologue Constant] [personality Constant]
(!name !N)* { ... }
linkage & visibility
参考llvm libLLVMCore源码分析 19 - GlobalValue
DLLStorageClassWINDOWS相关,暂不分析。
cconv参考llvm libLLVMCore源码分析 13 - Other Operators
unnamed_addr|local_unnamed_addrunnamed_addr:函数的地址不重要,只需要关心函数的内容,这样相同的函数满足一定条件就可以合并。
local_unnamed_addr:函数的地址在当前的Module内不重要,只需要关心函数的内容,这样Module内相同的函数满足一定条件就可以合并。
fn AttrsFunction Attributes是函数的一部分,相同的函数类型,可以有不同的Attributes,如下所示:
define void @f() noinline { ... }
define void @f() alwaysinline { ... }
define void @f() alwaysinline optsize { ... }
define void @f() optsize { ... }
可选的Function Attributes如下:
alignstack(
allocsize(
alwaysinline:inliner忽略inlining size的阈值,尽可能进行inline。
builtin:函数是builtin function。
cold:函数不经常被调用。
convergent:表明调用该函数不能在控制流上依赖额外的值。例如 llvm.nvvm.barrier0就有convergent属性,主要用于SIMD/SIMT架构下。
disable_sanitizer_instrumentation:禁止Sanitizer插桩。
dontcall-error:当函数调用没有被优化掉时,会上报error。
dontcall-warn:当函数调用没有被优化掉时,会上报warning。
frame-pointer:指示函数是否需要保存栈帧指针,none:不需要。non-leaf:函数调用其他函数时需要。all:全都需要。
hot:函数经常被调用。
inaccessiblememonly:函数只能访问Module内其他函数不访问的内存。
inaccessiblemem_or_argmemonly:函数只能访问Module内其他函数不访问的内存,或指针参数传递的内存。
inlinehint:建议inliner进行inline,类似C中的inline关键字。
jumptable:函数会被加到jump-instruction table,所有对函数地址的引用会被替换为jump-instruction table中的指针,所以函数必须是unnamed_addr。
minsize:指示编译器尽可能减小函数的codesize。
naked:禁止生产prologue / epilogue。
no-inline-line-tables:inline函数的时候用call site的源码位置替换函数的源码位置。
no-jump-tables:禁止switch case生产jump table。
nobuiltin:函数不是builtin function。
noduplicate:不能在一个函数内多处调用。
nofree:函数不调用内存释放函数。
noimplicitfloat:禁止隐式浮点代码。
noinline:只是inliner禁止inline当前函数。
nomerge:禁止合并函数调用(比如尾调用优化)
nonlazybind:禁止函数进行lazy symbol binding。
noprofile:禁止profiling插桩。
noredzone:禁止生成redzone。
indirect-tls-seg-refs:禁止通过segment register使用TLS。
noreturn:函数不通过return指令返回。
norecurse:函数不直接或间接递归调用自己。
willreturn:调用函数要么产生未定义行为,要么会返回到调用栈中的某一个点执行。
nosync:函数不和其他线程通过内存或其他方式同步。
nounwind:函数不抛出异常。
nosanitize_bounds:禁止Sanitizer进行边界检查插桩。
nosanitize_coverage:禁止SanitizerCoverage插桩。
null_pointer_is_valid:null地址是合法地址。
optforfuzzing:只是函数向最大化fuzzing signal的方向优化。
optnone:禁止除了过程间优化pass之外的优化。
optsize:在对性能影响不大的前提下,尽量优化函数的codesize。
patchable-function:函数必须遵循一些约定,保证可以被打补丁。
probe-stack:生成一个guard region在栈的结尾。
readnone:函数仅用参数计算结果,而不解引用参数指针,或者访问可变的状态。并且函数不能改写调用方可见的任何内存和状态。
readonly:函数不能改写调用方可见的任何内存和状态。
stack-probe-size:函数不能使用超过stack-probe-size指定大小的栈空间。
no-stack-arg-probe:禁止stack probe。
writeonly:函数只会写内存。
argmemonly:函数只能访问指针参数传递的内存。
returns_twice:函数可以返回两次,比如C中的setjmp。
safestack:使能SafeStack保护。
sanitize_address:使能AddressSanitizer 。
sanitize_memory:使能MemorySanitizer 。
sanitize_thread:使能ThreadSanitizer 。
sanitize_hwaddress:使能HWAddressSanitizer。
sanitize_memtag:使能MemTagSanitizer
speculative_load_hardening:只能Speculative load hardening。
speculatable:函数除了计算结果之外没有副作用,不存在未定义行为。
ssp:使能栈保护:1)char数组超过ssp-buffer-size;2)符合类型包含char数组超过ssp-buffer-size;3)alloca申请的变量或者常量超过ssp-buffer-size
sspstrong:使能栈保护:1)所有的数组;2)所有的包含数组的复合类型;3)alloca;4)被取地址的局部变量。
sspreq:使能栈保护:所有场景。.
strictfp:指示函数需要严格的浮点语义。
denormal-fp-math:指示浮点数如何处理小值。
denormal-fp-math-f32:和denormal-fp-math语义相同,但仅对32bit的浮点类型生效。
thunk:指示函数通过尾调用代理其他函数。
tls-load-hoist:函数通过TLS变量减少冗余的TLS地址计算。
uwtable[(sync|async)]:为函数生成unwind table entry。
nocf_check:指示不需要控制流检查。
shadowcallstack:使能ShadowCallStack检查。
mustprogress:指示函数会通过返回或栈展开等方式和环境交互。
warn-stack-size=
vscale_range(
Parameter Attributes是函数参数和返回值的属性,示例如下所示:
declare i32 @printf(i8* noalias nocapture, ...) declare i32 @atoi(i8 zeroext) declare signext i8 @returns_signed_char()
可选的Parameter Attributes如下:
zeroext:零扩展。
signext:符号位扩展。
inreg:以目标架构特定的方式处理(通常是放到寄存器而不是内存中)。
byval(
byref(
preallocated(
inalloca(
sret(
elementtype(
align
noalias:函数只能通过这个指针参数或返回值去访问这片内存,用在指针参数上和C99中的restrict语义相同,用在返回值上,既函数的返回值和调用方的任何对象的内存都不相交。
nocapture:函数不能捕获这个指针参数。
nofree:函数不能free这个指针参数
nest:指示指针参数可以通过trampoline intrinsics去除,该属性用于支持C语言中的嵌套函数。
returned:指示函数总是将这个参数作为返回值。
nonnull:指针参数不为null。
dereferenceable(
dereferenceable_or_null(
swiftself:指示这个参数是swift中的self/context。
swiftasync:指示这个参数是swift中的asynchronous context。
swifterror:用于优化swift的错误处理。
immarg:参数是一个立即数,是一个平凡的整形或者浮点常量。
noundef:参数或者返回值不是undef的。
alignstack(
allocalign:这个参数是函数申请的内存返回值的对齐。



