================
@@ -170,8 +324,504 @@ RValue WebAssemblyABIInfo::EmitVAArg(CodeGenFunction
&CGF, Address VAListAddr,
/*AllowHigherAlign=*/true, Slot);
}
+// Generate wrapper name for runtime function pointer binding
+std::string WebAssemblyTargetCodeGenInfo::getRuntimeWrapperName(
+ const FunctionProtoType *SrcProto, const FunctionProtoType *DstProto,
+ const ASTContext &Ctx) const {
+ std::string Name = "__wasm_runtime_wrapper_";
+
+ // Encode source signature
+ QualType SrcRetTy = SrcProto->getReturnType();
+ if (SrcRetTy->isVoidType()) {
+ Name += 'v';
+ } else {
+ Name += getTypeSig(SrcRetTy, Ctx);
+ }
+ for (QualType ParamType : SrcProto->param_types()) {
+ Name += getTypeSig(ParamType, Ctx);
+ }
+
+ Name += "_to_";
+
+ // Encode destination signature
+ QualType DstRetTy = DstProto->getReturnType();
+ if (DstRetTy->isVoidType()) {
+ Name += 'v';
+ } else {
+ Name += getTypeSig(DstRetTy, Ctx);
+ }
+ for (QualType ParamType : DstProto->param_types()) {
+ Name += getTypeSig(ParamType, Ctx);
+ }
+
+ return Name;
+}
+
+// Emit runtime binding for function pointer cast
+// This handles cases like g_list_free_full where a runtime parameter
+// needs to be cast from fewer params to more params
+llvm::Value
*WebAssemblyTargetCodeGenInfo::emitWasmRuntimeFunctionPointerBinding(
+ CodeGenFunction &CGF, llvm::Value *FnPtr, QualType SrcType,
+ QualType DstType, bool IsImmediate) const {
+
+ const FunctionProtoType *SrcProto =
+ SrcType->getPointeeType()->getAs<FunctionProtoType>();
+ const FunctionProtoType *DstProto =
+ DstType->getPointeeType()->getAs<FunctionProtoType>();
+
+ if (!SrcProto || !DstProto)
+ return nullptr;
+
+ // Check parameter counts: source must have same or fewer params than
destination
+ // We can add parameters (caller provides them, we ignore extras when
calling source)
+ // We cannot remove parameters (caller doesn't provide them, we can't invent
values)
+ unsigned SrcParams = SrcProto->getNumParams();
+ unsigned DstParams = DstProto->getNumParams();
+
+ if (SrcParams > DstParams)
+ return nullptr; // Can't remove parameters
+
+ // Check return types: we can discard a return value but cannot invent one.
+ // Compare LLVM types (not C types) since wasm only cares about
i32/i64/f32/f64.
+ QualType SrcRetTy = SrcProto->getReturnType();
+ QualType DstRetTy = DstProto->getReturnType();
+ llvm::Type *SrcRetLLVMTy = CGF.CGM.getTypes().ConvertType(SrcRetTy);
+ llvm::Type *DstRetLLVMTy = CGF.CGM.getTypes().ConvertType(DstRetTy);
+ bool sameReturnType = SrcRetLLVMTy == DstRetLLVMTy;
+
+ if (!DstRetTy->isVoidType() && !sameReturnType)
+ return nullptr; // Can't invent return values
+
+ // Reject if signatures are identical (no adaptation needed)
+ if (SrcParams == DstParams && sameReturnType)
+ return nullptr;
+
+ // A null function pointer needs no wrapper — fall through to bitcast
+ if (isa<llvm::ConstantPointerNull>(FnPtr))
+ return nullptr;
+
+ LLVM_DEBUG(llvm::dbgs() << "emitWasmRuntimeFunctionPointerBinding: "
+ << "src params=" << SrcParams
+ << " dst params=" << DstParams << "\n");
+
+ llvm::Module &M = CGF.CGM.getModule();
+ llvm::LLVMContext &Context = M.getContext();
+ llvm::PointerType *PtrTy = llvm::PointerType::getUnqual(Context);
+ llvm::Type *I32Ty = llvm::IntegerType::getInt32Ty(Context);
+
+ // Pre-allocated pool: N wrapper functions + N TLS slots per signature pair.
+ // Each runtime invocation atomically claims a slot. This supports both
+ // "call immediately" and "store for later" patterns without overwrites.
+ static const unsigned POOL_SIZE = 64;
+
+ std::string WrapperName = getRuntimeWrapperName(SrcProto, DstProto,
CGF.CGM.getContext());
+
+ std::string SourceId = M.getSourceFileName();
+ if (SourceId.empty())
+ SourceId = M.getName();
+ for (char &C : SourceId)
+ if (!isalnum(C) && C != '_')
+ C = '_';
+ WrapperName += "_" + SourceId;
+
+ std::string PoolName = "__wasm_runtime_pool_" + WrapperName;
+
+ // Get or create pool globals (once per module per signature pair)
+ llvm::GlobalVariable *Counter = M.getNamedGlobal(PoolName + "_counter");
+ llvm::GlobalVariable *ImmediateSlot = M.getNamedGlobal(PoolName +
"_immediate_slot");
+ llvm::Function *ImmediateWrapper = M.getFunction(WrapperName + "_immediate");
+ llvm::ArrayType *SlotArrayTy = llvm::ArrayType::get(PtrTy, POOL_SIZE);
+ llvm::GlobalVariable *Slots = nullptr;
+ llvm::GlobalVariable *WrapperTable = nullptr;
+ llvm::FunctionType *SrcFnType = nullptr;
+ llvm::FunctionType *DstFnType = nullptr;
+
+ if (!Counter) {
+ SrcFnType = llvm::cast<llvm::FunctionType>(
+ CGF.CGM.getTypes().ConvertType(QualType(SrcProto, 0)));
+ DstFnType = llvm::cast<llvm::FunctionType>(
+ CGF.CGM.getTypes().ConvertType(QualType(DstProto, 0)));
+
+ Counter = new llvm::GlobalVariable(
+ M, I32Ty, false, llvm::GlobalValue::InternalLinkage,
+ llvm::ConstantInt::get(I32Ty, 0), PoolName + "_counter");
+ Counter->setThreadLocalMode(llvm::GlobalValue::GeneralDynamicTLSModel);
+
+ // Immediate-call TLS slot: per-thread, no races, reused every call
+ ImmediateSlot = new llvm::GlobalVariable(
+ M, PtrTy, false, llvm::GlobalValue::InternalLinkage,
+ llvm::ConstantPointerNull::get(PtrTy), PoolName + "_immediate_slot");
+
ImmediateSlot->setThreadLocalMode(llvm::GlobalValue::GeneralDynamicTLSModel);
+
+ // Immediate wrapper: loads from TLS slot, calls with adapted signature
+ ImmediateWrapper = llvm::Function::Create(
+ DstFnType, llvm::GlobalValue::InternalLinkage,
+ WrapperName + "_immediate", M);
+ ImmediateWrapper->addFnAttr(llvm::Attribute::NoInline);
+ ImmediateWrapper->addFnAttr(llvm::Attribute::NoUnwind);
+ {
+ llvm::BasicBlock *BB = llvm::BasicBlock::Create(Context, "entry",
ImmediateWrapper);
+ llvm::IRBuilder<> B(BB);
+ llvm::Value *FP = B.CreateLoad(PtrTy, ImmediateSlot);
+ llvm::BasicBlock *CallBB = llvm::BasicBlock::Create(Context, "call",
ImmediateWrapper);
+ llvm::BasicBlock *NullBB = llvm::BasicBlock::Create(Context, "nullslot",
ImmediateWrapper);
+ B.CreateCondBr(B.CreateIsNotNull(FP), CallBB, NullBB);
+ B.SetInsertPoint(CallBB);
+ llvm::SmallVector<llvm::Value *, 8> ImmArgs;
+ auto AI = ImmediateWrapper->arg_begin();
+ for (unsigned J = 0; J < SrcParams && AI != ImmediateWrapper->arg_end();
++J, ++AI) {
+ llvm::Value *A = &*AI;
+ if (A->getType() != SrcFnType->getParamType(J))
+ A = B.CreateBitOrPointerCast(A, SrcFnType->getParamType(J));
+ ImmArgs.push_back(A);
+ }
+ llvm::CallInst *ImmCall = B.CreateCall(SrcFnType, FP, ImmArgs);
+ if (DstFnType->getReturnType()->isVoidTy()) {
+ B.CreateRetVoid(); B.SetInsertPoint(NullBB); B.CreateRetVoid();
+ } else {
+ llvm::Value *R = ImmCall;
+ if (R->getType() != DstFnType->getReturnType())
+ R = B.CreateBitOrPointerCast(R, DstFnType->getReturnType());
+ B.CreateRet(R);
+ B.SetInsertPoint(NullBB);
+ B.CreateRet(llvm::Constant::getNullValue(DstFnType->getReturnType()));
+ }
+ }
+
+ Slots = new llvm::GlobalVariable(
+ M, SlotArrayTy, false, llvm::GlobalValue::InternalLinkage,
+ llvm::ConstantAggregateZero::get(SlotArrayTy), PoolName + "_slots");
+
+ // 8-entry direct-mapped cache: avoids pool allocation for repeated fn_ptrs
+ static const unsigned CACHE_SIZE = 8;
+ llvm::ArrayType *CacheTy = llvm::ArrayType::get(PtrTy, CACHE_SIZE);
+ new llvm::GlobalVariable(
+ M, CacheTy, false, llvm::GlobalValue::InternalLinkage,
+ llvm::ConstantAggregateZero::get(CacheTy), PoolName + "_cache_keys");
+ new llvm::GlobalVariable(
+ M, CacheTy, false, llvm::GlobalValue::InternalLinkage,
+ llvm::ConstantAggregateZero::get(CacheTy), PoolName +
"_cache_wrappers");
+
+ // Pre-generate POOL_SIZE wrapper functions + build lookup table
+ llvm::SmallVector<llvm::Constant *, 64> WrappersConst;
+ for (unsigned I = 0; I < POOL_SIZE; ++I) {
+ std::string InstName = WrapperName + "_" + std::to_string(I);
+ llvm::Function *W = llvm::Function::Create(
+ DstFnType, llvm::GlobalValue::InternalLinkage, InstName, M);
+ W->addFnAttr(llvm::Attribute::NoInline);
+ W->addFnAttr(llvm::Attribute::NoUnwind);
+
+ llvm::BasicBlock *BB = llvm::BasicBlock::Create(Context, "entry", W);
+ llvm::IRBuilder<> B(BB);
+
+ llvm::Value *SlotPtr = B.CreateConstInBoundsGEP1_32(PtrTy, Slots, I);
+ llvm::Value *FP = B.CreateLoad(PtrTy, SlotPtr);
+
+ // Defensive null check: if slot was never written, skip call
+ llvm::BasicBlock *CallBB = llvm::BasicBlock::Create(Context, "call", W);
+ llvm::BasicBlock *NullBB = llvm::BasicBlock::Create(Context, "nullslot",
W);
+ llvm::Value *IsNotNull = B.CreateIsNotNull(FP);
+ B.CreateCondBr(IsNotNull, CallBB, NullBB);
+
+ B.SetInsertPoint(CallBB);
+ llvm::SmallVector<llvm::Value *, 8> CallArgs;
+ auto ArgIt = W->arg_begin();
+ for (unsigned J = 0; J < SrcParams && ArgIt != W->arg_end(); ++J,
++ArgIt) {
+ llvm::Value *A = &*ArgIt;
+ if (A->getType() != SrcFnType->getParamType(J))
+ A = B.CreateBitOrPointerCast(A, SrcFnType->getParamType(J));
+ CallArgs.push_back(A);
+ }
+ llvm::CallInst *Call = B.CreateCall(SrcFnType, FP, CallArgs);
+
+ if (DstFnType->getReturnType()->isVoidTy()) {
+ B.CreateRetVoid();
+ B.SetInsertPoint(NullBB);
+ B.CreateRetVoid();
+ } else {
+ llvm::Value *Ret = Call;
+ if (Ret->getType() != DstFnType->getReturnType())
+ Ret = B.CreateBitOrPointerCast(Ret, DstFnType->getReturnType());
+ B.CreateRet(Ret);
+ B.SetInsertPoint(NullBB);
+ B.CreateRet(llvm::Constant::getNullValue(DstFnType->getReturnType()));
+ }
+
+ WrappersConst.push_back(llvm::ConstantExpr::getBitCast(W, PtrTy));
+ }
+
+ // Create constant lookup table (not TLS — read-only function pointers)
+ llvm::ArrayType *WrapTblTy = llvm::ArrayType::get(PtrTy, POOL_SIZE);
+ WrapperTable = new llvm::GlobalVariable(
+ M, WrapTblTy, true, llvm::GlobalValue::InternalLinkage,
+ llvm::ConstantArray::get(WrapTblTy, WrappersConst),
+ PoolName + "_wrappers");
+ WrapperTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+ } else {
+ Slots = M.getNamedGlobal(PoolName + "_slots");
+ WrapperTable = M.getNamedGlobal(PoolName + "_wrappers");
+ SrcFnType = llvm::cast<llvm::FunctionType>(
+ CGF.CGM.getTypes().ConvertType(QualType(SrcProto, 0)));
+ }
+
+ // Runtime null check
+ llvm::Value *IsNull = CGF.Builder.CreateIsNull(FnPtr);
+ llvm::BasicBlock *NullContBB = llvm::BasicBlock::Create(Context, "nullcont",
CGF.CurFn);
+ llvm::BasicBlock *NotNullBB = llvm::BasicBlock::Create(Context, "notnull",
CGF.CurFn);
+ CharUnits PtrAlign = CGF.CGM.getPointerAlign();
+
+ if (IsImmediate) {
+ // === Immediate call: 1 TLS slot + 1 wrapper, no branches after null
check ===
+ CGF.Builder.CreateCondBr(IsNull, NullContBB, NotNullBB);
+
+ CGF.Builder.SetInsertPoint(NotNullBB);
+ CGF.Builder.CreateStore(FnPtr, Address(ImmediateSlot, PtrTy, PtrAlign));
+ CGF.Builder.CreateBr(NullContBB);
+
+ CGF.Builder.SetInsertPoint(NullContBB);
+ llvm::PHINode *PHI = CGF.Builder.CreatePHI(PtrTy, 2);
+ PHI->addIncoming(llvm::ConstantExpr::getBitCast(ImmediateWrapper, PtrTy),
NotNullBB);
+ PHI->addIncoming(llvm::ConstantPointerNull::get(PtrTy), NullContBB);
+ return PHI;
+ }
+
+ // === Store-for-later: pool with 64 slots + 8-entry cache + atomic counter
===
+ CGF.Builder.CreateCondBr(IsNull, NullContBB, NotNullBB);
+
+ CGF.Builder.SetInsertPoint(NotNullBB);
+ llvm::ArrayType *WrapTblTy = llvm::ArrayType::get(PtrTy, POOL_SIZE);
+ static const unsigned CACHE_SIZE = 8;
+ llvm::ArrayType *CacheTy = llvm::ArrayType::get(PtrTy, CACHE_SIZE);
+ llvm::GlobalVariable *CacheKeys = M.getNamedGlobal(PoolName + "_cache_keys");
+ llvm::GlobalVariable *CacheWrappers = M.getNamedGlobal(PoolName +
"_cache_wrappers");
+ llvm::BasicBlock *CacheHitBB = llvm::BasicBlock::Create(Context, "cachehit",
CGF.CurFn);
+ llvm::BasicBlock *CacheMissBB = llvm::BasicBlock::Create(Context,
"cachemiss", CGF.CurFn);
+ llvm::BasicBlock *ScanBB = llvm::BasicBlock::Create(Context, "scan",
CGF.CurFn);
+ llvm::BasicBlock *ScanFoundBB = llvm::BasicBlock::Create(Context, "scanfnd",
CGF.CurFn);
+ llvm::BasicBlock *ScanNextBB = llvm::BasicBlock::Create(Context, "scannxt",
CGF.CurFn);
+ llvm::BasicBlock *AllocCheckBB = llvm::BasicBlock::Create(Context,
"allocchk", CGF.CurFn);
+ llvm::BasicBlock *AllocStoreBB = llvm::BasicBlock::Create(Context,
"allocstr", CGF.CurFn);
+ llvm::BasicBlock *OverflowBB = llvm::BasicBlock::Create(Context, "overflow",
CGF.CurFn);
+ llvm::BasicBlock *ContBB = llvm::BasicBlock::Create(Context, "cont",
CGF.CurFn);
+
+ // Cache lookup: idx = (fn_ptr >> 2) & 7
+ llvm::Value *CacheIdx = CGF.Builder.CreateAnd(
+ CGF.Builder.CreateLShr(
+ CGF.Builder.CreatePtrToInt(FnPtr, I32Ty),
+ llvm::ConstantInt::get(I32Ty, 2)),
+ llvm::ConstantInt::get(I32Ty, CACHE_SIZE - 1));
+ llvm::Value *CacheKeyGEP = CGF.Builder.CreateInBoundsGEP(
+ CacheTy, CacheKeys, {llvm::ConstantInt::get(I32Ty, 0), CacheIdx});
+ Address CacheKeyAddr(CacheKeyGEP, PtrTy, PtrAlign);
+ llvm::Value *CachedFn = CGF.Builder.CreateLoad(CacheKeyAddr);
+ llvm::Value *CacheHit = CGF.Builder.CreateICmpEQ(CachedFn, FnPtr);
+ llvm::Value *CacheWrapGEP = CGF.Builder.CreateInBoundsGEP(
+ CacheTy, CacheWrappers, {llvm::ConstantInt::get(I32Ty, 0), CacheIdx});
+ Address CacheWrapAddr(CacheWrapGEP, PtrTy, PtrAlign);
+
+ CGF.Builder.CreateCondBr(CacheHit, CacheHitBB, CacheMissBB);
+
+ // Cache hit: load cached wrapper, branch to cont
+ CGF.Builder.SetInsertPoint(CacheHitBB);
+ llvm::Value *CacheHitW = CGF.Builder.CreateLoad(CacheWrapAddr);
+ CGF.Builder.CreateBr(ContBB);
+
+ // Cache miss: scan pool for existing mapping
+ CGF.Builder.SetInsertPoint(CacheMissBB);
+ CGF.Builder.CreateBr(ScanBB);
+
+ // Scan loop: find fn_ptr in slots[0..POOL_SIZE-1]
+ CGF.Builder.SetInsertPoint(ScanBB);
+ llvm::PHINode *ScanIdx = CGF.Builder.CreatePHI(I32Ty, 2);
+ ScanIdx->addIncoming(llvm::ConstantInt::get(I32Ty, 0), CacheMissBB);
+ llvm::Value *ScanSlotGEP = CGF.Builder.CreateInBoundsGEP(
+ SlotArrayTy, Slots, {llvm::ConstantInt::get(I32Ty, 0), ScanIdx});
+ llvm::Value *ScanFn = CGF.Builder.CreateLoad(Address(ScanSlotGEP, PtrTy,
PtrAlign));
+ llvm::Value *ScanMatch = CGF.Builder.CreateICmpEQ(ScanFn, FnPtr);
+ CGF.Builder.CreateCondBr(ScanMatch, ScanFoundBB, ScanNextBB);
+
+ // Found existing slot: update cache, return existing wrapper
+ CGF.Builder.SetInsertPoint(ScanFoundBB);
+ CGF.Builder.CreateStore(FnPtr, CacheKeyAddr);
+ llvm::Value *FoundWrapGEP = CGF.Builder.CreateInBoundsGEP(
+ WrapTblTy, WrapperTable, {llvm::ConstantInt::get(I32Ty, 0), ScanIdx});
+ llvm::Value *FoundW = CGF.Builder.CreateLoad(Address(FoundWrapGEP, PtrTy,
PtrAlign));
+ CGF.Builder.CreateStore(FoundW, CacheWrapAddr);
+ CGF.Builder.CreateBr(ContBB);
+
+ // Advance scan
+ CGF.Builder.SetInsertPoint(ScanNextBB);
+ llvm::Value *NextIdx = CGF.Builder.CreateAdd(
+ ScanIdx, llvm::ConstantInt::get(I32Ty, 1));
+ llvm::Value *ScanEnd = CGF.Builder.CreateICmpUGE(
+ NextIdx, llvm::ConstantInt::get(I32Ty, POOL_SIZE));
+ ScanIdx->addIncoming(NextIdx, ScanNextBB);
+ CGF.Builder.CreateCondBr(ScanEnd, AllocCheckBB, ScanBB);
+
+ // Allocate new slot: atomic counter increment
+ CGF.Builder.SetInsertPoint(AllocCheckBB);
+ Address CounterAddr(Counter, I32Ty, PtrAlign);
+ llvm::Value *Slot = CGF.Builder.CreateAtomicRMW(
+ llvm::AtomicRMWInst::Add, CounterAddr,
+ llvm::ConstantInt::get(I32Ty, 1), llvm::AtomicOrdering::Monotonic);
+ llvm::Value *InBounds = CGF.Builder.CreateICmpULT(
+ Slot, llvm::ConstantInt::get(I32Ty, POOL_SIZE));
+ CGF.Builder.CreateCondBr(InBounds, AllocStoreBB, OverflowBB);
+
+ // Overflow
+ CGF.Builder.SetInsertPoint(OverflowBB);
+ CGF.Builder.CreateCall(llvm::Intrinsic::getOrInsertDeclaration(
+ &M, llvm::Intrinsic::trap));
+ CGF.Builder.CreateUnreachable();
+
+ // Store in pool + update cache
+ CGF.Builder.SetInsertPoint(AllocStoreBB);
+ llvm::Value *SlotIdx[] = {llvm::ConstantInt::get(I32Ty, 0), Slot};
+ llvm::Value *SlotGEP = CGF.Builder.CreateInBoundsGEP(
+ SlotArrayTy, Slots, SlotIdx);
+ CGF.Builder.CreateStore(FnPtr, Address(SlotGEP, PtrTy, PtrAlign));
+ llvm::Value *WrapGEP = CGF.Builder.CreateInBoundsGEP(
+ WrapTblTy, WrapperTable, SlotIdx);
+ llvm::Value *W = CGF.Builder.CreateLoad(Address(WrapGEP, PtrTy, PtrAlign));
+ CGF.Builder.CreateStore(FnPtr, CacheKeyAddr);
+ CGF.Builder.CreateStore(W, CacheWrapAddr);
+ CGF.Builder.CreateBr(ContBB);
+
+ // Null path
+ CGF.Builder.SetInsertPoint(NullContBB);
+ CGF.Builder.CreateBr(ContBB);
+
+ // ContBB: PHI for result
+ CGF.Builder.SetInsertPoint(ContBB);
+ llvm::PHINode *PHI = CGF.Builder.CreatePHI(PtrTy, 4);
+ PHI->addIncoming(CacheHitW, CacheHitBB);
+ PHI->addIncoming(FoundW, ScanFoundBB);
+ PHI->addIncoming(W, AllocStoreBB);
+ PHI->addIncoming(llvm::ConstantPointerNull::get(PtrTy), NullContBB);
+ return PHI;
+}
+
std::unique_ptr<TargetCodeGenInfo>
CodeGen::createWebAssemblyTargetCodeGenInfo(CodeGenModule &CGM,
WebAssemblyABIKind K) {
return std::make_unique<WebAssemblyTargetCodeGenInfo>(CGM.getTypes(), K);
}
+
+// Helper to get the type signature character for a given QualType
+// Returns a character that represents the given QualType in a wasm signature.
+// See getInvokeSig() in WebAssemblyAsmPrinter for related logic.
+char WebAssemblyTargetCodeGenInfo::getTypeSig(const QualType &Ty,
+ const ASTContext &Ctx) const {
+ if (Ty->isAnyPointerType()) {
----------------
kleisauke wrote:
It looks like `isAnyPointerType()` doesn't catch C++ pointer types, so perhaps
this should be:
```suggestion
if (Ty->isCompoundType()) {
```
While this isn't reproducible with the current changes in this PR, it came up
during the effort to sync `getOrCreateWasmFunctionPointerThunk()` with the
`WebAssemblyFixFunctionBitcasts` pass.
<details>
<summary>Details</summary>
Tested with these changesets:
https://github.com/fluendo/llvm-project/compare/218e499fe206f02894954bbd5aa5ddb3e5e78a48...kleisauke:wasm-function-pointers-rebase6
https://github.com/kleisauke/wasm-vips/compare/1740576a2cdcdd3a31ed6c4a370cd4e357554819...llvm-pr-153168
```console
FAILED: [code=262] gobject/libgobject-2.0.a.p/gsourceclosure.c.o
emcc -Igobject/libgobject-2.0.a.p -Igobject -I../gobject -I. -I.. -Iglib
-I../glib -fvisibility=hidden -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64
-Wall -Winvalid-pch -Wextra -Wpedantic -std=gnu99 -O3 -D_GNU_SOURCE
-fno-strict-aliasing -DG_DISABLE_CAST_CHECKS -DG_DISABLE_ASSERT
-DG_DISABLE_CHECKS -Wfloat-conversion -Wimplicit-fallthrough
-Wmisleading-indentation -Wmissing-field-initializers -Wnonnull
-Wnull-dereference -Wunused -Wno-unused-parameter -Wno-cast-function-type
-Wno-pedantic -Wno-format-zero-length -Wno-variadic-macros -Werror=format=2
-Werror=init-self -Werror=missing-include-dirs -Werror=pointer-arith
-Werror=unused-result -Wstrict-prototypes -Wno-bad-function-cast
-Werror=implicit-function-declaration -Werror=missing-prototypes
-Werror=pointer-sign -Wno-string-plus-int -Wno-typedef-redefinition -Os
-pthread -fwasm-exceptions -fvisibility=hidden -fwasm-fix-function-bitcasts
-msimd128 -DWASM_SIMD_COMPAT_SLOW -fPIC '-DG_LOG_DOMAIN="GLib-GObject"'
-DGOBJECT_COMPILATION -Wsign-conversion -Wshorten-64-to-32 -MD -MQ
gobject/libgobject-2.0.a.p/gsourceclosure.c.o -MF
gobject/libgobject-2.0.a.p/gsourceclosure.c.o.d -o
gobject/libgobject-2.0.a.p/gsourceclosure.c.o -c ../gobject/gsourceclosure.c
../gobject/gsourceclosure.c:82:1: warning: unused function
'io_watch_closure_callback' [-Wunused-function]
82 | io_watch_closure_callback (GIOChannel *channel,
| ^~~~~~~~~~~~~~~~~~~~~~~~~
Unhandled QualType
UNREACHABLE executed at
/home/kleisauke/emsdk/llvm/git/src/clang/lib/CodeGen/Targets/WebAssembly.cpp:707!
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and
include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0. Program arguments:
/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang
-target wasm32-unknown-emscripten -mllvm -combiner-global-alias-analysis=false
-mllvm -wasm-enable-sjlj -mllvm -wasm-use-legacy-eh -mllvm -disable-lsr
--sysroot=/home/kleisauke/emsdk/emscripten/main/cache/sysroot
-D__EMSCRIPTEN_SHARED_MEMORY__=1 -Xclang -iwithsysroot/include/fakesdl -Xclang
-iwithsysroot/include/compat -Igobject/libgobject-2.0.a.p -Igobject
-I../gobject -I. -I.. -Iglib -I../glib -fvisibility=hidden
-fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wextra
-Wpedantic -std=gnu99 -O3 -D_GNU_SOURCE -fno-strict-aliasing
-DG_DISABLE_CAST_CHECKS -DG_DISABLE_ASSERT -DG_DISABLE_CHECKS
-Wfloat-conversion -Wimplicit-fallthrough -Wmisleading-indentation
-Wmissing-field-initializers -Wnonnull -Wnull-dereference -Wunused
-Wno-unused-parameter -Wno-cast-function-type -Wno-pedantic
-Wno-format-zero-length -Wno-variadic-macros -Werror=format=2 -Werror=init-self
-Werror=missing-include-dirs -Werror=pointer-arith -Werror=unused-result
-Wstrict-prototypes -Wno-bad-function-cast
-Werror=implicit-function-declaration -Werror=missing-prototypes
-Werror=pointer-sign -Wno-string-plus-int -Wno-typedef-redefinition -Os
-pthread -fwasm-exceptions -fvisibility=hidden -fwasm-fix-function-bitcasts
-msimd128 -DWASM_SIMD_COMPAT_SLOW -fPIC -DG_LOG_DOMAIN=\"GLib-GObject\"
-DGOBJECT_COMPILATION -Wsign-conversion -Wshorten-64-to-32 -MD -MQ
gobject/libgobject-2.0.a.p/gsourceclosure.c.o -MF
gobject/libgobject-2.0.a.p/gsourceclosure.c.o.d
-ogobject/libgobject-2.0.a.p/gsourceclosure.c.o -c ../gobject/gsourceclosure.c
1. <eof> parser at end of file
2. Per-file LLVM IR generation
3. ../gobject/gsourceclosure.c:32:1 <Spelling=<scratch space>:46:1>:
Generating code for declaration 'g_io_channel_get_type_once'
#0 0x00000000024ea2e1 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int)
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x24ea2e1)
#1 0x00000000024e7ba7 llvm::sys::CleanupOnSignal(unsigned long)
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x24e7ba7)
#2 0x0000000002418144 CrashRecoverySignalHandler(int)
CrashRecoveryContext.cpp:0:0
#3 0x00007efe29d0a0b0 __restore_rt (/lib64/libc.so.6+0x1a0b0)
#4 0x00007efe29d64dcc __pthread_kill_implementation (/lib64/libc.so.6+0x74dcc)
#5 0x00007efe29d09f8e gsignal (/lib64/libc.so.6+0x19f8e)
#6 0x00007efe29cf17b3 abort (/lib64/libc.so.6+0x17b3)
#7 0x0000000002423dbc llvm::llvm_unreachable_internal(char const*, char
const*, unsigned int)
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x2423dbc)
#8 0x0000000002c8fc5d
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x2c8fc5d)
#9 0x0000000002c92271
WebAssemblyTargetCodeGenInfo::getThunkName(std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char>>, clang::FunctionProtoType const*,
clang::ASTContext const&) const
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x2c92271)
#10 0x0000000002c927d5
WebAssemblyTargetCodeGenInfo::getOrCreateWasmFunctionPointerThunk(clang::CodeGen::CodeGenModule&,
llvm::Value*, clang::QualType, clang::QualType) const
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x2c927d5)
#11 0x000000000289fe2a (anonymous
namespace)::ScalarExprEmitter::VisitCastExpr(clang::CastExpr*)
CGExprScalar.cpp:0:0
#12 0x000000000289c59f
clang::CodeGen::CodeGenFunction::EmitScalarExpr(clang::Expr const*, bool)
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x289c59f)
#13 0x0000000002d815a4
clang::CodeGen::CodeGenFunction::EmitScalarInit(clang::Expr const*,
clang::ValueDecl const*, clang::CodeGen::LValue, bool)
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x2d815a4)
#14 0x0000000002d82f70
clang::CodeGen::CodeGenFunction::EmitExprAsInit(clang::Expr const*,
clang::ValueDecl const*, clang::CodeGen::LValue, bool)
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x2d82f70)
#15 0x0000000002d8c3c1
clang::CodeGen::CodeGenFunction::EmitAutoVarInit(clang::CodeGen::CodeGenFunction::AutoVarEmission
const&)
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x2d8c3c1)
#16 0x0000000002d91079
clang::CodeGen::CodeGenFunction::EmitVarDecl(clang::VarDecl const&) (.part.0)
CGDecl.cpp:0:0
#17 0x0000000002d9180d clang::CodeGen::CodeGenFunction::EmitDecl(clang::Decl
const&, bool)
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x2d9180d)
#18 0x00000000029b24d4
clang::CodeGen::CodeGenFunction::EmitDeclStmt(clang::DeclStmt const&)
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x29b24d4)
#19 0x00000000029c73c5
clang::CodeGen::CodeGenFunction::EmitSimpleStmt(clang::Stmt const*,
llvm::ArrayRef<clang::Attr const*>)
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x29c73c5)
#20 0x00000000029be961 clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt
const*, llvm::ArrayRef<clang::Attr const*>)
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x29be961)
#21 0x00000000029c6ec3
clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope(clang::CompoundStmt
const&, bool, clang::CodeGen::AggValueSlot)
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x29c6ec3)
#22 0x0000000002a2f09c
clang::CodeGen::CodeGenFunction::EmitFunctionBody(clang::Stmt const*)
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x2a2f09c)
#23 0x0000000002a46054
clang::CodeGen::CodeGenFunction::GenerateCode(clang::GlobalDecl,
llvm::Function*, clang::CodeGen::CGFunctionInfo const&)
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x2a46054)
#24 0x0000000002aa8270
clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition(clang::GlobalDecl,
llvm::GlobalValue*)
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x2aa8270)
#25 0x0000000002aa3b94
clang::CodeGen::CodeGenModule::EmitGlobalDefinition(clang::GlobalDecl,
llvm::GlobalValue*)
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x2aa3b94)
#26 0x0000000002aaf19e clang::CodeGen::CodeGenModule::EmitDeferred()
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x2aaf19e)
#27 0x0000000002ab134e clang::CodeGen::CodeGenModule::Release()
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x2ab134e)
#28 0x0000000002e46dac (anonymous
namespace)::CodeGeneratorImpl::HandleTranslationUnit(clang::ASTContext&)
ModuleBuilder.cpp:0:0
#29 0x0000000002e43ff5
clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&)
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x2e43ff5)
#30 0x0000000004cb5df4 clang::ParseAST(clang::Sema&, bool, bool)
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x4cb5df4)
#31 0x00000000031d94de clang::FrontendAction::Execute()
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x31d94de)
#32 0x000000000314f03b
clang::CompilerInstance::ExecuteAction(clang::FrontendAction&)
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x314f03b)
#33 0x00000000032e8c92
clang::ExecuteCompilerInvocation(clang::CompilerInstance*)
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x32e8c92)
#34 0x0000000000d3d8af cc1_main(llvm::ArrayRef<char const*>, char const*,
void*)
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0xd3d8af)
#35 0x0000000000d35998 ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&,
llvm::ToolContext const&, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>)
driver.cpp:0:0
#36 0x0000000000d35b7a int llvm::function_ref<int (llvm::SmallVectorImpl<char
const*>&)>::callback_fn<clang_main(int, char**, llvm::ToolContext
const&)::'lambda'(llvm::SmallVectorImpl<char const*>&)>(long,
llvm::SmallVectorImpl<char const*>&) driver.cpp:0:0
#37 0x0000000002eb8d39 void llvm::function_ref<void
()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>,
std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char>>*, bool*) const::'lambda'()>(long) Job.cpp:0:0
#38 0x000000000241854b
llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>)
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x241854b)
#39 0x0000000002eb95cd
clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>,
std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char>>*, bool*) const (.part.0) Job.cpp:0:0
#40 0x0000000002e748ef
clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&,
clang::driver::Command const*&, bool) const
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x2e748ef)
#41 0x0000000002e758ef
clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&,
llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool)
const
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x2e758ef)
#42 0x0000000002e83815
clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&,
llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&)
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0x2e83815)
#43 0x0000000000d3ad93 clang_main(int, char**, llvm::ToolContext const&)
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0xd3ad93)
#44 0x0000000000c10654 main
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0xc10654)
#45 0x00007efe29cf3681 __libc_start_call_main (/lib64/libc.so.6+0x3681)
#46 0x00007efe29cf3798 __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x3798)
#47 0x0000000000d34be5 _start
(/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin/clang+0xd34be5)
clang: error: clang frontend command failed due to signal (use -v to see
invocation)
clang version 23.0.0git (https://github.com/kleisauke/llvm-project
8c8189494b548b0fc6ba858701daae043c7b8306)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir:
/home/kleisauke/emsdk/llvm/git/build_wasm-function-pointers-rebase6_64/bin
Build config: +assertions
clang: note: diagnostic msg:
********************
PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang: note: diagnostic msg: /tmp/gsourceclosure-b0b801.c
clang: note: diagnostic msg: /tmp/gsourceclosure-b0b801.sh
clang: note: diagnostic msg:
********************
```
</details>
https://github.com/llvm/llvm-project/pull/153168
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits