Skip to content

Commit 32b54e9

Browse files
committed
compiler: Print an Array initializer at the Array's own precision
`_gen_value` printed the initializer with the printer's default dtype rather than the Array's, which stamped a `float` suffix onto the entries of a `double` Array and silently rounded them to single precision. Route it through a new `initvalue` printer hook, which also gives the targets a place to specialize an initializer whose type cannot be built from a plain literal.
1 parent 671cb1c commit 32b54e9

2 files changed

Lines changed: 21 additions & 1 deletion

File tree

‎devito/ir/cgen/printer.py‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,17 @@ def _print_FieldFromComposite(self, expr):
373373
def _print_ListInitializer(self, expr):
374374
return f"{{{', '.join(self._print(i) for i in expr.params)}}}"
375375

376+
def initvalue(self, init, dtype):
377+
"""
378+
Print the aggregate initializer `init` of an Array of type `dtype`.
379+
380+
Kept separate from `_print_ListInitializer` because a static
381+
initializer, unlike an expression, cannot rely on implicit conversions:
382+
some types (e.g. CUDA's `__half`) are only constructible from a literal
383+
via a runtime call, which is illegal in that position.
384+
"""
385+
return self._print(init)
386+
376387
def _print_IndexedPointer(self, expr):
377388
base = self._print(expr.base)
378389
return f"{base}{''.join(f'[{self._print(i)}]' for i in expr.index)}"

‎devito/ir/iet/visitors.py‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,12 +360,21 @@ def _gen_value(self, obj, mode=1, masked=()):
360360
if obj.is_Array and obj.initvalue is not None and mode == 1:
361361
init = ListInitializer(obj.initvalue)
362362
if not obj._mem_constant or init.is_numeric:
363-
value = c.Initializer(value, self.ccode(init))
363+
value = c.Initializer(value, self._gen_initvalue(obj, init))
364364
elif obj.is_LocalObject and obj.initvalue is not None and mode == 1:
365365
value = c.Initializer(value, self.ccode(obj.initvalue))
366366

367367
return value
368368

369+
def _gen_initvalue(self, obj, init):
370+
"""
371+
Convert the aggregate initializer `init` of the Array `obj` into a C
372+
string, delegating to the printer so that languages whose types cannot
373+
be built from plain literals (e.g. CUDA's `__half`) can specialize it.
374+
"""
375+
printer = get_printer(self.printer, obj.dtype)
376+
return printer.initvalue(init, obj.dtype)
377+
369378
def _gen_rettype(self, obj):
370379
try:
371380
return self._gen_value(obj, 0).typename

0 commit comments

Comments
 (0)