xoofx / LibObjectFile

LibObjectFile is a .NET library to read, manipulate and write linker and executable object files (e.g ELF, PE, DWARF, ar...)
BSD 2-Clause "Simplified" License
159 stars 11 forks source link

Make LEB128 size calculation branchless #29

Closed PaulusParssinen closed 1 year ago

PaulusParssinen commented 1 year ago

I saw this library being references in the C# reimplementation of ObjWriter for ILC/NativeAOT and I noticed the ULEB128 calculations which I knew neat trick for. I learned this trick from Google's AOSP source some years back and been using it since in my own libs.

It uses System.Numerics.BitOperations.LeadingZeroCount, which is not in .NET Standard but is supported from .NET Core 3 and up which also is the lowest supported TFM in .NET Standard 2.1. This is why I added it as TFM to csproj. edit: Thanks to targeting .NET 7, we can call BitOperations.LeadingZeroCount directly 🎉

x86 Codegen (.NET 7.0) ### SizeOfULEB128 ```assembly ; Method LibObjectFile.Dwarf.DwarfHelper:SizeOfULEB128(ulong):uint (FullOpts) G_M000_IG01: ;; offset=0x0000 G_M000_IG02: ;; offset=0x0000 or rcx, 1 xor eax, eax lzcnt rax, rcx neg eax add eax, 70 imul eax, eax, 37 shr eax, 8 G_M000_IG03: ;; offset=0x0016 ret ; Total bytes of code: 23 ``` ### SizeOfILEB128 ```assembly ; Method LibObjectFile.Dwarf.DwarfHelper:SizeOfILEB128(long):uint (FullOpts) G_M000_IG01: ;; offset=0x0000 G_M000_IG02: ;; offset=0x0000 mov rax, rcx sar rax, 63 xor rax, rcx or rax, 1 lzcnt rax, rax neg eax add eax, 71 imul eax, eax, 37 shr eax, 8 G_M000_IG03: ;; offset=0x001E ret ; Total bytes of code: 31 ```

This is pretty obscure bit-twiddling hack that I understand completely if it's too much of an premature optimization/hack for this library, just testing waters. 😄

xoofx commented 1 year ago

Sorry, took time to have a look and was not sure to introduce a .NET Core 3 support. So I preferred to switch to net7.0 (latest master)

If you don't mind to recommit a version without the #ifdef and the changes to the csproj? Thanks!