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