diff --git a/App/lib/Phase/BuildPipeline.vp b/App/lib/Phase/BuildPipeline.vp index c275722..e7ffd03 100644 --- a/App/lib/Phase/BuildPipeline.vp +++ b/App/lib/Phase/BuildPipeline.vp @@ -79,6 +79,7 @@ _phaseb_backend: int = PHASEB_BACKEND_IRCORE _ircore_lib: win32.win32base.HANDLE = None _ircore_ready: int = 0 _ircore_obj_fn: callable[[char*, sizet, char**, sizet*, char**, sizet*], int] = None +_ircore_asan_fn: callable[[char*, sizet, char**, sizet*, char**, sizet*], int] = None _ircore_free_fn: callable[[char*], int] = None # ircore.dll imports the exact LLVM build it was compiled with (MSYS2 clang64 22.1.x). @@ -90,8 +91,8 @@ extern def SetDllDirectoryA(lpPathName: LPCSTR) -> BOOL def _ircore_load() -> int: - """Load ircore.dll and resolve its two entry points; 1 = available, 0 = not available.""" - global _ircore_lib, _ircore_obj_fn, _ircore_free_fn + """Load ircore.dll and resolve its entry points; 1 = available, 0 = not available.""" + global _ircore_lib, _ircore_obj_fn, _ircore_asan_fn, _ircore_free_fn if _ircore_lib is not None: return 1 h: win32.win32base.HANDLE = win32.win32base.LoadLibraryA("ircore.dll") if h is None: @@ -101,11 +102,13 @@ def _ircore_load() -> int: if h is None: return 0 p_obj: win32.win32base.VOIDPTR = win32.win32base.GetProcAddress(h, "ircore_mlir_to_obj") + p_asan: win32.win32base.VOIDPTR = win32.win32base.GetProcAddress(h, "ircore_mlir_to_obj_asan") p_free: win32.win32base.VOIDPTR = win32.win32base.GetProcAddress(h, "ircore_free") - if p_obj is None or p_free is None: + if p_obj is None or p_asan is None or p_free is None: win32.win32base.FreeLibrary(h) return 0 _ircore_obj_fn = p_obj + _ircore_asan_fn = p_asan _ircore_free_fn = p_free _ircore_lib = h return 1 @@ -545,7 +548,12 @@ def _ircore_compile_module(ir_path: str, obj_path: str, module_name: str) -> int out_len: sizet = 0 err: char* = None err_len: sizet = 0 - rc: int = _ircore_obj_fn(src, sizet(fsize), &out_obj, &out_len, &err, &err_len) + # --asan: the DLL runs forceattrs,asan before codegen (same passes/options as the legacy + # `opt -passes=forceattrs,asan ...` step); the project still links the ASan runtime. + if _asan_mode != 0: + rc: int = _ircore_asan_fn(src, sizet(fsize), &out_obj, &out_len, &err, &err_len) + else: + rc: int = _ircore_obj_fn(src, sizet(fsize), &out_obj, &out_len, &err, &err_len) stdlib.free(src) if rc != 0: @@ -583,7 +591,7 @@ def compile_ll_to_obj(ir_path: str, output_dir: str, module_name: str, cc_cmd: s # IRCore backend: one in-process call for plain modules. ASan instrumentation, raw-IR # merging (llvm-link/opt), --traceback frame pointers and --phase2command still need the # external tools, so they fall through to the legacy command flow below (kept intact). - if _phaseb_ircore_active() != 0 and _asan_mode == 0 and _traceback_mode == 0 \ + if _phaseb_ircore_active() != 0 and _traceback_mode == 0 \ and _phase2_cmd_path is None: raw_sidecar: str = _ir_sibling_path(ir_path, ".raw.ll") inline_marker: str = _ir_sibling_path(ir_path, ".inline") @@ -832,7 +840,7 @@ def init_llc_task(task: LlcTask*, ir_path: str, output_dir: str, module_name: st # IRCore backend: plain modules compile in-process (the commands above stay allocated for # the legacy path / reporting but are not run). ASan instrumentation, raw-IR merging and # --phase2command keep the external tools. - if _phaseb_ircore_active() != 0 and _asan_mode == 0 and _traceback_mode == 0 \ + if _phaseb_ircore_active() != 0 and _traceback_mode == 0 \ and _phase2_cmd_path is None and has_raw == 0 and need_inline == 0: task.UseIrcore = 1 task.IrPath = stdlib.malloc(len(ir_path) + 1) @@ -2271,7 +2279,7 @@ def _tb_read_whole(mb: memhub.MemBuddy*, path: str) -> str: if buf is None: f.close() return None - # 容量全程用 sizet(与 sz 同宽):旧写法 ULONG(sz) + ULONG(2) 会在 sz >= 4GiB 时静默回绕 + # 容量全程�?sizet(与 sz 同宽):旧写�?ULONG(sz) + ULONG(2) 会在 sz >= 4GiB 时静默回�? got: LONG = f.read_all(buf, sizet(sz) + 2) f.close() if got < 0: return None