llvm: expose deterministic archive writing - #47
Conversation
a30473c to
41fcc68
Compare
There was a problem hiding this comment.
Review — deterministic archive writing bindings
Solid, focused addition. Resource cleanup is correct throughout (all C strings freed, writer disposed via defer, error messages released with LLVMDisposeMessage), error wrapping carries the member index, and the C layer null-checks every entry point. Two design details are worth confirming and a couple of minor points are inline. No blocking issues.
Main observation — file-member custom-name plumbing is unreachable via the public API
LLVMGoArchiveWriterAddFile honors a non-empty Name override (backports.cpp:66-69), and WriteArchive forwards member.name to it (archive.go:74-77). But ArchiveMember.name is unexported and NewArchiveMemberFromFile never sets it, so no caller can attach a custom name to a file member — the archive name is always path::filename(Path). The override branch is therefore effectively dead code from the exported API's perspective (and untested). Consider either exposing a constructor that sets a custom name for a file member (plus a test), or dropping the Name handling from LLVMGoArchiveWriterAddFile so an unexercised path isn't carried forward. The NewArchiveMemberFromFile doc ("member name is the base name of path", archive.go:38-39) is accurate for the public API today, but will need updating if the override is ever exposed.
Inline comments cover the member-precedence and empty-triple points.
| for i, member := range members { | ||
| var cErr *C.char | ||
| switch { | ||
| case member.path != "": |
There was a problem hiding this comment.
The switch silently prefers the file branch when a member has both path and a buffer set, ignoring the buffer with no diagnostic — unlike the clear per-index error in the default case. The exported constructors never produce such a member, but fields are package-visible and internal callers (e.g. the raw ArchiveMember{} literals in the tests) could set both. Consider either documenting the precedence on ArchiveMember or rejecting an ambiguous member (both path and buffer) with an explicit error, mirroring the empty-member check below.
| } | ||
|
|
||
| // WriteArchive creates a deterministic, non-thin archive with a symbol table. | ||
| // targetTriple determines the platform archive format. |
There was a problem hiding this comment.
When targetTriple is empty, the C side silently falls back to Archive::getDefaultKind() (host default) rather than failing (backports.cpp:47-51). WriteArchive doesn't reject an empty triple, so this fallback is reachable. Worth documenting the empty-triple behavior here so callers know an unset triple produces a host-default archive format rather than an error.
f054bb1 to
7a1b701
Compare
7a1b701 to
d8f8a2a
Compare
Expose LLVM ArchiveWriter through the Go bindings so callers can build deterministic static archives directly from LLVM memory buffers and file-backed members.
This avoids forcing in-memory codegen results through temporary object files before archiving. The API selects the archive format from the target triple, writes a normal symbol table, and keeps memory-buffer ownership with the caller.
Tests cover mixed memory/file members and invalid input.