Skip to content

unary_ops

Classes:

UnaryOpVisitorMixin

Bases: VisitorMixinBase

Methods:

visit

visit(node: UnaryOp) -> None
Source code in src/irx/builders/llvmliteir/visitors/unary_ops.py
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
@VisitorCore.visit.dispatch  # type: ignore[attr-defined,untyped-decorator]
def visit(self, node: astx.UnaryOp) -> None:
    """
    title: Visit UnaryOp nodes.
    parameters:
      node:
        type: astx.UnaryOp
    """
    if node.op_code == "++":
        self.visit_child(node.operand)
        operand_val = safe_pop(self.result_stack)
        if operand_val is None:
            raise Exception("codegen: Invalid unary operand.")
        operand_key = (
            semantic_symbol_key(node.operand, node.operand.name)
            if isinstance(node.operand, astx.Identifier)
            else ""
        )

        one = ir.Constant(operand_val.type, 1)
        if is_fp_type(operand_val.type):
            result = self._llvm.ir_builder.fadd(operand_val, one, "inctmp")
        else:
            result = self._llvm.ir_builder.add(operand_val, one, "inctmp")

        if isinstance(node.operand, astx.Identifier):
            if operand_key in self.const_vars:
                raise Exception(
                    f"Cannot mutate '{node.operand.name}':"
                    "declared as constant"
                )
            var_addr = self.named_values.get(operand_key)
            if var_addr:
                self._llvm.ir_builder.store(result, var_addr)

        self.result_stack.append(result)
        return

    if node.op_code == "--":
        self.visit_child(node.operand)
        operand_val = safe_pop(self.result_stack)
        if operand_val is None:
            raise Exception("codegen: Invalid unary operand.")
        operand_key = (
            semantic_symbol_key(node.operand, node.operand.name)
            if isinstance(node.operand, astx.Identifier)
            else ""
        )
        one = ir.Constant(operand_val.type, 1)
        if is_fp_type(operand_val.type):
            result = self._llvm.ir_builder.fsub(operand_val, one, "dectmp")
        else:
            result = self._llvm.ir_builder.sub(operand_val, one, "dectmp")

        if isinstance(node.operand, astx.Identifier):
            if operand_key in self.const_vars:
                raise Exception(
                    f"Cannot mutate '{node.operand.name}':"
                    "declared as constant"
                )
            var_addr = self.named_values.get(operand_key)
            if var_addr:
                self._llvm.ir_builder.store(result, var_addr)

        self.result_stack.append(result)
        return

    if node.op_code == "!":
        self.visit_child(node.operand)
        val = safe_pop(self.result_stack)
        if val is None:
            raise Exception("codegen: Invalid unary operand.")

        zero = ir.Constant(val.type, 0)
        is_zero = self._llvm.ir_builder.icmp_signed(
            "==", val, zero, "iszero"
        )

        if isinstance(val.type, ir.IntType) and val.type.width == 1:
            result = is_zero
        else:
            result = self._llvm.ir_builder.zext(
                is_zero, val.type, "nottmp"
            )

        if isinstance(node.operand, astx.Identifier):
            operand_key = semantic_symbol_key(
                node.operand, node.operand.name
            )
            if operand_key in self.const_vars:
                raise Exception(
                    f"Cannot mutate '{node.operand.name}':"
                    "declared as constant"
                )
            addr = self.named_values.get(operand_key)
            if addr:
                self._llvm.ir_builder.store(result, addr)

        self.result_stack.append(result)
        return

    raise Exception(f"Unary operator {node.op_code} not implemented yet.")