For several reasons related to code size and memory consumption (see below), it
is best to try to evaluate as much initialization code at compile time as
possible and only run unknown expressions (e.g. external calls) at runtime. This
is in practice a partial evaluator of the runtime.initAll
function, which
calls each package initializer.
It works by directly interpreting LLVM IR:
runtime.initAll
function. Return values are also considered 'dirty'.runtime.initAll
, all globals it references are also marked
dirty.runtime.alloc
) is emulated by creating new objects. The
value in the allocation is the initializer of the global, the zero value is
the zero initializer.alloca
) is often emulated using a fake alloca object,
until the address of the alloca is taken in which case it is also created as
a real alloca
in runtime.initAll
and marked dirty. This may be necessary
when calling an external function with the given alloca as paramter.A partial evaluator is hard to get right, so why go through all the trouble of writing one?
The main reason is that the previous attempt wasn't complete and wasn't sound. It simply tried to evaluate Go SSA directly, which was good but more difficult than necessary. An IR based interpreter needs to understand fewer instructions as the LLVM IR simply has less (complex) instructions than Go SSA. Also, LLVM provides some useful tools like easily getting all uses of a function or global, which Go SSA does not provide.
But why is it necessary at all? The answer is that globals with initializers are much easier to optimize by LLVM than initialization code. Also, there are a few other benefits:
For more details, see this section of the documentation.
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。