def get_size(ctype, num, il_code): """Return ILValue representing total size of `num` objects of given ctype. ctype - CType of object to count num - Integral ILValue representing number of these objects """ long_num = set_type(num, ctypes.longint, il_code) total = ILValue(ctypes.longint) size = ILValue(ctypes.longint) il_code.register_literal_var(size, str(ctype.size)) il_code.add(math_cmds.Mult(total, long_num, size)) return total
def _fix_chunk_count(self, il_code): """Convert chunk and count so that chunk is in {1, 2, 4, 8}. The Rel commands requre that chunk be in {1, 2, 4, 8}. If the given chunk value is not in this set, we multiply count and divide chunk by an appropriate value so that chunk is in {1, 2, 4, 8}, and then return the new value of chunk and the new value of count. In addition, this command moves `count` to a 64-bit value. """ # Cache the value of fixed_chunk and fixed_count so it is not # recomputed unnecessarily if self.fixed_chunk or self.fixed_count: return if not self.count: self.fixed_chunk, self.fixed_count = self.chunk, self.count return # TODO: Technically, if count is an unsigned long and `chunk` is in # `sizes`, we don't need to emit a SET command. resized_count = set_type(self.count, ctypes.longint, il_code) sizes = [8, 4, 2, 1] if self.chunk in sizes: self.fixed_chunk, self.fixed_count = self.chunk, resized_count return # Select the biggest legal size that divides given chunk size for new_chunk in sizes: if self.chunk % new_chunk == 0: break self.fixed_chunk = new_chunk scale = ILValue(ctypes.longint) scale_factor = str(int(self.chunk / new_chunk)) il_code.register_literal_var(scale, scale_factor) self.fixed_count = ILValue(ctypes.longint) il_code.add(math_cmds.Mult(self.fixed_count, resized_count, scale))