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:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user