snapshot before regression test
This commit is contained in:
155
lib/core/Handles/HandlesRaise.py
Normal file
155
lib/core/Handles/HandlesRaise.py
Normal file
@@ -0,0 +1,155 @@
|
||||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
if TYPE_CHECKING:
|
||||
from lib.core.translator import Translator
|
||||
import ast
|
||||
import llvmlite.ir as ir
|
||||
from lib.core.Handles.HandlesBase import BaseHandle, EXCEPTION_CODE_MAP
|
||||
from lib.constants.config import mode as _config_mode
|
||||
|
||||
|
||||
class RaiseHandle(BaseHandle):
|
||||
def _get_exception_code(self, ExcName: str) -> int:
|
||||
if ExcName in EXCEPTION_CODE_MAP:
|
||||
return EXCEPTION_CODE_MAP[ExcName]
|
||||
if ExcName in self.Trans.exception_registry:
|
||||
return self.Trans.exception_registry[ExcName]
|
||||
return 1
|
||||
|
||||
def _HandleRaiseLlvm(self, Node: ast.Raise) -> None:
|
||||
Gen: "Translator.LlvmGen" = self.Trans.LlvmGen
|
||||
exc_val: ir.Constant = ir.Constant(ir.IntType(32), 1)
|
||||
exc_msg: ir.Value | None = None
|
||||
IsStopIteration: bool = False
|
||||
if Node.exc:
|
||||
if isinstance(Node.exc, ast.Constant) and isinstance(Node.exc.value, int):
|
||||
exc_val = ir.Constant(ir.IntType(32), Node.exc.value)
|
||||
elif isinstance(Node.exc, ast.Name):
|
||||
ExcName: str = Node.exc.id
|
||||
if ExcName == 'StopIteration':
|
||||
IsStopIteration = True
|
||||
exc_val = ir.Constant(ir.IntType(32), self._get_exception_code(ExcName))
|
||||
elif isinstance(Node.exc, ast.Call) and isinstance(Node.exc.func, ast.Name):
|
||||
ExcName: str = Node.exc.func.id
|
||||
if ExcName == 'StopIteration':
|
||||
IsStopIteration = True
|
||||
exc_val = ir.Constant(ir.IntType(32), self._get_exception_code(ExcName))
|
||||
if Node.exc.args:
|
||||
first_arg: ast.expr = Node.exc.args[0]
|
||||
if isinstance(first_arg, ast.Constant) and isinstance(first_arg.value, str):
|
||||
exc_msg = self.HandleExprLlvm(first_arg)
|
||||
elif isinstance(first_arg, (ast.Name, ast.Call, ast.Attribute)):
|
||||
arg_val: ir.Value | None = self.HandleExprLlvm(first_arg)
|
||||
if arg_val:
|
||||
if isinstance(arg_val.type, ir.PointerType):
|
||||
if self._is_char_pointer(arg_val):
|
||||
exc_msg = arg_val
|
||||
else:
|
||||
try:
|
||||
exc_msg = Gen.builder.bitcast(arg_val, ir.PointerType(ir.IntType(8)), name="exc_msg_cast")
|
||||
except Exception as _e:
|
||||
if _config_mode == "strict":
|
||||
self.Trans.LogWarning(f"异常被忽略: {_e}")
|
||||
else:
|
||||
try:
|
||||
exc_msg = Gen.builder.inttoptr(arg_val, ir.PointerType(ir.IntType(8)), name="exc_msg_ptr")
|
||||
except Exception as _e:
|
||||
if _config_mode == "strict":
|
||||
self.Trans.LogWarning(f"异常被忽略: {_e}")
|
||||
else:
|
||||
val: ir.Value | None = self.HandleExprLlvm(Node.exc)
|
||||
if val:
|
||||
if isinstance(val.type, ir.IntType):
|
||||
if val.type.width != 32:
|
||||
try:
|
||||
val = Gen.builder.trunc(val, ir.IntType(32), name="exc_trunc")
|
||||
except Exception: # 回退:trunc 失败时设默认值 1
|
||||
val = ir.Constant(ir.IntType(32), 1)
|
||||
exc_val = val
|
||||
else:
|
||||
try:
|
||||
val = Gen.builder.ptrtoint(val, ir.IntType(32), name="exc_ptr2int")
|
||||
exc_val = val
|
||||
except Exception as _e:
|
||||
if _config_mode == "strict":
|
||||
self.Trans.LogWarning(f"异常被忽略: {_e}")
|
||||
if IsStopIteration:
|
||||
if Gen._stop_iter_flag_param is not None:
|
||||
Gen.builder.store(ir.Constant(ir.IntType(1), 1), Gen._stop_iter_flag_param)
|
||||
if Gen.func and Gen.func.type.pointee.return_type != ir.VoidType():
|
||||
ret_type: ir.Type = Gen.func.type.pointee.return_type
|
||||
if isinstance(ret_type, ir.PointerType):
|
||||
Gen.builder.ret(ir.Constant(ret_type, None))
|
||||
elif isinstance(ret_type, ir.IntType):
|
||||
Gen.builder.ret(ir.Constant(ret_type, 0))
|
||||
elif isinstance(ret_type, (ir.FloatType, ir.DoubleType)):
|
||||
Gen.builder.ret(ir.Constant(ret_type, 0.0))
|
||||
elif isinstance(ret_type, ir.BaseStructType):
|
||||
if ret_type.elements:
|
||||
zero_val: ir.Constant = ir.Constant(ret_type, [
|
||||
ir.Constant(et, None) if isinstance(et, (ir.PointerType, ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType))
|
||||
else ir.Constant(et, 0) if isinstance(et, (ir.IntType, ir.FloatType, ir.DoubleType))
|
||||
else ir.Constant(et, ir.Undefined) for et in ret_type.elements])
|
||||
else:
|
||||
zero_val = ir.Constant(ret_type, None)
|
||||
Gen.builder.ret(zero_val)
|
||||
else:
|
||||
Gen.builder.ret(ir.Constant(ret_type, 0))
|
||||
else:
|
||||
Gen.builder.ret_void()
|
||||
return
|
||||
if Gen.eh_except_block_stack:
|
||||
ExceptBB: ir.Block = Gen.eh_except_block_stack[-1][0]
|
||||
EndBB: ir.Block | None = Gen.eh_except_block_stack[-1][1]
|
||||
exception_code: ir.AllocaInstr = Gen.eh_except_block_stack[-1][2]
|
||||
eh_message: ir.AllocaInstr = Gen.eh_except_block_stack[-1][3]
|
||||
Gen._store(exc_val, exception_code)
|
||||
if exc_msg:
|
||||
Gen._store(exc_msg, eh_message)
|
||||
else:
|
||||
null_ptr: ir.Constant = ir.Constant(ir.PointerType(ir.IntType(8)), None)
|
||||
Gen._store(null_ptr, eh_message)
|
||||
if Gen.func and ExceptBB and ExceptBB.function is Gen.func:
|
||||
Gen.builder.branch(ExceptBB)
|
||||
else:
|
||||
eh_msg_arg: ir.Argument | None = None
|
||||
eh_code_arg: ir.Argument | None = None
|
||||
if Gen.func:
|
||||
for arg in Gen.func.args:
|
||||
if arg.name == '__eh_msg_out__':
|
||||
eh_msg_arg = arg
|
||||
elif arg.name == '__eh_code_out__':
|
||||
eh_code_arg = arg
|
||||
if eh_msg_arg is not None:
|
||||
if exc_msg:
|
||||
Gen.builder.store(exc_msg, eh_msg_arg)
|
||||
else:
|
||||
null_ptr = ir.Constant(ir.PointerType(ir.IntType(8)), None)
|
||||
Gen.builder.store(null_ptr, eh_msg_arg)
|
||||
if eh_code_arg is not None:
|
||||
Gen.builder.store(exc_val, eh_code_arg)
|
||||
if Gen.func and Gen.func.type.pointee.return_type == ir.IntType(32):
|
||||
Gen.builder.ret(ir.Constant(ir.IntType(32), 1))
|
||||
else:
|
||||
Gen.builder.ret_void()
|
||||
else:
|
||||
eh_msg_arg: ir.Argument | None = None
|
||||
eh_code_arg: ir.Argument | None = None
|
||||
if Gen.func:
|
||||
for arg in Gen.func.args:
|
||||
if arg.name == '__eh_msg_out__':
|
||||
eh_msg_arg = arg
|
||||
elif arg.name == '__eh_code_out__':
|
||||
eh_code_arg = arg
|
||||
if eh_msg_arg is not None:
|
||||
if exc_msg:
|
||||
Gen.builder.store(exc_msg, eh_msg_arg)
|
||||
else:
|
||||
null_ptr: ir.Constant = ir.Constant(ir.PointerType(ir.IntType(8)), None)
|
||||
Gen.builder.store(null_ptr, eh_msg_arg)
|
||||
if eh_code_arg is not None:
|
||||
Gen.builder.store(exc_val, eh_code_arg)
|
||||
if Gen.func and Gen.func.type.pointee.return_type == ir.IntType(32):
|
||||
Gen.builder.ret(ir.Constant(ir.IntType(32), 1))
|
||||
else:
|
||||
Gen.builder.ret_void()
|
||||
Reference in New Issue
Block a user