mirror of
https://github.com/open-policy-agent/opa.git
synced 2026-08-12 19:32:48 -06:00
5a1ed9c7fa
We're in this situation: performing dead code analysis on wasm isn't too hard, but it requires a representation of all wasm instructions: we'd need to be able to parse the "runtime" wasm bits, i.e., what's built using llvm from C code. When building upon that wasm module, we process the function bodies uninterpreted -- they are all just `[]byte` to us. This restriction lets us get by without implementing all the wasm instructions -- we only write what we use, and read a bare minimum to work as outlined above. To still be able to remove dead code, this change employs a trick: at build time, when the aforementioned runtime wasm module is compiled, we're calling wasm-opt on it to extract its call graph. We'll use that, together with the functions actually planned in our wasm compiler (using the subset of instructions that we understand), to remove all unused functions from the name section, and replace their function bodies with `unreachable`. We cannot really remove them, since that would require reindexing all functions; and we cannot do that without replacing the function indices at their call sites in the "runtime" wasm module. Another restriction to the impact of this approach is call_indirect: We need to keep every function that's referenced in the table -- we don't know which function might be calling them indirectly. In a follow-up, we could record that information and use it to further reduce the code size: we know that if none of the regex-related builtins are used, we could also stub out the re2-related functions. Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>