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