def _unpack(self, generator, variable, idl_dtype, dtype): if generator.is_trivial(idl_dtype): return c.Collection([ self._guard(f'sizeof({dtype})'), c.Statement(f'{variable} = packet->read<{dtype}>()') ]) else: return c.Collection([ c.If(f'!unpack_{idl_dtype}(packet, {variable})', c.Block([c.Statement('return false')])) ])
def _alloc_array_on_high_bw_mem(self, obj, storage): if obj in storage._high_bw_mem: return super(DeviceOpenMPDataManager, self)._alloc_array_on_high_bw_mem(obj, storage) decl, alloc, free = storage._high_bw_mem[obj] alloc = c.Collection([alloc, self._Parallelizer._map_alloc(obj)]) free = c.Collection([self._Parallelizer._map_delete(obj), free]) storage._high_bw_mem[obj] = (decl, alloc, free)
def dump(self, forward, source_includes, no_forward=False): header = c.Collection([c.MultilineComment(WARNING)] + [c.Line(x) for x in forward]) ns = self.ns(header) if not no_forward and self.forward.contents: ns.append(self.forward) ns = self.ns(header) ns.append(self.header) source = c.Collection([c.MultilineComment(WARNING)] + [c.Line(x) for x in source_includes]) ns = self.ns(source) ns.append(self.source) return header, source
def eval(self, generator): variable = f'data.{self.base.name.eval()}' idl_dtype = self.base.dtype.dtype.eval() dtype = generator.get_dtype(idl_dtype) ret_block = block = c.Collection() if self.base.optional: conditional_block = c.Block() block.append(self._guard('sizeof(bool)')) block.append(c.If('packet.Data.ReadByte() == 1', conditional_block)) block = conditional_block variable = f'{variable}.Value' if idl_dtype == 'vector': spec = self.base.dtype.spec.eval() block.append(self._guard('sizeof(byte)')) block.append( c.Statement(f'var size_{spec} = packet.Data.ReadUInt8()')) block.append( c.If( f'size_{spec} > 0', c.Block([ c.Statement( f'{variable} = new List<{spec}>(size_{spec})'), c.For('byte i = 0', f'i < size_{spec}', '++i', self._unpack_vector(generator, variable)) ]))) else: block.append(self._unpack(generator, variable, idl_dtype, dtype)) return ret_block
def eval(self, generator): variable = f'data.{self.base.name.eval()}' idl_dtype = self.base.dtype.dtype.eval() dtype = generator.get_dtype(idl_dtype) ret_block = block = c.Collection() if self.base.optional: conditional_block = c.Block() block.append(self._guard('sizeof(bool)')) block.append(c.If('packet->read<bool>()', conditional_block)) block = conditional_block variable = f'(*{variable})' if idl_dtype == 'vector': spec = self.base.dtype.spec.eval() block.append(self._guard('sizeof(uint8_t)')) block.append( c.If( f'auto size_{spec} = packet->read<uint8_t>(); size_{spec} > 0', c.Block([ c.Statement(f'{variable}.reserve(size_{spec})'), c.For('uint8_t i = 0', f'i < size_{spec}', '++i', self._unpack_vector(generator, variable)) ]))) else: block.append(self._unpack(generator, variable, idl_dtype, dtype)) return ret_block
def dump(self, forward, source_includes): header = c.Collection([c.MultilineComment(WARNING)] + [c.Line('#pragma once')] + [c.Line(x) for x in forward]) ns = self.ns(header) if self.forward.contents: ns.append(self.forward) ns = self.ns(header) ns.append(self.header) source = c.Collection([c.MultilineComment(WARNING)] + [c.Line(x) for x in source_includes]) ns = self.ns(source) ns.append(self.source) return header, source
def ns(self, parent): ns = c.Collection([c.Line(f'namespace {self.namespace[0]}')]) parent.append(ns) if len(self.namespace) > 1: block = c.Block([c.Line(f'class {self.namespace[1]}')]) ns.append(block) return block return parent
def visit_Conditional(self, o): if o.condition is BooleanTrue(): return c.Collection(self._visit(o.then_body)) else: then_body = c.Block(self._visit(o.then_body)) if o.else_body: else_body = c.Block(self._visit(o.else_body)) return c.If(ccode(o.condition), then_body, else_body) else: return c.If(ccode(o.condition), then_body)
def _unpack(self, generator, variable, idl_dtype, dtype): if generator.is_trivial(idl_dtype): return c.Collection([ self._guard(f'sizeof({dtype})'), c.Statement( f'{variable} = packet.Data.Read{READ_MAP[idl_dtype]}()') ]) elif idl_dtype == 'string': # TODO(gpascualg): Not the solution i enjoy the most return c.Collection([ c.If(f'!unpack_{idl_dtype}(packet, ref {variable})', c.Block([c.Statement('return false')])) ]) else: return c.Collection([ c.Statement(f'{variable} = new {idl_dtype}()'), c.If(f'!unpack_{idl_dtype}(packet, {variable})', c.Block([c.Statement('return false')])) ])
def visit_CallableBody(self, o): body = [] prev = None for i in o.children: v = self._visit(i) if v: if prev: body.append(c.Line()) prev = v body.extend(as_tuple(v)) return c.Collection(body)
def _map_function_on_high_bw_mem(self, site, obj, storage, read_only=False): """ Place a Function in the high bandwidth memory. """ alloc = self._Parallelizer._map_to(obj) if read_only is False: free = c.Collection([self._Parallelizer._map_update(obj), self._Parallelizer._map_release(obj)]) else: free = self._Parallelizer._map_delete(obj) storage.update(obj, site, allocs=alloc, frees=free)
def _map_function_on_high_bw_mem(self, obj, storage, read_only=False): """Place a Function in the high bandwidth memory.""" if obj in storage._high_bw_mem: return alloc = self._Parallelizer._map_to(obj) if read_only is False: free = c.Collection([self._Parallelizer._map_update(obj), self._Parallelizer._map_release(obj)]) else: free = self._Parallelizer._map_delete(obj) storage._high_bw_mem[obj] = (None, alloc, free)
def eval(self, generator): block = c.Collection() raw_variable = f'data.{self.base.name.eval()}' if self.base.optional: variable = f'*{raw_variable}' block.append( c.Statement(f'*packet << static_cast<bool>({raw_variable})')) block.append( c.If(raw_variable, c.Block([self._pack(generator, variable)]))) else: block.append(self._pack(generator, raw_variable)) return block
def _pack(self, generator, variable): dtype = self.base.dtype.dtype.eval() if dtype == 'vector': spec = self.base.dtype.spec.eval() return c.Collection([ c.Statement(f'*packet << static_cast<uint8_t>(({variable}).size())'), CppRangedFor('auto& x', variable, c.Block([ c.Statement('*packet << x') if generator.is_trivial(spec) else \ c.Statement(f'pack_{spec}(packet, x)') ])) ]) else: if generator.is_trivial(dtype): return c.Statement(f'*packet << {variable}') else: return c.Statement(f'pack_{dtype}(packet, {variable})')
def _pack(self, generator, variable): dtype = self.base.dtype.dtype.eval() if dtype == 'vector': spec = self.base.dtype.spec.eval() return c.Collection([ c.Statement(f'packet.Data.WriteInt8((byte)(({variable}).Count))'), CSharpRangedFor('var x', variable, c.Block([ c.Statement(f'packet.Data.Write{WRITE_MAP[spec]}(x)') if generator.is_trivial(spec) else \ c.Statement(f'pack_{spec}(packet, x)') ])) ]) else: if generator.is_trivial(dtype): return c.Statement( f'packet.Data.Write{WRITE_MAP[dtype]}({variable})') else: return c.Statement(f'pack_{dtype}(packet, {variable})')
def eval(self, generator): block = c.Collection() raw_variable = f'data.{self.base.name.eval()}' if self.base.optional: variable = f'{raw_variable}.Value' block.append( c.Statement( f'packet.Data.WriteByte((byte)Convert.ToInt32({raw_variable}.HasValue))' )) block.append( c.If(f'{raw_variable}.HasValue', c.Block([self._pack(generator, variable)]))) else: block.append(self._pack(generator, raw_variable)) return block
def visit_CallableBody(self, o): body = [] prev = None for i in [ o.init, o.unpacks, o.allocs, o.casts, o.maps, # pre o.body, # actual body o.unmaps, o.frees ]: # post if i in o.children: v = self.visit(i) else: v = i if v: if prev: body.append(c.Line()) prev = v body.extend(as_tuple(v)) return c.Collection(body)
def visit_HaloSpot(self, o): body = flatten(self._visit(i) for i in o.children) return c.Collection(body)
def visit_List(self, o): body = flatten(self._visit(i) for i in o.children) return c.Module(o.header + (c.Collection(body), ) + o.footer)
def visit_Pragma(self, o): if len(o.pragmas) == 1: return o.pragmas[0] else: return c.Collection(o.pragmas)
def get_idl_dtype_size(idl_dtype, spec_type, variable, optional): # Here goes all the sizes logic ret = col = c.Collection([]) # Optional data is an special case if optional: col.append(c.Statement('size += sizeof(bool)')) inner = c.Block([]) col.append(c.If(f'data.{variable}.HasValue', inner)) col = inner dtype = self.get_dtype(idl_dtype) if self.is_trivial(idl_dtype): col.append(c.Statement(f'size += sizeof({dtype})')) elif idl_dtype == 'string': col.append( c.Statement( f'size += (byte)(sizeof({self.get_dtype("uint8")}) + ' + self._str_len(f'data.{variable}') + ')')) elif self.is_message(idl_dtype): col.append( c.Statement( f'size += {idl_dtype}_size(data.{variable})')) elif idl_dtype == 'vector': if self.is_trivial(spec_type): # TODO(gpascualg): No vector of optionals yet col.append( c.Statement( f'size += (byte)(sizeof({self.get_dtype("uint8")}) + data.{variable}.Count * {get_idl_dtype_size(spec_type, None, variable, None)})' )) elif self.is_message(spec_type): if self._is_trivial( spec_type, self.user_defined_messages[spec_type], include_messages=False): col.append( c.Collection([ c.If( f'data.{variable}.Count == 0', c.Block([ c.Statement( f'size += sizeof({self.get_dtype("uint8")})' ) ]), c.Block([ c.Statement( f'size += (byte)(sizeof({self.get_dtype("uint8")}) + data.{variable}.Count * {spec_type}_size(data.{variable}[0]))' ) ])) ])) else: col.append( c.Collection([ c.Statement( f'size += sizeof({self.get_dtype("uint8")})' ), c.For( 'int i = 0', f'i < data.{variable}.Count', '++i', c.Block([ c.Statement( f'size += {spec_type}_size(data.{variable}[i])' ) ])) ])) elif spec_type == 'string': raise NotImplementedError( f'Vector of strings is a WIP') else: raise NotImplementedError( f'Unsupported vector type {spec_type}') else: raise NotImplementedError(f'Unrecognized type {idl_dtype}') return ret
def generate_common(self): # Common structs (id_forward, id_struct), (data_forward, data_struct) = self._global_structs() self.structs.forward.insert(0, id_forward) self.structs.forward.insert(0, data_forward) self.structs.header.insert(0, id_struct) self.structs.header.insert(0, data_struct) # Switch jump table decl, body, _ = self._jump_table(CppMethod) self.marshal.header.append(decl) self.marshal.source.append(body) # Opcodes enum self.opcodes.header.append(self._opcode_enum()) # Language specific string methods self.__generate_string_methods() # Generate individual sizes for message_name, message in self.user_defined_messages.items(): header, body, _, all_trivial = self._sizeof_message( CppMethod, message_name, message, fname=message_name) self.marshal.forward.append(header) if all_trivial: self.marshal.header.append(body) else: self.marshal.source.append(body) # Big size switch body = c.FunctionBody( c.Template( 'typename T', c.FunctionDeclaration( c.Value('inline uint8_t', 'message_size'), [self._data_cref('T', 'message')])), c.Block([ c.Collection([ c.Line( ('' if i == 0 else 'else ') + f'if constexpr (std::is_same_v<std::decay_t<T>, {message_name}>)' ), c.Block( [c.Statement(f'return {message_name}_size(message)')]) ]) for i, message_name in enumerate(self.user_defined_messages) ])) self.marshal.header.append(body) # Big pack switch body = c.FunctionBody( c.Template( 'typename T', c.FunctionDeclaration(c.Value('inline void', 'pack_message'), [ self._data_object_ref(self._packet_type(), 'packet'), c.Value('T&&', 'message') ])), c.Block([ c.Collection([ c.Line( ('' if i == 0 else 'else ') + f'if constexpr (std::is_same_v<std::decay_t<T>, {message_name}>)' ), c.Block([ c.Statement( f'pack_{message_name}(packet, std::forward<T>(message))' ) ]) ]) for i, message_name in enumerate(self.user_defined_messages) ])) self.marshal.header.append(body)