00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00035 #include "ctrump/ast/abi.h"
00036 #include "ctrump/ast/types.h"
00037 #include "ctrump/common/abort.h"
00038 #include <stdlib.h>
00039 #include <assert.h>
00040
00044 const struct ctrump_abi ctrump_spu_abi =
00045 {
00046 .sizeof_pointer = 4,
00047 .sizeof_long = 4,
00048 .sizeof_int = 4,
00049 .sizeof_enum = 4,
00050 .sizeof_short = 2,
00051 .sizeof_bool = 1,
00052 .sizeof_longlong = 8,
00053 .sizeof_float = 4,
00054 .sizeof_double = 8,
00055 .sizeof_long_double = 8,
00056 .sizeof_vector = 16,
00057
00058 .alignof_pointer = 4,
00059 .alignof_long = 4,
00060 .alignof_int = 4,
00061 .alignof_enum = 4,
00062 .alignof_short = 2,
00063 .alignof_bool = 1,
00064 .alignof_longlong = 8,
00065 .alignof_float = 4,
00066 .alignof_double = 8,
00067 .alignof_long_double = 8,
00068 .alignof_vector = 16,
00069
00070 .is_char_signed = 0,
00071 };
00072
00076 const struct ctrump_abi ctrump_ppc32_abi =
00077 {
00078 .sizeof_pointer = 4,
00079 .sizeof_long = 4,
00080 .sizeof_int = 4,
00081 .sizeof_enum = 4,
00082 .sizeof_short = 2,
00083 .sizeof_bool = 1,
00084 .sizeof_longlong = 8,
00085 .sizeof_float = 4,
00086 .sizeof_double = 8,
00087 .sizeof_long_double = 16,
00088 .sizeof_vector = 16,
00089
00090 .alignof_pointer = 4,
00091 .alignof_long = 4,
00092 .alignof_int = 4,
00093 .alignof_enum = 4,
00094 .alignof_short = 2,
00095 .alignof_bool = 1,
00096 .alignof_longlong = 8,
00097 .alignof_float = 4,
00098 .alignof_double = 8,
00099 .alignof_long_double = 16,
00100 .alignof_vector = 16,
00101
00102 .is_char_signed = 0,
00103 };
00104
00108 const struct ctrump_abi ctrump_ppc64_abi =
00109 {
00110 .sizeof_pointer = 8,
00111 .sizeof_long = 8,
00112 .sizeof_int = 4,
00113 .sizeof_enum = 4,
00114 .sizeof_short = 2,
00115 .sizeof_bool = 1,
00116 .sizeof_longlong = 8,
00117 .sizeof_float = 4,
00118 .sizeof_double = 8,
00119 .sizeof_long_double = 16,
00120 .sizeof_vector = 16,
00121
00122 .alignof_pointer = 8,
00123 .alignof_long = 8,
00124 .alignof_int = 4,
00125 .alignof_enum = 4,
00126 .alignof_short = 2,
00127 .alignof_bool = 1,
00128 .alignof_longlong = 8,
00129 .alignof_float = 4,
00130 .alignof_double = 8,
00131 .alignof_long_double = 16,
00132 .alignof_vector = 16,
00133
00134 .is_char_signed = 0,
00135 };
00136
00140 const struct ctrump_abi ctrump_x86_abi =
00141 {
00142 .sizeof_pointer = 4,
00143 .sizeof_long = 4,
00144 .sizeof_int = 4,
00145 .sizeof_enum = 4,
00146 .sizeof_short = 2,
00147 .sizeof_bool = 1,
00148 .sizeof_longlong = 8,
00149 .sizeof_float = 4,
00150 .sizeof_double = 8,
00151 .sizeof_long_double = 12,
00152 .sizeof_vector = 16,
00153
00154 .alignof_pointer = 4,
00155 .alignof_long = 4,
00156 .alignof_int = 4,
00157 .alignof_enum = 4,
00158 .alignof_short = 2,
00159 .alignof_bool = 1,
00160 .alignof_longlong = 8,
00161 .alignof_float = 4,
00162 .alignof_double = 8,
00163 .alignof_long_double = 12,
00164 .alignof_vector = 16,
00165
00166 .is_char_signed = 1,
00167 };
00168
00175 const struct ctrump_abi ctrump_x86LP64_abi =
00176 {
00177 .sizeof_pointer = 8,
00178 .sizeof_long = 8,
00179 .sizeof_int = 4,
00180 .sizeof_enum = 4,
00181 .sizeof_short = 2,
00182 .sizeof_bool = 1,
00183 .sizeof_longlong = 8,
00184 .sizeof_float = 4,
00185 .sizeof_double = 8,
00186 .sizeof_long_double = 16,
00187 .sizeof_vector = 16,
00188
00189 .alignof_pointer = 8,
00190 .alignof_long = 8,
00191 .alignof_int = 4,
00192 .alignof_enum = 4,
00193 .alignof_short = 2,
00194 .alignof_bool = 1,
00195 .alignof_longlong = 8,
00196 .alignof_float = 4,
00197 .alignof_double = 8,
00198 .alignof_long_double = 16,
00199 .alignof_vector = 16,
00200
00201 .is_char_signed = 1,
00202 };
00203
00204 #define CHECK_ERROR(e) \
00205 { \
00206 int r; \
00207 r = (e); \
00208 if (r < 0) \
00209 return r; \
00210 } \
00211
00212
00216 static int
00217 calc_union_size(size_t *size,
00218 size_t *align,
00219 const struct ctrump_abi *abi,
00220 const struct ctrump_record_type *u)
00221 {
00222 int i, n=u->nfield;
00223 size_t max_size = 1;
00224 size_t max_align = 1;
00225 if (! u->is_completed) {
00226 return -1;
00227 }
00228 for (i=0; i<n; i++) {
00229 struct ctrump_record_type_field *f = &u->fields[i];
00230 size_t field_size, field_align;
00231
00232 CHECK_ERROR(ctrump_texpr_size(&field_size, &field_align,
00233 abi, f->type));
00234
00235 if (field_size > max_size) {
00236 max_size = field_size;
00237 }
00238
00239 if (field_align > max_align) {
00240 max_align = field_align;
00241 }
00242 }
00243
00244 *size = max_size;
00245 *align = max_align;
00246
00247 return 0;
00248 }
00249
00250 static int
00251 align_ceil(int val, int align_to)
00252 {
00253 val += (align_to-1);
00254 return val - (val%align_to);
00255 }
00256
00260 static int
00261 record_field_offset(int *offset_ret,
00262 int *max_align_ret,
00263 struct ctrump_record_type_field *f,
00264 const struct ctrump_abi *abi)
00265 {
00266 size_t field_size, field_align;
00267
00268 int field_attr_align = CTRUMP_ALIGN_UNSPECIFIED;
00269 int this_field_offset;
00270
00271 int offset = *offset_ret;
00272 int max_align = *max_align_ret;
00273
00274 if (field_attr_align == CTRUMP_ALIGN_UNSPECIFIED ||
00275 field_attr_align == 0) {
00276 field_attr_align = 1;
00277 }
00278
00279 CHECK_ERROR(ctrump_texpr_size(&field_size, &field_align,
00280 abi, f->type));
00281
00282 if (field_align > max_align) {
00283 max_align = field_align;
00284 }
00285
00286 offset = align_ceil(offset, field_align);
00287 this_field_offset = offset = align_ceil(offset, field_attr_align);
00288
00289 offset += field_size;
00290
00291 *offset_ret = offset;
00292 *max_align_ret = max_align;
00293
00294 return this_field_offset;
00295 }
00296
00300 static int
00301 calc_struct_size(size_t *size,
00302 size_t *align,
00303 const struct ctrump_abi *abi,
00304 const struct ctrump_record_type *s)
00305 {
00306 int i, n=s->nfield;
00307 int offset = 0;
00308 int max_align = 1;
00309
00310 if (! s->is_completed) {
00311 return -1;
00312 }
00313
00314 for (i=0; i<n; i++) {
00315 struct ctrump_record_type_field *f = &s->fields[i];
00316 record_field_offset(&offset, &max_align, f, abi);
00317 }
00318
00319 if (s->attr.aligned != CTRUMP_ALIGN_UNSPECIFIED) {
00320 int a = s->attr.aligned;
00321 offset = align_ceil(offset, a);
00322 if (a > max_align)
00323 max_align = a;
00324 }
00325
00326 *size = offset;
00327 *align = max_align;
00328
00329 return 0;
00330 }
00331
00332 int
00333 ctrump_texpr_size(size_t *size,
00334 size_t *align,
00335 const struct ctrump_abi *abi,
00336 const struct ctrump_texpr *type)
00337 {
00338 size_t get_size, get_align;
00339 int attr_align;
00340 tailcall:
00341 switch (type->code) {
00342 case CTRUMP_TYPE_BUILTIN:
00343 switch (type->u.builtin.code) {
00344 case CTRUMP_BOOL:
00345 *size = abi->sizeof_bool;
00346 *align = abi->alignof_bool;
00347 return 0;
00348
00349 case CTRUMP_CHAR:
00350 case CTRUMP_SCHAR:
00351 case CTRUMP_UCHAR:
00352 *size = 1;
00353 *align = 1;
00354 return 0;
00355
00356 case CTRUMP_SSHORT:
00357 case CTRUMP_USHORT:
00358 *size = abi->sizeof_short;
00359 *align = abi->alignof_short;
00360 return 0;
00361
00362 case CTRUMP_SINT:
00363 case CTRUMP_UINT:
00364 *size = abi->sizeof_int;
00365 *align = abi->alignof_int;
00366 return 0;
00367
00368 case CTRUMP_SLONG:
00369 case CTRUMP_ULONG:
00370 *size = abi->sizeof_long;
00371 *align = abi->alignof_long;
00372 return 0;
00373
00374 case CTRUMP_SLONGLONG:
00375 case CTRUMP_ULONGLONG:
00376 *size = abi->sizeof_longlong;
00377 *align = abi->alignof_longlong;
00378 return 0;
00379
00380 case CTRUMP_FLOAT:
00381 *size = abi->sizeof_float;
00382 *align = abi->alignof_float;
00383 return 0;
00384
00385 case CTRUMP_DOUBLE:
00386 *size = abi->sizeof_double;
00387 *align = abi->alignof_double;
00388 return 0;
00389
00390 case CTRUMP_LONG_DOUBLE:
00391 *size = abi->sizeof_long_double;
00392 *align = abi->alignof_long_double;
00393
00394 case CTRUMP_VEC_SCHAR:
00395 case CTRUMP_VEC_UCHAR:
00396 case CTRUMP_VEC_SSHORT:
00397 case CTRUMP_VEC_USHORT:
00398 case CTRUMP_VEC_SINT:
00399 case CTRUMP_VEC_UINT:
00400 case CTRUMP_VEC_SLONG:
00401 case CTRUMP_VEC_ULONG:
00402 case CTRUMP_VEC_SLONGLONG:
00403 case CTRUMP_VEC_ULONGLONG:
00404 case CTRUMP_VEC_FLOAT:
00405 case CTRUMP_VEC_DOUBLE:
00406 *size = abi->sizeof_vector;
00407 *align = abi->alignof_vector;
00408 return 0;
00409
00410 case CTRUMP_VOID:
00411
00412 return -1;
00413 }
00414
00415 case CTRUMP_TYPE_ENUM:
00416 *size = abi->sizeof_enum;
00417 *align = abi->alignof_enum;
00418 return 0;
00419
00420 case CTRUMP_TYPE_POINTER:
00421 *size = abi->sizeof_pointer;
00422 *align = abi->alignof_pointer;
00423 return 0;
00424
00425 case CTRUMP_TYPE_ARRAY:
00426 CHECK_ERROR(ctrump_texpr_size(&get_size, &get_align,
00427 abi, type->u.array.array_of));
00428
00429 *size = get_size * type->u.array.size;
00430 *align = get_align;
00431 return 0;
00432
00433 case CTRUMP_TYPE_TYPEDEF_NAME:
00434 type = type->u.typedef_name.defined_to;
00435 goto tailcall;
00436
00437 case CTRUMP_TYPE_QUALIFIED:
00438 CHECK_ERROR(ctrump_texpr_size(&get_size, &get_align,
00439 abi, type->u.qualified.unqualified_type));
00440
00441 attr_align = type->u.qualified.attr.aligned;
00442
00443 if (attr_align > get_align)
00444 get_align = attr_align;
00445 *size = get_size;
00446 *align = get_align;
00447 return 0;
00448
00449 case CTRUMP_TYPE_UNION:
00450 return calc_union_size(size, align, abi, &type->u.union_);
00451
00452 case CTRUMP_TYPE_STRUCT:
00453 return calc_struct_size(size, align, abi, &type->u.struct_);
00454
00455 case CTRUMP_TYPE_VARLEN_ARRAY:
00456 return -1;
00457
00458 case CTRUMP_TYPE_INCOMPLETE_ARRAY:
00459 case CTRUMP_TYPE_FUNC:
00460
00461 return -1;
00462 }
00463
00464 ctrump_unreachable("calc type size");
00465 }
00466
00467 int
00468 ctrump_is_bitconvertion_on_type_conversion(const struct ctrump_texpr *convert_to,
00469 const struct ctrump_texpr *convert_from,
00470 const struct ctrump_abi *abi)
00471 {
00472 size_t to_size, to_align, from_size, from_align;
00473 int from_is_float, to_is_float;
00474 if ((!ctrump_type_is_scalar(convert_to)) ||
00475 (!ctrump_type_is_scalar(convert_from))) {
00476 return 0;
00477 }
00478
00479 to_is_float = ctrump_type_is_float(convert_to);
00480 from_is_float = ctrump_type_is_float(convert_from);
00481
00482 if (to_is_float != from_is_float)
00483 return 0;
00484
00485 assert(ctrump_texpr_size(&to_size, &to_align, abi, convert_to) == 0);
00486 assert(ctrump_texpr_size(&from_size, &from_align, abi, convert_from) == 0);
00487
00488 return (to_size == from_size);
00489 }
00490
00491
00492 int
00493 ctrump_struct_field_offset(const struct ctrump_record_type *record,
00494 const struct ctrump_symbol *field_tag,
00495 const struct ctrump_abi *abi)
00496 {
00497 int i, n=record->nfield;
00498 int offset = 0;
00499 int max_align = 1;
00500
00501 if (! record->is_completed) {
00502 return -1;
00503 }
00504
00505 for (i=0; i<n; i++) {
00506 struct ctrump_record_type_field *f = &record->fields[i];
00507 int this_field_offset;
00508 this_field_offset = record_field_offset(&offset, &max_align, f, abi);
00509
00510 if (f->name == field_tag)
00511 return this_field_offset;
00512 }
00513
00514
00515 return -1;
00516 }