def nonarith(self, left, right, il_code): """ Check equality of non-arithmetic expressions """ # If either operand is a null pointer constant, cast it to the other's pointer type. if left.ctype.is_pointer() and right.null_ptr_const: right = set_type(right, left.ctype, il_code) elif right.ctype.is_pointer() and left.null_ptr_const: left = set_type(left, right.ctype, il_code) # If both operands are not pointer types, quit now if not left.ctype.is_pointer() or not right.ctype.is_pointer(): with report_err(): err = "comparison between incomparable types" raise CompilerError(err, self.op.r) # If one side is pointer to void, cast the other to same. elif left.ctype.arg.is_void(): check_cast(right, left.ctype, self.op.r) right = set_type(right, left.ctype, il_code) elif right.ctype.arg.is_void(): check_cast(left, right.ctype, self.op.r) left = set_type(left, right.ctype, il_code) # If both types are still incompatible, warn! elif not left.ctype.compatible(right.ctype): with report_err(): err = "comparison between distinct pointer types" raise CompilerError(err, self.op.r) # Now, we can do comparison out = ILValue(ctypes.integer) il_code.add(self.eq_il_cmd(out, left, right)) return out
def get_args_without_prototype(self, il_code, symbol_table, c): """Return list of argument ILValues for function this represents. This function only performs integer promotion on the arguments before passing them to the called function. """ final_args = [] for arg_given in self.args: arg = arg_given.make_il(il_code, symbol_table, c) # perform integer promotions if arg.ctype.is_arith() and arg.ctype.size < 4: arg = set_type(arg, ctypes.integer, il_code) final_args.append(arg) return final_args
def make_il(self, il_code, symbol_table, c): lvalue = self.lvalue(il_code, symbol_table, c) # Decay array if lvalue.ctype().is_array(): addr = lvalue.addr(il_code) return set_type(addr, PointerCType(lvalue.ctype().elem), il_code) # Decay function elif lvalue.ctype().is_function(): return lvalue.addr(il_code) # Nothing to decay else: return lvalue.val(il_code)
def make_il(self, il_code, symbol_table, c): """ Make IL code for returning this value """ if self.return_value and not c.return_type.is_void(): il_value = self.return_value.make_il(il_code, symbol_table, c) check_cast(il_value, c.return_type, self.return_value.r) ret = set_type(il_value, c.return_type, il_code) il_code.add(control_cmds.Return(ret)) elif self.return_value and c.return_type.is_void(): err = "function with void return type cannot return value" raise CompilerError(err, self.r) elif not self.return_value and not c.return_type.is_void(): err = "function with non-void return type must return value" raise CompilerError(err, self.r) else: il_code.add(control_cmds.Return())
def make_il(self, il_code, symbol_table, c): """ Make IL for this cast operation """ self.set_self_vars(il_code, symbol_table, c) base_type, _ = self.make_specs_ctype(self.node.specs, False) ctype, _ = self.make_ctype(self.node.decls[0], base_type) if not ctype.is_void() and not ctype.is_scalar(): err = "can only cast to scalar or void type" raise CompilerError(err, self.node.decls[0].r) il_value = self.expr.make_il(il_code, symbol_table, c) if not il_value.ctype.is_scalar(): err = "can only cast from scalar type" raise CompilerError(err, self.r) return set_type(il_value, ctype, il_code)
def make_il(self, il_code, symbol_table, c): """ Make code for this node """ expr = self.expr.make_il(il_code, symbol_table, c) if not self.check_type(expr): err = f"{self.descr} requires {self.opnd_descr} type operand" raise CompilerError(err, self.expr.r) # perform integer promotion if expr.ctype.size < 4: expr = set_type(expr, ctypes.integer, il_code) if self.cmd: out = ILValue(expr.ctype) # perform constant folding if expr.literal: val = self.arith_const(expr.literal.val, expr.ctype) val = shift_into_range(val, expr.ctype) il_code.register_literal_var(out, val) else: il_code.add(self.cmd(out, expr)) return out return expr
def get_args_with_prototype(self, func_ctype, il_code, symbol_table, c): """Return list of argument ILValues for function this represents. This function converts all passed arguments to expected types. """ arg_types = func_ctype.args if len(arg_types) != len(self.args): err = ("incorrect number of arguments for function call" f" (expected {len(arg_types)}, have {len(self.args)})") if self.args: raise CompilerError(err, self.args[-1].r) else: raise CompilerError(err, self.r) final_args = [] for arg_given, arg_type in zip(self.args, arg_types): arg = arg_given.make_il(il_code, symbol_table, c) check_cast(arg, arg_type, arg_given.r) final_args.append(set_type(arg, arg_type.make_unqual(), il_code)) return final_args