emitfunc.py 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  1. """Code generation for native function bodies."""
  2. from __future__ import annotations
  3. from typing_extensions import Final
  4. from mypyc.analysis.blockfreq import frequently_executed_blocks
  5. from mypyc.codegen.emit import DEBUG_ERRORS, Emitter, TracebackAndGotoHandler, c_array_initializer
  6. from mypyc.common import MODULE_PREFIX, NATIVE_PREFIX, REG_PREFIX, STATIC_PREFIX, TYPE_PREFIX
  7. from mypyc.ir.class_ir import ClassIR
  8. from mypyc.ir.func_ir import FUNC_CLASSMETHOD, FUNC_STATICMETHOD, FuncDecl, FuncIR, all_values
  9. from mypyc.ir.ops import (
  10. ERR_FALSE,
  11. NAMESPACE_MODULE,
  12. NAMESPACE_STATIC,
  13. NAMESPACE_TYPE,
  14. Assign,
  15. AssignMulti,
  16. BasicBlock,
  17. Box,
  18. Branch,
  19. Call,
  20. CallC,
  21. Cast,
  22. ComparisonOp,
  23. ControlOp,
  24. DecRef,
  25. Extend,
  26. Float,
  27. FloatComparisonOp,
  28. FloatNeg,
  29. FloatOp,
  30. GetAttr,
  31. GetElementPtr,
  32. Goto,
  33. IncRef,
  34. InitStatic,
  35. Integer,
  36. IntOp,
  37. KeepAlive,
  38. LoadAddress,
  39. LoadErrorValue,
  40. LoadGlobal,
  41. LoadLiteral,
  42. LoadMem,
  43. LoadStatic,
  44. MethodCall,
  45. Op,
  46. OpVisitor,
  47. RaiseStandardError,
  48. Register,
  49. Return,
  50. SetAttr,
  51. SetMem,
  52. Truncate,
  53. TupleGet,
  54. TupleSet,
  55. Unbox,
  56. Unreachable,
  57. Value,
  58. )
  59. from mypyc.ir.pprint import generate_names_for_ir
  60. from mypyc.ir.rtypes import (
  61. RArray,
  62. RStruct,
  63. RTuple,
  64. RType,
  65. is_int32_rprimitive,
  66. is_int64_rprimitive,
  67. is_int_rprimitive,
  68. is_pointer_rprimitive,
  69. is_tagged,
  70. )
  71. def native_function_type(fn: FuncIR, emitter: Emitter) -> str:
  72. args = ", ".join(emitter.ctype(arg.type) for arg in fn.args) or "void"
  73. ret = emitter.ctype(fn.ret_type)
  74. return f"{ret} (*)({args})"
  75. def native_function_header(fn: FuncDecl, emitter: Emitter) -> str:
  76. args = []
  77. for arg in fn.sig.args:
  78. args.append(f"{emitter.ctype_spaced(arg.type)}{REG_PREFIX}{arg.name}")
  79. return "{ret_type}{name}({args})".format(
  80. ret_type=emitter.ctype_spaced(fn.sig.ret_type),
  81. name=emitter.native_function_name(fn),
  82. args=", ".join(args) or "void",
  83. )
  84. def generate_native_function(
  85. fn: FuncIR, emitter: Emitter, source_path: str, module_name: str
  86. ) -> None:
  87. declarations = Emitter(emitter.context)
  88. names = generate_names_for_ir(fn.arg_regs, fn.blocks)
  89. body = Emitter(emitter.context, names)
  90. visitor = FunctionEmitterVisitor(body, declarations, source_path, module_name)
  91. declarations.emit_line(f"{native_function_header(fn.decl, emitter)} {{")
  92. body.indent()
  93. for r in all_values(fn.arg_regs, fn.blocks):
  94. if isinstance(r.type, RTuple):
  95. emitter.declare_tuple_struct(r.type)
  96. if isinstance(r.type, RArray):
  97. continue # Special: declared on first assignment
  98. if r in fn.arg_regs:
  99. continue # Skip the arguments
  100. ctype = emitter.ctype_spaced(r.type)
  101. init = ""
  102. declarations.emit_line(
  103. "{ctype}{prefix}{name}{init};".format(
  104. ctype=ctype, prefix=REG_PREFIX, name=names[r], init=init
  105. )
  106. )
  107. # Before we emit the blocks, give them all labels
  108. blocks = fn.blocks
  109. for i, block in enumerate(blocks):
  110. block.label = i
  111. # Find blocks that are never jumped to or are only jumped to from the
  112. # block directly above it. This allows for more labels and gotos to be
  113. # eliminated during code generation.
  114. for block in fn.blocks:
  115. terminator = block.terminator
  116. assert isinstance(terminator, ControlOp)
  117. for target in terminator.targets():
  118. is_next_block = target.label == block.label + 1
  119. # Always emit labels for GetAttr error checks since the emit code that
  120. # generates them will add instructions between the branch and the
  121. # next label, causing the label to be wrongly removed. A better
  122. # solution would be to change the IR so that it adds a basic block
  123. # inbetween the calls.
  124. is_problematic_op = isinstance(terminator, Branch) and any(
  125. isinstance(s, GetAttr) for s in terminator.sources()
  126. )
  127. if not is_next_block or is_problematic_op:
  128. fn.blocks[target.label].referenced = True
  129. common = frequently_executed_blocks(fn.blocks[0])
  130. for i in range(len(blocks)):
  131. block = blocks[i]
  132. visitor.rare = block not in common
  133. next_block = None
  134. if i + 1 < len(blocks):
  135. next_block = blocks[i + 1]
  136. body.emit_label(block)
  137. visitor.next_block = next_block
  138. ops = block.ops
  139. visitor.ops = ops
  140. visitor.op_index = 0
  141. while visitor.op_index < len(ops):
  142. ops[visitor.op_index].accept(visitor)
  143. visitor.op_index += 1
  144. body.emit_line("}")
  145. emitter.emit_from_emitter(declarations)
  146. emitter.emit_from_emitter(body)
  147. class FunctionEmitterVisitor(OpVisitor[None]):
  148. def __init__(
  149. self, emitter: Emitter, declarations: Emitter, source_path: str, module_name: str
  150. ) -> None:
  151. self.emitter = emitter
  152. self.names = emitter.names
  153. self.declarations = declarations
  154. self.source_path = source_path
  155. self.module_name = module_name
  156. self.literals = emitter.context.literals
  157. self.rare = False
  158. # Next basic block to be processed after the current one (if any), set by caller
  159. self.next_block: BasicBlock | None = None
  160. # Ops in the basic block currently being processed, set by caller
  161. self.ops: list[Op] = []
  162. # Current index within ops; visit methods can increment this to skip/merge ops
  163. self.op_index = 0
  164. def temp_name(self) -> str:
  165. return self.emitter.temp_name()
  166. def visit_goto(self, op: Goto) -> None:
  167. if op.label is not self.next_block:
  168. self.emit_line("goto %s;" % self.label(op.label))
  169. def visit_branch(self, op: Branch) -> None:
  170. true, false = op.true, op.false
  171. negated = op.negated
  172. negated_rare = False
  173. if true is self.next_block and op.traceback_entry is None:
  174. # Switch true/false since it avoids an else block.
  175. true, false = false, true
  176. negated = not negated
  177. negated_rare = True
  178. neg = "!" if negated else ""
  179. cond = ""
  180. if op.op == Branch.BOOL:
  181. expr_result = self.reg(op.value)
  182. cond = f"{neg}{expr_result}"
  183. elif op.op == Branch.IS_ERROR:
  184. typ = op.value.type
  185. compare = "!=" if negated else "=="
  186. if isinstance(typ, RTuple):
  187. # TODO: What about empty tuple?
  188. cond = self.emitter.tuple_undefined_check_cond(
  189. typ, self.reg(op.value), self.c_error_value, compare
  190. )
  191. else:
  192. cond = f"{self.reg(op.value)} {compare} {self.c_error_value(typ)}"
  193. else:
  194. assert False, "Invalid branch"
  195. # For error checks, tell the compiler the branch is unlikely
  196. if op.traceback_entry is not None or op.rare:
  197. if not negated_rare:
  198. cond = f"unlikely({cond})"
  199. else:
  200. cond = f"likely({cond})"
  201. if false is self.next_block:
  202. if op.traceback_entry is None:
  203. if true is not self.next_block:
  204. self.emit_line(f"if ({cond}) goto {self.label(true)};")
  205. else:
  206. self.emit_line(f"if ({cond}) {{")
  207. self.emit_traceback(op)
  208. self.emit_lines("goto %s;" % self.label(true), "}")
  209. else:
  210. self.emit_line(f"if ({cond}) {{")
  211. self.emit_traceback(op)
  212. if true is not self.next_block:
  213. self.emit_line("goto %s;" % self.label(true))
  214. self.emit_lines("} else", " goto %s;" % self.label(false))
  215. def visit_return(self, op: Return) -> None:
  216. value_str = self.reg(op.value)
  217. self.emit_line("return %s;" % value_str)
  218. def visit_tuple_set(self, op: TupleSet) -> None:
  219. dest = self.reg(op)
  220. tuple_type = op.tuple_type
  221. self.emitter.declare_tuple_struct(tuple_type)
  222. if len(op.items) == 0: # empty tuple
  223. self.emit_line(f"{dest}.empty_struct_error_flag = 0;")
  224. else:
  225. for i, item in enumerate(op.items):
  226. self.emit_line(f"{dest}.f{i} = {self.reg(item)};")
  227. self.emit_inc_ref(dest, tuple_type)
  228. def visit_assign(self, op: Assign) -> None:
  229. dest = self.reg(op.dest)
  230. src = self.reg(op.src)
  231. # clang whines about self assignment (which we might generate
  232. # for some casts), so don't emit it.
  233. if dest != src:
  234. # We sometimes assign from an integer prepresentation of a pointer
  235. # to a real pointer, and C compilers insist on a cast.
  236. if op.src.type.is_unboxed and not op.dest.type.is_unboxed:
  237. src = f"(void *){src}"
  238. self.emit_line(f"{dest} = {src};")
  239. def visit_assign_multi(self, op: AssignMulti) -> None:
  240. typ = op.dest.type
  241. assert isinstance(typ, RArray)
  242. dest = self.reg(op.dest)
  243. # RArray values can only be assigned to once, so we can always
  244. # declare them on initialization.
  245. self.emit_line(
  246. "%s%s[%d] = %s;"
  247. % (
  248. self.emitter.ctype_spaced(typ.item_type),
  249. dest,
  250. len(op.src),
  251. c_array_initializer([self.reg(s) for s in op.src], indented=True),
  252. )
  253. )
  254. def visit_load_error_value(self, op: LoadErrorValue) -> None:
  255. if isinstance(op.type, RTuple):
  256. values = [self.c_undefined_value(item) for item in op.type.types]
  257. tmp = self.temp_name()
  258. self.emit_line("{} {} = {{ {} }};".format(self.ctype(op.type), tmp, ", ".join(values)))
  259. self.emit_line(f"{self.reg(op)} = {tmp};")
  260. else:
  261. self.emit_line(f"{self.reg(op)} = {self.c_error_value(op.type)};")
  262. def visit_load_literal(self, op: LoadLiteral) -> None:
  263. index = self.literals.literal_index(op.value)
  264. if not is_int_rprimitive(op.type):
  265. self.emit_line("%s = CPyStatics[%d];" % (self.reg(op), index), ann=op.value)
  266. else:
  267. self.emit_line(
  268. "%s = (CPyTagged)CPyStatics[%d] | 1;" % (self.reg(op), index), ann=op.value
  269. )
  270. def get_attr_expr(self, obj: str, op: GetAttr | SetAttr, decl_cl: ClassIR) -> str:
  271. """Generate attribute accessor for normal (non-property) access.
  272. This either has a form like obj->attr_name for attributes defined in non-trait
  273. classes, and *(obj + attr_offset) for attributes defined by traits. We also
  274. insert all necessary C casts here.
  275. """
  276. cast = f"({op.class_type.struct_name(self.emitter.names)} *)"
  277. if decl_cl.is_trait and op.class_type.class_ir.is_trait:
  278. # For pure trait access find the offset first, offsets
  279. # are ordered by attribute position in the cl.attributes dict.
  280. # TODO: pre-calculate the mapping to make this faster.
  281. trait_attr_index = list(decl_cl.attributes).index(op.attr)
  282. # TODO: reuse these names somehow?
  283. offset = self.emitter.temp_name()
  284. self.declarations.emit_line(f"size_t {offset};")
  285. self.emitter.emit_line(
  286. "{} = {};".format(
  287. offset,
  288. "CPy_FindAttrOffset({}, {}, {})".format(
  289. self.emitter.type_struct_name(decl_cl),
  290. f"({cast}{obj})->vtable",
  291. trait_attr_index,
  292. ),
  293. )
  294. )
  295. attr_cast = f"({self.ctype(op.class_type.attr_type(op.attr))} *)"
  296. return f"*{attr_cast}((char *){obj} + {offset})"
  297. else:
  298. # Cast to something non-trait. Note: for this to work, all struct
  299. # members for non-trait classes must obey monotonic linear growth.
  300. if op.class_type.class_ir.is_trait:
  301. assert not decl_cl.is_trait
  302. cast = f"({decl_cl.struct_name(self.emitter.names)} *)"
  303. return f"({cast}{obj})->{self.emitter.attr(op.attr)}"
  304. def visit_get_attr(self, op: GetAttr) -> None:
  305. dest = self.reg(op)
  306. obj = self.reg(op.obj)
  307. rtype = op.class_type
  308. cl = rtype.class_ir
  309. attr_rtype, decl_cl = cl.attr_details(op.attr)
  310. prefer_method = cl.is_trait and attr_rtype.error_overlap
  311. if cl.get_method(op.attr, prefer_method=prefer_method):
  312. # Properties are essentially methods, so use vtable access for them.
  313. version = "_TRAIT" if cl.is_trait else ""
  314. self.emit_line(
  315. "%s = CPY_GET_ATTR%s(%s, %s, %d, %s, %s); /* %s */"
  316. % (
  317. dest,
  318. version,
  319. obj,
  320. self.emitter.type_struct_name(rtype.class_ir),
  321. rtype.getter_index(op.attr),
  322. rtype.struct_name(self.names),
  323. self.ctype(rtype.attr_type(op.attr)),
  324. op.attr,
  325. )
  326. )
  327. else:
  328. # Otherwise, use direct or offset struct access.
  329. attr_expr = self.get_attr_expr(obj, op, decl_cl)
  330. self.emitter.emit_line(f"{dest} = {attr_expr};")
  331. always_defined = cl.is_always_defined(op.attr)
  332. merged_branch = None
  333. if not always_defined:
  334. self.emitter.emit_undefined_attr_check(
  335. attr_rtype, dest, "==", obj, op.attr, cl, unlikely=True
  336. )
  337. branch = self.next_branch()
  338. if branch is not None:
  339. if (
  340. branch.value is op
  341. and branch.op == Branch.IS_ERROR
  342. and branch.traceback_entry is not None
  343. and not branch.negated
  344. ):
  345. # Generate code for the following branch here to avoid
  346. # redundant branches in the generated code.
  347. self.emit_attribute_error(branch, cl.name, op.attr)
  348. self.emit_line("goto %s;" % self.label(branch.true))
  349. merged_branch = branch
  350. self.emitter.emit_line("}")
  351. if not merged_branch:
  352. exc_class = "PyExc_AttributeError"
  353. self.emitter.emit_line(
  354. 'PyErr_SetString({}, "attribute {} of {} undefined");'.format(
  355. exc_class, repr(op.attr), repr(cl.name)
  356. )
  357. )
  358. if attr_rtype.is_refcounted and not op.is_borrowed:
  359. if not merged_branch and not always_defined:
  360. self.emitter.emit_line("} else {")
  361. self.emitter.emit_inc_ref(dest, attr_rtype)
  362. if merged_branch:
  363. if merged_branch.false is not self.next_block:
  364. self.emit_line("goto %s;" % self.label(merged_branch.false))
  365. self.op_index += 1
  366. elif not always_defined:
  367. self.emitter.emit_line("}")
  368. def next_branch(self) -> Branch | None:
  369. if self.op_index + 1 < len(self.ops):
  370. next_op = self.ops[self.op_index + 1]
  371. if isinstance(next_op, Branch):
  372. return next_op
  373. return None
  374. def visit_set_attr(self, op: SetAttr) -> None:
  375. if op.error_kind == ERR_FALSE:
  376. dest = self.reg(op)
  377. obj = self.reg(op.obj)
  378. src = self.reg(op.src)
  379. rtype = op.class_type
  380. cl = rtype.class_ir
  381. attr_rtype, decl_cl = cl.attr_details(op.attr)
  382. if cl.get_method(op.attr):
  383. # Again, use vtable access for properties...
  384. assert not op.is_init and op.error_kind == ERR_FALSE, "%s %d %d %s" % (
  385. op.attr,
  386. op.is_init,
  387. op.error_kind,
  388. rtype,
  389. )
  390. version = "_TRAIT" if cl.is_trait else ""
  391. self.emit_line(
  392. "%s = CPY_SET_ATTR%s(%s, %s, %d, %s, %s, %s); /* %s */"
  393. % (
  394. dest,
  395. version,
  396. obj,
  397. self.emitter.type_struct_name(rtype.class_ir),
  398. rtype.setter_index(op.attr),
  399. src,
  400. rtype.struct_name(self.names),
  401. self.ctype(rtype.attr_type(op.attr)),
  402. op.attr,
  403. )
  404. )
  405. else:
  406. # ...and struct access for normal attributes.
  407. attr_expr = self.get_attr_expr(obj, op, decl_cl)
  408. if not op.is_init and attr_rtype.is_refcounted:
  409. # This is not an initialization (where we know that the attribute was
  410. # previously undefined), so decref the old value.
  411. always_defined = cl.is_always_defined(op.attr)
  412. if not always_defined:
  413. self.emitter.emit_undefined_attr_check(
  414. attr_rtype, attr_expr, "!=", obj, op.attr, cl
  415. )
  416. self.emitter.emit_dec_ref(attr_expr, attr_rtype)
  417. if not always_defined:
  418. self.emitter.emit_line("}")
  419. elif attr_rtype.error_overlap and not cl.is_always_defined(op.attr):
  420. # If there is overlap with the error value, update bitmap to mark
  421. # attribute as defined.
  422. self.emitter.emit_attr_bitmap_set(src, obj, attr_rtype, cl, op.attr)
  423. # This steals the reference to src, so we don't need to increment the arg
  424. self.emitter.emit_line(f"{attr_expr} = {src};")
  425. if op.error_kind == ERR_FALSE:
  426. self.emitter.emit_line(f"{dest} = 1;")
  427. PREFIX_MAP: Final = {
  428. NAMESPACE_STATIC: STATIC_PREFIX,
  429. NAMESPACE_TYPE: TYPE_PREFIX,
  430. NAMESPACE_MODULE: MODULE_PREFIX,
  431. }
  432. def visit_load_static(self, op: LoadStatic) -> None:
  433. dest = self.reg(op)
  434. prefix = self.PREFIX_MAP[op.namespace]
  435. name = self.emitter.static_name(op.identifier, op.module_name, prefix)
  436. if op.namespace == NAMESPACE_TYPE:
  437. name = "(PyObject *)%s" % name
  438. self.emit_line(f"{dest} = {name};", ann=op.ann)
  439. def visit_init_static(self, op: InitStatic) -> None:
  440. value = self.reg(op.value)
  441. prefix = self.PREFIX_MAP[op.namespace]
  442. name = self.emitter.static_name(op.identifier, op.module_name, prefix)
  443. if op.namespace == NAMESPACE_TYPE:
  444. value = "(PyTypeObject *)%s" % value
  445. self.emit_line(f"{name} = {value};")
  446. self.emit_inc_ref(name, op.value.type)
  447. def visit_tuple_get(self, op: TupleGet) -> None:
  448. dest = self.reg(op)
  449. src = self.reg(op.src)
  450. self.emit_line(f"{dest} = {src}.f{op.index};")
  451. self.emit_inc_ref(dest, op.type)
  452. def get_dest_assign(self, dest: Value) -> str:
  453. if not dest.is_void:
  454. return self.reg(dest) + " = "
  455. else:
  456. return ""
  457. def visit_call(self, op: Call) -> None:
  458. """Call native function."""
  459. dest = self.get_dest_assign(op)
  460. args = ", ".join(self.reg(arg) for arg in op.args)
  461. lib = self.emitter.get_group_prefix(op.fn)
  462. cname = op.fn.cname(self.names)
  463. self.emit_line(f"{dest}{lib}{NATIVE_PREFIX}{cname}({args});")
  464. def visit_method_call(self, op: MethodCall) -> None:
  465. """Call native method."""
  466. dest = self.get_dest_assign(op)
  467. obj = self.reg(op.obj)
  468. rtype = op.receiver_type
  469. class_ir = rtype.class_ir
  470. name = op.method
  471. method = rtype.class_ir.get_method(name)
  472. assert method is not None
  473. # Can we call the method directly, bypassing vtable?
  474. is_direct = class_ir.is_method_final(name)
  475. # The first argument gets omitted for static methods and
  476. # turned into the class for class methods
  477. obj_args = (
  478. []
  479. if method.decl.kind == FUNC_STATICMETHOD
  480. else [f"(PyObject *)Py_TYPE({obj})"]
  481. if method.decl.kind == FUNC_CLASSMETHOD
  482. else [obj]
  483. )
  484. args = ", ".join(obj_args + [self.reg(arg) for arg in op.args])
  485. mtype = native_function_type(method, self.emitter)
  486. version = "_TRAIT" if rtype.class_ir.is_trait else ""
  487. if is_direct:
  488. # Directly call method, without going through the vtable.
  489. lib = self.emitter.get_group_prefix(method.decl)
  490. self.emit_line(f"{dest}{lib}{NATIVE_PREFIX}{method.cname(self.names)}({args});")
  491. else:
  492. # Call using vtable.
  493. method_idx = rtype.method_index(name)
  494. self.emit_line(
  495. "{}CPY_GET_METHOD{}({}, {}, {}, {}, {})({}); /* {} */".format(
  496. dest,
  497. version,
  498. obj,
  499. self.emitter.type_struct_name(rtype.class_ir),
  500. method_idx,
  501. rtype.struct_name(self.names),
  502. mtype,
  503. args,
  504. op.method,
  505. )
  506. )
  507. def visit_inc_ref(self, op: IncRef) -> None:
  508. src = self.reg(op.src)
  509. self.emit_inc_ref(src, op.src.type)
  510. def visit_dec_ref(self, op: DecRef) -> None:
  511. src = self.reg(op.src)
  512. self.emit_dec_ref(src, op.src.type, is_xdec=op.is_xdec)
  513. def visit_box(self, op: Box) -> None:
  514. self.emitter.emit_box(self.reg(op.src), self.reg(op), op.src.type, can_borrow=True)
  515. def visit_cast(self, op: Cast) -> None:
  516. branch = self.next_branch()
  517. handler = None
  518. if branch is not None:
  519. if (
  520. branch.value is op
  521. and branch.op == Branch.IS_ERROR
  522. and branch.traceback_entry is not None
  523. and not branch.negated
  524. and branch.false is self.next_block
  525. ):
  526. # Generate code also for the following branch here to avoid
  527. # redundant branches in the generated code.
  528. handler = TracebackAndGotoHandler(
  529. self.label(branch.true),
  530. self.source_path,
  531. self.module_name,
  532. branch.traceback_entry,
  533. )
  534. self.op_index += 1
  535. self.emitter.emit_cast(
  536. self.reg(op.src), self.reg(op), op.type, src_type=op.src.type, error=handler
  537. )
  538. def visit_unbox(self, op: Unbox) -> None:
  539. self.emitter.emit_unbox(self.reg(op.src), self.reg(op), op.type)
  540. def visit_unreachable(self, op: Unreachable) -> None:
  541. self.emitter.emit_line("CPy_Unreachable();")
  542. def visit_raise_standard_error(self, op: RaiseStandardError) -> None:
  543. # TODO: Better escaping of backspaces and such
  544. if op.value is not None:
  545. if isinstance(op.value, str):
  546. message = op.value.replace('"', '\\"')
  547. self.emitter.emit_line(f'PyErr_SetString(PyExc_{op.class_name}, "{message}");')
  548. elif isinstance(op.value, Value):
  549. self.emitter.emit_line(
  550. "PyErr_SetObject(PyExc_{}, {});".format(
  551. op.class_name, self.emitter.reg(op.value)
  552. )
  553. )
  554. else:
  555. assert False, "op value type must be either str or Value"
  556. else:
  557. self.emitter.emit_line(f"PyErr_SetNone(PyExc_{op.class_name});")
  558. self.emitter.emit_line(f"{self.reg(op)} = 0;")
  559. def visit_call_c(self, op: CallC) -> None:
  560. if op.is_void:
  561. dest = ""
  562. else:
  563. dest = self.get_dest_assign(op)
  564. args = ", ".join(self.reg(arg) for arg in op.args)
  565. self.emitter.emit_line(f"{dest}{op.function_name}({args});")
  566. def visit_truncate(self, op: Truncate) -> None:
  567. dest = self.reg(op)
  568. value = self.reg(op.src)
  569. # for C backend the generated code are straight assignments
  570. self.emit_line(f"{dest} = {value};")
  571. def visit_extend(self, op: Extend) -> None:
  572. dest = self.reg(op)
  573. value = self.reg(op.src)
  574. if op.signed:
  575. src_cast = self.emit_signed_int_cast(op.src.type)
  576. else:
  577. src_cast = self.emit_unsigned_int_cast(op.src.type)
  578. self.emit_line(f"{dest} = {src_cast}{value};")
  579. def visit_load_global(self, op: LoadGlobal) -> None:
  580. dest = self.reg(op)
  581. self.emit_line(f"{dest} = {op.identifier};", ann=op.ann)
  582. def visit_int_op(self, op: IntOp) -> None:
  583. dest = self.reg(op)
  584. lhs = self.reg(op.lhs)
  585. rhs = self.reg(op.rhs)
  586. if op.op == IntOp.RIGHT_SHIFT:
  587. # Signed right shift
  588. lhs = self.emit_signed_int_cast(op.lhs.type) + lhs
  589. rhs = self.emit_signed_int_cast(op.rhs.type) + rhs
  590. self.emit_line(f"{dest} = {lhs} {op.op_str[op.op]} {rhs};")
  591. def visit_comparison_op(self, op: ComparisonOp) -> None:
  592. dest = self.reg(op)
  593. lhs = self.reg(op.lhs)
  594. rhs = self.reg(op.rhs)
  595. lhs_cast = ""
  596. rhs_cast = ""
  597. if op.op in (ComparisonOp.SLT, ComparisonOp.SGT, ComparisonOp.SLE, ComparisonOp.SGE):
  598. # Always signed comparison op
  599. lhs_cast = self.emit_signed_int_cast(op.lhs.type)
  600. rhs_cast = self.emit_signed_int_cast(op.rhs.type)
  601. elif op.op in (ComparisonOp.ULT, ComparisonOp.UGT, ComparisonOp.ULE, ComparisonOp.UGE):
  602. # Always unsigned comparison op
  603. lhs_cast = self.emit_unsigned_int_cast(op.lhs.type)
  604. rhs_cast = self.emit_unsigned_int_cast(op.rhs.type)
  605. elif isinstance(op.lhs, Integer) and op.lhs.value < 0:
  606. # Force signed ==/!= with negative operand
  607. rhs_cast = self.emit_signed_int_cast(op.rhs.type)
  608. elif isinstance(op.rhs, Integer) and op.rhs.value < 0:
  609. # Force signed ==/!= with negative operand
  610. lhs_cast = self.emit_signed_int_cast(op.lhs.type)
  611. self.emit_line(f"{dest} = {lhs_cast}{lhs} {op.op_str[op.op]} {rhs_cast}{rhs};")
  612. def visit_float_op(self, op: FloatOp) -> None:
  613. dest = self.reg(op)
  614. lhs = self.reg(op.lhs)
  615. rhs = self.reg(op.rhs)
  616. if op.op != FloatOp.MOD:
  617. self.emit_line("%s = %s %s %s;" % (dest, lhs, op.op_str[op.op], rhs))
  618. else:
  619. # TODO: This may set errno as a side effect, that is a little sketchy.
  620. self.emit_line("%s = fmod(%s, %s);" % (dest, lhs, rhs))
  621. def visit_float_neg(self, op: FloatNeg) -> None:
  622. dest = self.reg(op)
  623. src = self.reg(op.src)
  624. self.emit_line(f"{dest} = -{src};")
  625. def visit_float_comparison_op(self, op: FloatComparisonOp) -> None:
  626. dest = self.reg(op)
  627. lhs = self.reg(op.lhs)
  628. rhs = self.reg(op.rhs)
  629. self.emit_line("%s = %s %s %s;" % (dest, lhs, op.op_str[op.op], rhs))
  630. def visit_load_mem(self, op: LoadMem) -> None:
  631. dest = self.reg(op)
  632. src = self.reg(op.src)
  633. # TODO: we shouldn't dereference to type that are pointer type so far
  634. type = self.ctype(op.type)
  635. self.emit_line(f"{dest} = *({type} *){src};")
  636. def visit_set_mem(self, op: SetMem) -> None:
  637. dest = self.reg(op.dest)
  638. src = self.reg(op.src)
  639. dest_type = self.ctype(op.dest_type)
  640. # clang whines about self assignment (which we might generate
  641. # for some casts), so don't emit it.
  642. if dest != src:
  643. self.emit_line(f"*({dest_type} *){dest} = {src};")
  644. def visit_get_element_ptr(self, op: GetElementPtr) -> None:
  645. dest = self.reg(op)
  646. src = self.reg(op.src)
  647. # TODO: support tuple type
  648. assert isinstance(op.src_type, RStruct)
  649. assert op.field in op.src_type.names, "Invalid field name."
  650. self.emit_line(
  651. "{} = ({})&(({} *){})->{};".format(
  652. dest, op.type._ctype, op.src_type.name, src, op.field
  653. )
  654. )
  655. def visit_load_address(self, op: LoadAddress) -> None:
  656. typ = op.type
  657. dest = self.reg(op)
  658. if isinstance(op.src, Register):
  659. src = self.reg(op.src)
  660. elif isinstance(op.src, LoadStatic):
  661. prefix = self.PREFIX_MAP[op.src.namespace]
  662. src = self.emitter.static_name(op.src.identifier, op.src.module_name, prefix)
  663. else:
  664. src = op.src
  665. self.emit_line(f"{dest} = ({typ._ctype})&{src};")
  666. def visit_keep_alive(self, op: KeepAlive) -> None:
  667. # This is a no-op.
  668. pass
  669. # Helpers
  670. def label(self, label: BasicBlock) -> str:
  671. return self.emitter.label(label)
  672. def reg(self, reg: Value) -> str:
  673. if isinstance(reg, Integer):
  674. val = reg.value
  675. if val == 0 and is_pointer_rprimitive(reg.type):
  676. return "NULL"
  677. s = str(val)
  678. if val >= (1 << 31):
  679. # Avoid overflowing signed 32-bit int
  680. if val >= (1 << 63):
  681. s += "ULL"
  682. else:
  683. s += "LL"
  684. elif val == -(1 << 63):
  685. # Avoid overflowing C integer literal
  686. s = "(-9223372036854775807LL - 1)"
  687. elif val <= -(1 << 31):
  688. s += "LL"
  689. return s
  690. elif isinstance(reg, Float):
  691. r = repr(reg.value)
  692. if r == "inf":
  693. return "INFINITY"
  694. elif r == "-inf":
  695. return "-INFINITY"
  696. elif r == "nan":
  697. return "NAN"
  698. return r
  699. else:
  700. return self.emitter.reg(reg)
  701. def ctype(self, rtype: RType) -> str:
  702. return self.emitter.ctype(rtype)
  703. def c_error_value(self, rtype: RType) -> str:
  704. return self.emitter.c_error_value(rtype)
  705. def c_undefined_value(self, rtype: RType) -> str:
  706. return self.emitter.c_undefined_value(rtype)
  707. def emit_line(self, line: str, *, ann: object = None) -> None:
  708. self.emitter.emit_line(line, ann=ann)
  709. def emit_lines(self, *lines: str) -> None:
  710. self.emitter.emit_lines(*lines)
  711. def emit_inc_ref(self, dest: str, rtype: RType) -> None:
  712. self.emitter.emit_inc_ref(dest, rtype, rare=self.rare)
  713. def emit_dec_ref(self, dest: str, rtype: RType, is_xdec: bool) -> None:
  714. self.emitter.emit_dec_ref(dest, rtype, is_xdec=is_xdec, rare=self.rare)
  715. def emit_declaration(self, line: str) -> None:
  716. self.declarations.emit_line(line)
  717. def emit_traceback(self, op: Branch) -> None:
  718. if op.traceback_entry is not None:
  719. self.emitter.emit_traceback(self.source_path, self.module_name, op.traceback_entry)
  720. def emit_attribute_error(self, op: Branch, class_name: str, attr: str) -> None:
  721. assert op.traceback_entry is not None
  722. globals_static = self.emitter.static_name("globals", self.module_name)
  723. self.emit_line(
  724. 'CPy_AttributeError("%s", "%s", "%s", "%s", %d, %s);'
  725. % (
  726. self.source_path.replace("\\", "\\\\"),
  727. op.traceback_entry[0],
  728. class_name,
  729. attr,
  730. op.traceback_entry[1],
  731. globals_static,
  732. )
  733. )
  734. if DEBUG_ERRORS:
  735. self.emit_line('assert(PyErr_Occurred() != NULL && "failure w/o err!");')
  736. def emit_signed_int_cast(self, type: RType) -> str:
  737. if is_tagged(type):
  738. return "(Py_ssize_t)"
  739. else:
  740. return ""
  741. def emit_unsigned_int_cast(self, type: RType) -> str:
  742. if is_int32_rprimitive(type):
  743. return "(uint32_t)"
  744. elif is_int64_rprimitive(type):
  745. return "(uint64_t)"
  746. else:
  747. return ""