fix(codegen): split raw IR by envelope length instead of a marker string
This commit is contained in:
1 parent
9e47c0ebc4
commit
e761a85ca7
1 file changed
+51
-19
@@ -56,7 +56,41 @@ MLIR_TRANSLATE_CMD: str = "mlir-translate"
|
||||
# body behaves like inline IR again.
|
||||
LLVM_LINK_CMD: str = "llvm-link"
|
||||
INLINE_PASSES: str = "always-inline,globaldce"
|
||||
define RAW_LLVM_MARKER = "//__VPC_RAW_LLVM__"
|
||||
define RAW_ENVELOPE_PREFIX = "//__VPC_RAWIR__ "
|
||||
|
||||
|
||||
def _parse_raw_envelope(ir_buf: bytes, ir_len: sizet, inline_out: int*, raw_len_out: sizet*) -> sizet:
|
||||
"""Parse the FULL-artifact envelope written by mlirlite.
|
||||
|
||||
Format: "<prefix><inline 0|1> <raw byte length>\n<raw LLVM text><MLIR module>".
|
||||
Returns the raw section's start offset (0 = no envelope) and fills the flag/length outputs.
|
||||
"""
|
||||
if inline_out is not None: inline_out[0] = 0
|
||||
if raw_len_out is not None: raw_len_out[0] = 0
|
||||
if ir_buf is None: return 0
|
||||
plen: sizet = string.strlen(RAW_ENVELOPE_PREFIX)
|
||||
if ir_len <= plen + 3: return 0
|
||||
if string.strncmp(ir_buf, RAW_ENVELOPE_PREFIX, plen) != 0: return 0
|
||||
i: sizet = plen
|
||||
while i < ir_len and ir_buf[i] == ' ': i += 1
|
||||
if i >= ir_len or (ir_buf[i] != '0' and ir_buf[i] != '1'): return 0
|
||||
inl: int = 0
|
||||
if ir_buf[i] == '1': inl = 1
|
||||
i += 1
|
||||
while i < ir_len and ir_buf[i] == ' ': i += 1
|
||||
rl: sizet = 0
|
||||
digits: int = 0
|
||||
while i < ir_len and ir_buf[i] >= '0' and ir_buf[i] <= '9':
|
||||
rl = rl * 10 + sizet(int(ir_buf[i]) - 48)
|
||||
i += 1
|
||||
digits += 1
|
||||
if digits == 0: return 0
|
||||
while i < ir_len and ir_buf[i] == '\r': i += 1
|
||||
if i >= ir_len or ir_buf[i] != '\n': return 0
|
||||
if inline_out is not None: inline_out[0] = inl
|
||||
if raw_len_out is not None: raw_len_out[0] = rl
|
||||
return i + 1
|
||||
|
||||
|
||||
|
||||
def _file_exists(path: str) -> int:
|
||||
@@ -355,19 +389,20 @@ def build_sliced_path(base_dir: str, sha1: str, ext: str) -> str:
|
||||
|
||||
|
||||
def write_ir_to_file(ir_buf: bytes, ir_len: sizet, output_dir: str, module_name: str) -> int:
|
||||
"""Write the IR buffer to <sha1>.ll; raw LLVM text is split into <sha1>.raw.ll."""
|
||||
"""Write the IR buffer to <sha1>.ll; the envelope's raw LLVM text becomes <sha1>.raw.ll."""
|
||||
if ir_buf is None or output_dir is None or module_name is None: return 1
|
||||
|
||||
# Raw LLVM functions (__llvmir__) follow a marker after the MLIR module: split them out so
|
||||
# mlir-opt only ever receives the MLIR module.
|
||||
raw_pos: str = string.strstr(ir_buf, RAW_LLVM_MARKER)
|
||||
mlir_len: sizet = ir_len
|
||||
raw_start: sizet = 0
|
||||
if raw_pos is not None:
|
||||
mlir_len = sizet(uint64(raw_pos) - uint64(ir_buf))
|
||||
raw_start = mlir_len + string.strlen(RAW_LLVM_MARKER)
|
||||
while raw_start < ir_len and (ir_buf[raw_start] == '\r' or ir_buf[raw_start] == '\n'):
|
||||
raw_start += 1
|
||||
# FULL artifacts carry a length-prefixed envelope (see _parse_raw_envelope); STUB/TEXT
|
||||
# artifacts have none and are written verbatim.
|
||||
inline_flag: int = 0
|
||||
raw_len: sizet = 0
|
||||
raw_start: sizet = _parse_raw_envelope(ir_buf, ir_len, &inline_flag, &raw_len)
|
||||
if raw_start > ir_len: raw_start = ir_len
|
||||
if raw_len > ir_len - raw_start: raw_len = ir_len - raw_start
|
||||
mlir_start: sizet = raw_start
|
||||
if raw_len > 0: mlir_start = raw_start + raw_len
|
||||
if mlir_start > ir_len: mlir_start = ir_len
|
||||
mlir_len: sizet = ir_len - mlir_start
|
||||
|
||||
# build sliced path: output_dir/{sha1 prefix}/{module_name}.ll
|
||||
path: str = build_sliced_path(output_dir, module_name, "ll")
|
||||
@@ -377,25 +412,22 @@ def write_ir_to_file(ir_buf: bytes, ir_len: sizet, output_dir: str, module_name:
|
||||
f: io.File* = io.File(path, io.MODE.W)
|
||||
if f.closed: return 1
|
||||
|
||||
written: int64 = f.write(ir_buf, mlir_len)
|
||||
written: int64 = f.write(ir_buf + mlir_start, mlir_len)
|
||||
f.close()
|
||||
if written < 0: return 1
|
||||
|
||||
if raw_pos is not None and ir_len > raw_start:
|
||||
if raw_len > 0:
|
||||
raw_path: str = build_sliced_path(output_dir, module_name, "raw.ll")
|
||||
if raw_path is None: return 1
|
||||
rf: io.File* = io.File(raw_path, io.MODE.W)
|
||||
if rf.closed: return 1
|
||||
rw: int64 = rf.write(ir_buf + raw_start, ir_len - raw_start)
|
||||
rw: int64 = rf.write(ir_buf + raw_start, raw_len)
|
||||
rf.close()
|
||||
if rw < 0: return 1
|
||||
|
||||
# Inline-pass marker: raw LLVM functions and/or a raw-MLIR body (__mlir__) are present, so
|
||||
# the object must go through opt -passes=always-inline,globaldce before llc.
|
||||
need_inline: int = 0
|
||||
if raw_pos is not None: need_inline = 1
|
||||
elif string.strstr(ir_buf, ".__vpc_mlir_") is not None: need_inline = 1
|
||||
if need_inline != 0:
|
||||
if inline_flag != 0 or raw_len > 0:
|
||||
flag_path: str = build_sliced_path(output_dir, module_name, "inline")
|
||||
if flag_path is None: return 1
|
||||
ff: io.File* = io.File(flag_path, io.MODE.W)
|
||||
|
||||
Reference in new issue
Block a user