|
4 | 4 | import abc |
5 | 5 | import os |
6 | 6 | from contextlib import contextmanager |
| 7 | +from enum import IntEnum |
7 | 8 |
|
8 | 9 | from llvmlite import ir |
9 | 10 | from numba.cuda import types |
10 | 11 | from numba.cuda.core import config |
11 | 12 | from numba.cuda import cgutils |
| 13 | +from numba.cuda.cudadrv import nvvm |
12 | 14 | from numba.cuda.datamodel.models import ComplexModel, UnionModel, UniTupleModel |
13 | 15 | from numba.cuda.types.ext_types import GridGroup |
14 | 16 |
|
15 | 17 |
|
| 18 | +class DwarfAddressClass(IntEnum): |
| 19 | + GENERIC = 0x00 |
| 20 | + GLOBAL = 0x01 |
| 21 | + REGISTER = 0x02 |
| 22 | + CONSTANT = 0x05 |
| 23 | + LOCAL = 0x06 |
| 24 | + PARAMETER = 0x07 |
| 25 | + SHARED = 0x08 |
| 26 | + |
| 27 | + |
16 | 28 | @contextmanager |
17 | 29 | def suspend_emission(builder): |
18 | 30 | """Suspends the emission of debug_metadata for the duration of the context |
@@ -121,6 +133,18 @@ def initialize(self): |
121 | 133 | # constructing subprograms |
122 | 134 | self.dicompileunit = self._di_compile_unit() |
123 | 135 |
|
| 136 | + def get_dwarf_address_class(self, addrspace): |
| 137 | + # Map NVVM address space to DWARF address class. |
| 138 | + |
| 139 | + addrspace_to_addrclass_dict = { |
| 140 | + nvvm.ADDRSPACE_GENERIC: None, |
| 141 | + nvvm.ADDRSPACE_GLOBAL: DwarfAddressClass.GLOBAL, |
| 142 | + nvvm.ADDRSPACE_SHARED: DwarfAddressClass.SHARED, |
| 143 | + nvvm.ADDRSPACE_CONSTANT: DwarfAddressClass.CONSTANT, |
| 144 | + nvvm.ADDRSPACE_LOCAL: DwarfAddressClass.LOCAL, |
| 145 | + } |
| 146 | + return addrspace_to_addrclass_dict.get(addrspace) |
| 147 | + |
124 | 148 | def _var_type(self, lltype, size, datamodel=None): |
125 | 149 | if self._DEBUG: |
126 | 150 | print( |
@@ -659,6 +683,67 @@ def _var_type(self, lltype, size, datamodel=None): |
659 | 683 | }, |
660 | 684 | is_distinct=True, |
661 | 685 | ) |
| 686 | + |
| 687 | + # Check if there's actually address space info to handle |
| 688 | + if ( |
| 689 | + isinstance(lltype, ir.LiteralStructType) |
| 690 | + and datamodel is not None |
| 691 | + and datamodel.inner_models() |
| 692 | + and hasattr(datamodel, "fe_type") |
| 693 | + and getattr(datamodel.fe_type, "_addrspace", None) not in (None, 0) |
| 694 | + ): |
| 695 | + # Process struct with datamodel that has _addrspace available |
| 696 | + meta = [] |
| 697 | + offset = 0 |
| 698 | + for element, field, model in zip( |
| 699 | + lltype.elements, datamodel._fields, datamodel.inner_models() |
| 700 | + ): |
| 701 | + size_field = self.cgctx.get_abi_sizeof(element) |
| 702 | + if isinstance(element, ir.PointerType) and field == "data": |
| 703 | + # Create pointer type with correct address space |
| 704 | + pointee_size = self.cgctx.get_abi_sizeof(element.pointee) |
| 705 | + pointee_model = getattr(model, "_pointee_model", None) |
| 706 | + pointee_type = self._var_type( |
| 707 | + element.pointee, pointee_size, datamodel=pointee_model |
| 708 | + ) |
| 709 | + meta_ptr = { |
| 710 | + "tag": ir.DIToken("DW_TAG_pointer_type"), |
| 711 | + "baseType": pointee_type, |
| 712 | + "size": _BYTE_SIZE * size_field, |
| 713 | + } |
| 714 | + addrspace = getattr(datamodel.fe_type, "_addrspace", None) |
| 715 | + dwarf_addrclass = self.get_dwarf_address_class(addrspace) |
| 716 | + if dwarf_addrclass is not None: |
| 717 | + meta_ptr["dwarfAddressSpace"] = dwarf_addrclass |
| 718 | + basetype = m.add_debug_info("DIDerivedType", meta_ptr) |
| 719 | + else: |
| 720 | + basetype = self._var_type( |
| 721 | + element, size_field, datamodel=model |
| 722 | + ) |
| 723 | + derived_type = m.add_debug_info( |
| 724 | + "DIDerivedType", |
| 725 | + { |
| 726 | + "tag": ir.DIToken("DW_TAG_member"), |
| 727 | + "name": field, |
| 728 | + "baseType": basetype, |
| 729 | + "size": _BYTE_SIZE * size_field, |
| 730 | + "offset": offset, |
| 731 | + }, |
| 732 | + ) |
| 733 | + meta.append(derived_type) |
| 734 | + offset += _BYTE_SIZE * size_field |
| 735 | + |
| 736 | + return m.add_debug_info( |
| 737 | + "DICompositeType", |
| 738 | + { |
| 739 | + "tag": ir.DIToken("DW_TAG_structure_type"), |
| 740 | + "name": f"{datamodel.fe_type}", |
| 741 | + "elements": m.add_metadata(meta), |
| 742 | + "size": offset, |
| 743 | + }, |
| 744 | + is_distinct=True, |
| 745 | + ) |
| 746 | + |
662 | 747 | # For other cases, use upstream Numba implementation |
663 | 748 | return super()._var_type(lltype, size, datamodel=datamodel) |
664 | 749 |
|
|
0 commit comments