feat: duplicate C exports across #import c units are a compile diagnostic

All units share one link namespace (per-unit isolation is PLAN-C C3.2,
deferred), so a symbol defined by two units previously died inside the
JIT dylib link or the AOT link with raw linker spew. The clang shim
gains sx_clang_object_exported_symbols (llvm::object scan: defined +
global, format-specific excluded) and compileCToObjects cross-checks
every unit object — collisions name both source files. Scan failures
are non-fatal; the linker remains the backstop. Covers JIT and native
AOT; the emcc path still relies on wasm-ld's own error.
This commit is contained in:
agra
2026-06-12 19:01:43 +03:00
parent 6114b51073
commit 9fb7290861
9 changed files with 122 additions and 0 deletions

View File

@@ -319,3 +319,54 @@ extern "C" LLVMMemoryBufferRef sx_clang_compile_to_object(
llvm::StringRef(obj_buf.data(), obj_buf.size()), "c_import.o");
return llvm::wrap(buf.release());
}
/* ------------------------------------------------------------------ */
/* Exported-symbol scan over a compiled object buffer */
/* ------------------------------------------------------------------ */
#include <llvm/Object/ObjectFile.h>
extern "C" SxCSymbolList *sx_clang_object_exported_symbols(
LLVMMemoryBufferRef obj,
char **out_error)
{
using namespace llvm;
MemoryBufferRef ref(
StringRef(LLVMGetBufferStart(obj), LLVMGetBufferSize(obj)),
"sx-c-import-object");
auto objOrErr = object::ObjectFile::createObjectFile(ref);
if (!objOrErr) {
if (out_error)
*out_error = strdup(toString(objOrErr.takeError()).c_str());
return nullptr;
}
std::vector<std::string> names;
for (const object::SymbolRef &sym : (*objOrErr)->symbols()) {
auto flagsOrErr = sym.getFlags();
if (!flagsOrErr) { consumeError(flagsOrErr.takeError()); continue; }
uint32_t flags = *flagsOrErr;
if (flags & object::SymbolRef::SF_Undefined) continue;
if (!(flags & object::SymbolRef::SF_Global)) continue;
if (flags & object::SymbolRef::SF_FormatSpecific) continue;
auto nameOrErr = sym.getName();
if (!nameOrErr) { consumeError(nameOrErr.takeError()); continue; }
names.push_back(nameOrErr->str());
}
SxCSymbolList *list = (SxCSymbolList *)malloc(sizeof(SxCSymbolList));
list->num_names = (int)names.size();
list->names = (const char **)malloc(sizeof(char *) * (names.empty() ? 1 : names.size()));
for (size_t i = 0; i < names.size(); i++)
list->names[i] = strdup(names[i].c_str());
return list;
}
extern "C" void sx_clang_free_symbol_list(SxCSymbolList *list)
{
if (!list) return;
for (int i = 0; i < list->num_names; i++)
free((void *)list->names[i]);
free(list->names);
free(list);
}