stage2: LLVM backend: improved naming and exporting

Introduce an explicit decl_map for *Decl to LLVMValueRef. Doc comment
reproduced here:

Ideally we would use `llvm_module.getNamedFunction` to go from *Decl to
LLVM function, but that has some downsides:
* we have to compute the fully qualified name every time we want to do the lookup
* for externally linked functions, the name is not fully qualified, but when
  a Decl goes from exported to not exported and vice-versa, we would use the wrong
  version of the name and incorrectly get function not found in the llvm module.
* it works for functions not all globals.
Therefore, this table keeps track of the mapping.

Non-exported functions now use fully-qualified symbol names.
`Module.Decl.getFullyQualifiedName` now returns a sentinel-terminated
slice which is useful to pass to LLVMAddFunction.

Instead of using aliases for all external symbols, now the LLVM backend
takes advantage of LLVMSetValueName to rename functions that become
exported. Aliases are still used for the second and remaining exports.

freeDecl is now handled properly in the LLVM backend, deleting the
LLVMValueRef corresponding to the Decl being deleted. The linker
backends for ELF, COFF, Mach-O, and Wasm had to be updated to forward
the freeDecl call to the LLVM backend.
This commit is contained in:
Andrew Kelley
2021-09-23 23:39:58 -07:00
parent 418105589a
commit f215d98043
8 changed files with 96 additions and 41 deletions

View File

@@ -619,11 +619,11 @@ pub const Decl = struct {
return decl.namespace.renderFullyQualifiedName(unqualified_name, writer);
}
pub fn getFullyQualifiedName(decl: Decl, gpa: *Allocator) ![]u8 {
pub fn getFullyQualifiedName(decl: Decl, gpa: *Allocator) ![:0]u8 {
var buffer = std.ArrayList(u8).init(gpa);
defer buffer.deinit();
try decl.renderFullyQualifiedName(buffer.writer());
return buffer.toOwnedSlice();
return buffer.toOwnedSliceSentinel(0);
}
pub fn typedValue(decl: Decl) error{AnalysisFail}!TypedValue {