@@ -3681,6 +3681,23 @@ struct GlobalOpLowering : public TsLlvmPattern<mlir_ts::GlobalOp>
36813681
36823682 LLVMCodeHelper lch (globalOp, rewriter, getTypeConverter (), tsLlvmContext->compileOptions );
36833683
3684+ // A ConstantOp whose *TupleType/ConstTupleType result* has a bound-method
3685+ // field (e.g. a plain `const obj = { ..., method() {} }` at global scope)
3686+ // lowers its method field via LLVM::AddressOfOp + LLVM::InsertValueOp (see
3687+ // LLVMCodeHelper::getTupleFromArrayAttr) -- not valid inside a static LLVM
3688+ // global initializer region, only inside real code (a function), so such a
3689+ // global must go through the constructor path below. Deliberately narrower
3690+ // than "any ConstantOp whose attribute contains a FlatSymbolRefAttr": that
3691+ // broader check also caught MSVC RTTI/EH type-descriptor globals (e.g.
3692+ // `??_R0PEAD@8`, which reference the `type_info` vtable symbol) that are
3693+ // NOT mlir_ts tuple types and were already lowering correctly as static
3694+ // data -- forcing those through the constructor path broke JIT symbol
3695+ // materialization for the whole module.
3696+ MLIRTypeHelper mth (rewriter.getContext (), tsLlvmContext->compileOptions );
3697+ auto isBoundMethodTupleConstant = [&](mlir_ts::ConstantOp constantOp) {
3698+ return mth.hasBoundMethodField (constantOp.getType ());
3699+ };
3700+
36843701 auto createAsGlobalConstructor = false ;
36853702 // TODO: we need to write correct attributes to Ops and detect which ops should be in GlobalConstructor
36863703 auto visitorAllOps = [&](Operation *op) {
@@ -3700,9 +3717,16 @@ struct GlobalOpLowering : public TsLlvmPattern<mlir_ts::GlobalOp>
37003717 else if (auto castOp = dyn_cast<mlir_ts::CastOp>(op))
37013718 {
37023719 auto castType = castOp.getRes ().getType ();
3703- if (isa<mlir_ts::ArrayType>(castType) || isa<mlir_ts::TupleType>(castType))
3720+ if (isa<mlir_ts::ArrayType>(castType) || isa<mlir_ts::TupleType>(castType))
3721+ {
3722+ createAsGlobalConstructor = true ;
3723+ }
3724+ }
3725+ else if (auto constantOp = dyn_cast<mlir_ts::ConstantOp>(op))
3726+ {
3727+ if (isBoundMethodTupleConstant (constantOp))
37043728 {
3705- createAsGlobalConstructor = true ;
3729+ createAsGlobalConstructor = true ;
37063730 }
37073731 }
37083732
0 commit comments