diff --git a/mlirlite/__builder.vp b/mlirlite/__builder.vp index f364777..22047bc 100644 --- a/mlirlite/__builder.vp +++ b/mlirlite/__builder.vp @@ -266,6 +266,38 @@ novirtual class IRBuilder: self._emit(line) + def build_store_at_entry(self, val: Value*, ptr: Value*, + is_volatile: int = 0): + """store [volatile ] , , emitted in the **entry block** + (inserted before the entry terminator) so the write dominates every path. + + Used to zero/null-initialize a local slot at function entry: a slot that is not + assigned on some path must still hold a safe value, e.g. the M3 owned-slife guard — + the exit-time `free(load slot)` must be `free(NULL)` (a no-op) instead of freeing + uninitialized stack garbage. Mirrors build_alloca_at_entry's insertion strategy. + """ + if self is None or val is None or ptr is None: return + pool: memhub.MemBuddy* = self.Pool + func: Function* = self.Func + if func is None or func.Blocks is None: + self.build_store(val, ptr, is_volatile) + return + blocks: GSList[BasicBlock]* = func.Blocks + entry_blk: BasicBlock* = blocks.Head + if entry_blk is None: + self.build_store(val, ptr, is_volatile) + return + val_ty_s: str = self._type_str(val.Ty) + ptr_ty_s: str = self._type_str(ptr.Ty) + line: str = pool.alloc(_LINE_CAP) + if line is None: return + if is_volatile != 0: + viperlib.snprintf(line, _LINE_CAP, "store volatile %s %s, %s %s", val_ty_s, val.Name, ptr_ty_s, ptr.Name) + else: + viperlib.snprintf(line, _LINE_CAP, "store %s %s, %s %s", val_ty_s, val.Name, ptr_ty_s, ptr.Name) + block_insert_text_before_terminator(pool, entry_blk, line) + + # ============================================================ # Binary operation instructions # ============================================================ @@ -1298,6 +1330,14 @@ def build_store(builder: IRBuilder*, val: Value*, ptr: Value*, builder.build_store(val, ptr, is_volatile) +def build_store_at_entry(builder: IRBuilder*, val: Value*, ptr: Value*, + is_volatile: int = 0): + """store [volatile ] , emitted in the entry block + (before the entry terminator) so the write dominates every path; used for + null-initializing a local slot at function entry (M3 owned-slife guard).""" + builder.build_store_at_entry(val, ptr, is_volatile) + + # ============================================================ # Binary operation instructions # ============================================================ diff --git a/mlirlite/__init__.vp b/mlirlite/__init__.vp index 857bc08..51346eb 100644 --- a/mlirlite/__init__.vp +++ b/mlirlite/__init__.vp @@ -62,6 +62,7 @@ from .__builder import ( builder_cur_block_is_terminated, builder_set_debug_location, builder_clear_debug_location, build_alloca, build_alloca_aligned, build_alloca_at_entry, build_load, build_store, + build_store_at_entry, build_add, build_sub, build_mul, build_sdiv, build_udiv, build_srem, build_urem, build_and, build_or, build_xor, build_shl, build_lshr, build_ashr, build_fadd, build_fsub, build_fmul, build_fdiv, build_frem, build_fneg,