1#!/usr/bin/env python3 2# 3# Copyright (c) 2024 Intel Corporation 4# 5# SPDX-License-Identifier: Apache-2.0 6 7""" 8Contains a class to describe data types used for 9dictionary logging. 10""" 11 12import struct 13 14 15class DataTypes: 16 """Class regarding data types, their alignments and sizes""" 17 INT = 0 18 UINT = 1 19 LONG = 2 20 ULONG = 3 21 LONG_LONG = 4 22 ULONG_LONG = 5 23 PTR = 6 24 DOUBLE = 7 25 LONG_DOUBLE = 8 26 NUM_TYPES = 9 27 28 def __init__(self, database): 29 self.database = database 30 self.data_types = {} 31 32 if database.is_tgt_64bit(): 33 self.add_data_type(self.LONG, "q") 34 self.add_data_type(self.ULONG, "Q") 35 self.add_data_type(self.LONG_LONG, "q") 36 self.add_data_type(self.ULONG_LONG, "Q") 37 self.add_data_type(self.PTR, "Q") 38 else: 39 self.add_data_type(self.LONG, "i") 40 self.add_data_type(self.ULONG, "I") 41 self.add_data_type(self.LONG_LONG, "q") 42 self.add_data_type(self.ULONG_LONG, "Q") 43 self.add_data_type(self.PTR, "I") 44 45 self.add_data_type(self.INT, "i") 46 self.add_data_type(self.UINT, "I") 47 self.add_data_type(self.DOUBLE, "d") 48 self.add_data_type(self.LONG_DOUBLE, "d") 49 50 51 @staticmethod 52 def get_stack_min_align(arch, is_tgt_64bit): 53 ''' 54 Correspond to the VA_STACK_ALIGN and VA_STACK_MIN_ALIGN 55 in cbprintf_internal.h. Note that there might be some 56 variations that is obtained via actually running through 57 the log parser. 58 59 Return a tuple where the first element is stack alignment 60 value. The second element is true if alignment needs to 61 be further refined according to data type, false if not. 62 ''' 63 if arch == "arc": 64 if is_tgt_64bit: 65 need_further_align = True 66 stack_min_align = 8 67 else: 68 need_further_align = False 69 stack_min_align = 1 70 71 elif arch == "arm64": 72 need_further_align = True 73 stack_min_align = 8 74 75 elif arch == "sparc": 76 need_further_align = False 77 stack_min_align = 1 78 79 elif arch == "x86": 80 if is_tgt_64bit: 81 need_further_align = True 82 stack_min_align = 8 83 else: 84 need_further_align = False 85 stack_min_align = 1 86 87 elif arch == "riscv32e": 88 need_further_align = False 89 stack_min_align = 1 90 91 elif arch == "riscv": 92 need_further_align = True 93 94 if is_tgt_64bit: 95 stack_min_align = 8 96 else: 97 stack_min_align = 1 98 99 else: 100 need_further_align = True 101 stack_min_align = 1 102 103 return (stack_min_align, need_further_align) 104 105 106 @staticmethod 107 def get_data_type_align(data_type, is_tgt_64bit): 108 ''' 109 Get the alignment for a particular data type. 110 ''' 111 if data_type == DataTypes.LONG_LONG: 112 align = 8 113 elif data_type == DataTypes.LONG: 114 if is_tgt_64bit: 115 align = 8 116 else: 117 align = 4 118 else: 119 # va_list alignment is at least a integer 120 align = 4 121 122 return align 123 124 125 def add_data_type(self, data_type, fmt): 126 """Add one data type""" 127 if self.database.is_tgt_little_endian(): 128 endianness = "<" 129 else: 130 endianness = ">" 131 132 formatter = endianness + fmt 133 134 self.data_types[data_type] = {} 135 self.data_types[data_type]['fmt'] = formatter 136 137 size = struct.calcsize(formatter) 138 139 if data_type == self.LONG_DOUBLE: 140 # Python doesn't have long double but we still 141 # need to skip correct number of bytes 142 size = 16 143 144 self.data_types[data_type]['sizeof'] = size 145 146 # Might need actual number for different architectures 147 # but these seem to work fine for now. 148 if self.database.is_tgt_64bit(): 149 align = 8 150 else: 151 align = 4 152 153 # 'align' is used to "jump" over an argument so it has 154 # to be at least size of the data type. 155 align = max(align, size) 156 self.data_types[data_type]['align'] = align 157 158 # 'stack_align' should correspond to VA_STACK_ALIGN 159 # in cbprintf_internal.h 160 stack_align, need_more_align = DataTypes.get_stack_min_align( 161 self.database.get_arch(), 162 self.database.is_tgt_64bit()) 163 164 if need_more_align: 165 stack_align = DataTypes.get_data_type_align(data_type, 166 self.database.is_tgt_64bit()) 167 168 self.data_types[data_type]['stack_align'] = stack_align 169 170 171 def get_sizeof(self, data_type): 172 """Get sizeof() of a data type""" 173 return self.data_types[data_type]['sizeof'] 174 175 176 def get_alignment(self, data_type): 177 """Get the alignment of a data type""" 178 return self.data_types[data_type]['align'] 179 180 181 def get_stack_alignment(self, data_type): 182 """Get the stack alignment of a data type""" 183 return self.data_types[data_type]['stack_align'] 184 185 186 def get_formatter(self, data_type): 187 """Get the formatter for a data type""" 188 return self.data_types[data_type]['fmt'] 189