coan 4.2.4
|
00001 /*************************************************************************** 00002 * Copyright (C) 2004, 2006 Symbian Software Ltd. * 00003 * All rights reserved. * 00004 * Copyright (C) 2007-2011 Mike Kinghan, imk@strudl.org * 00005 * All rights reserved. * 00006 * * 00007 * Contributed originally by Mike Kinghan, imk@strudl.org * 00008 * * 00009 * Redistribution and use in source and binary forms, with or without * 00010 * modification, are permitted provided that the following conditions * 00011 * are met: * 00012 * * 00013 * Redistributions of source code must retain the above copyright * 00014 * notice, this list of conditions and the following disclaimer. * 00015 * * 00016 * Redistributions in binary form must reproduce the above copyright * 00017 * notice, this list of conditions and the following disclaimer in the * 00018 * documentation and/or other materials provided with the distribution. * 00019 * * 00020 * Neither the name of Symbian Software Ltd. nor the names of its * 00021 * contributors may be used to endorse or promote products derived from * 00022 * this software without specific prior written permission. * 00023 * * 00024 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * 00025 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * 00026 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * 00027 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * 00028 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * 00029 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * 00030 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * 00031 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * 00032 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,* 00033 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * 00034 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * 00035 * DAMAGE. * 00036 * * 00037 **************************************************************************/ 00038 00039 #include "integer_ops.h" 00040 #include "report.h" 00041 00049 00050 /* Helpers */ 00051 00057 static int 00058 sign(int_spec_t const *int_spec) 00059 { 00060 switch(int_spec->type) { 00061 case INT_INT: 00062 return int_spec->val.i < 0 ? -1 : 1; 00063 case INT_UINT: 00064 return 1; 00065 case INT_LONG: 00066 return int_spec->val.l < 0L ? -1 : 1; 00067 case INT_ULONG: 00068 return 1; 00069 case INT_LLONG: 00070 return int_spec->val.ll < 0LL ? -1 : 1; 00071 case INT_ULLONG: 00072 return 1; 00073 default: 00074 return 0; 00075 } 00076 } 00077 00078 00092 static void 00093 sign_extend(int_spec_t * converted, int_spec_t const * unconverted) 00094 { 00095 if (IS_SIGNED(unconverted->type) && sign(unconverted) == -1 && 00096 RANK(converted->type) > RANK(unconverted->type)) { 00097 switch(converted->type) { 00098 case INT_LONG: 00099 case INT_ULONG: 00100 switch(unconverted->type) { 00101 case INT_INT: 00102 converted->val.ul = unconverted->val.i; 00103 break; 00104 default: 00105 assert(false); 00106 } 00107 break; 00108 case INT_LLONG: 00109 case INT_ULLONG: 00110 switch(unconverted->type) { 00111 case INT_INT: 00112 converted->val.ull = unconverted->val.i; 00113 break; 00114 case INT_LONG: 00115 converted->val.ull = unconverted->val.l; 00116 break; 00117 default: 00118 assert(false); 00119 } 00120 break; 00121 default: 00122 assert(false); 00123 } 00124 } 00125 } 00126 00140 static void 00141 do_usual_conversions(int_spec_t const * l, int_spec_t const *r, int_spec_t *cl, int_spec_t *cr) 00142 { 00143 int_type lhs = l->type; 00144 int_type rhs = r->type; 00145 int_spec_t * post_sign_changed = NULL; 00146 int_spec_t const * pre_sign_changed = NULL; 00147 00148 /* Initialise the converted operands with the unconverted operands */ 00149 *cl = *l; 00150 *cr = *r; 00151 00152 /* if both operands have the same type, then no further conversion is needed. */ 00153 if (lhs == rhs) { 00154 return; 00155 } 00156 /* Otherwise, if both operands have signed integer types or both have unsigned 00157 integer types, the operand with the type of lesser integer conversion rank is 00158 converted to the type of the operand with greater rank. */ 00159 if (IS_SIGNED(lhs) == IS_SIGNED(rhs)) { 00160 cl->type = cr->type = RANK(lhs) > RANK(rhs) ? lhs : rhs; 00161 return; 00162 00163 } 00164 /* Otherwise, if the operand that has unsigned integer type has rank greater or 00165 equal to the rank of the type of the other operand, then the operand with 00166 signed integer type is converted to the type of the operand with unsigned 00167 integer type. */ 00168 if (!IS_SIGNED(lhs) && RANK(lhs) >= RANK(rhs)) { 00169 post_sign_changed = cr; 00170 pre_sign_changed = r; 00171 cr->type = cl->type; 00172 } 00173 else if (!IS_SIGNED(rhs) && RANK(rhs) >= RANK(lhs)) { 00174 post_sign_changed = cl; 00175 pre_sign_changed = l; 00176 cl->type = cr->type; 00177 } 00178 /* Otherwise, if the type of the operand with signed integer type can represent 00179 all of the values of the type of the operand with unsigned integer type, then 00180 the operand with unsigned integer type is converted to the type of the 00181 operand with signed integer type. */ 00182 else if (IS_SIGNED(lhs) && SIZEOF(lhs) > SIZEOF(rhs)) { 00183 post_sign_changed = cr; 00184 pre_sign_changed = r; 00185 cr->type = cl->type; 00186 } 00187 else if (IS_SIGNED(rhs) && SIZEOF(rhs) > SIZEOF(lhs)) { 00188 post_sign_changed = cl; 00189 pre_sign_changed = l; 00190 cl->type = cr->type; 00191 } 00192 /* Otherwise, both operands are converted to the unsigned integer type 00193 corresponding to the type of the operand with signed integer type. */ 00194 else if (IS_SIGNED(lhs)) { 00195 post_sign_changed = cl; 00196 pre_sign_changed = l; 00197 cl->type = cr->type = MAKE_UNSIGNED(lhs); 00198 00199 } 00200 else if (IS_SIGNED(rhs)) { 00201 post_sign_changed = cr; 00202 pre_sign_changed = r; 00203 cl->type = cr->type = MAKE_UNSIGNED(rhs); 00204 } 00205 if (post_sign_changed) { 00206 sign_extend(post_sign_changed,pre_sign_changed); 00207 if (sign(post_sign_changed) != sign(pre_sign_changed)) { 00208 char *orig = format_int(pre_sign_changed); 00209 char *converted = format_int(post_sign_changed); 00210 report(GRIPE_SIGN_CHANGED,NULL,"Integer %s changed to %s by the usual arithmetic conversions", 00211 orig,converted); 00212 free(orig); 00213 free(converted); 00214 } 00215 } 00216 } 00217 00226 static bool 00227 check_shift_validity(char const *direction, int_type type, int_spec_t const * shiftval) 00228 { 00229 bool ok = true; 00230 unsigned type_bits = SIZEOF(type) * 8; 00231 unsigned long long val = shiftval->val.ull; 00232 if (IS_SIGNED(shiftval->type)) { 00233 unsigned long long neg_bit = (unsigned long long)1 << (type_bits - 1); 00234 if (val & neg_bit) { 00235 report(GRIPE_NEGATIVE_SHIFT,NULL,"Negative %s-shift has undefined behavior. " 00236 "The expression will not be resolved",direction); 00237 ok = false; 00238 } 00239 } 00240 if (ok && val >= type_bits) { 00241 report(GRIPE_SHIFT_OVERFLOW,NULL,"Shifting a quantity passed its width has undefined behavior. The expression will not be resolved"); 00242 ok = false; 00243 } 00244 return ok; 00245 } 00246 00249 /* API*/ 00250 00251 int_spec_t 00252 lt(int_spec_t const * l, int_spec_t const *r) 00253 { 00254 int_spec_t result = {INT_UNION_INITOR,INT_INT}; 00255 int_spec_t cl,cr; 00256 do_usual_conversions(l,r,&cl,&cr); 00257 result.type = cl.type; 00258 switch(result.type) { 00259 case INT_INT: 00260 result.val.i = cl.val.i < cr.val.i; 00261 break; 00262 case INT_UINT: 00263 result.val.i = cl.val.ui < cr.val.ui; 00264 break; 00265 case INT_LONG: 00266 result.val.i = cl.val.l < cr.val.l; 00267 break; 00268 case INT_ULONG: 00269 result.val.i = cl.val.ul < cr.val.ul; 00270 break; 00271 case INT_LLONG: 00272 result.val.i = cl.val.ll < cr.val.ll; 00273 break; 00274 case INT_ULLONG: 00275 result.val.i = cl.val.ull < cr.val.ull; 00276 break; 00277 default: 00278 assert(false); 00279 } 00280 return result; 00281 } 00282 00283 int_spec_t 00284 gt(int_spec_t const * l, int_spec_t const *r) 00285 { 00286 return lt(r,l); 00287 } 00288 00289 int_spec_t 00290 le(int_spec_t const * l, int_spec_t const *r) 00291 { 00292 int_spec_t result = INT_SPEC_INITOR; 00293 int_spec_t cl,cr; 00294 do_usual_conversions(l,r,&cl,&cr); 00295 result.type = cl.type; 00296 switch(result.type) { 00297 case INT_INT: 00298 result.val.i = cl.val.i <= cr.val.i; 00299 break; 00300 case INT_UINT: 00301 result.val.i = cl.val.ui <= cr.val.ui; 00302 break; 00303 case INT_LONG: 00304 result.val.i = cl.val.l <= cr.val.l; 00305 break; 00306 case INT_ULONG: 00307 result.val.i = cl.val.ul <= cr.val.ul; 00308 break; 00309 case INT_LLONG: 00310 result.val.i = cl.val.ll <= cr.val.ll; 00311 break; 00312 case INT_ULLONG: 00313 result.val.i = cl.val.ull <= cr.val.ull; 00314 break; 00315 default: 00316 assert(false); 00317 } 00318 return result; 00319 } 00320 00321 int_spec_t 00322 ge(int_spec_t const * l, int_spec_t const *r) 00323 { 00324 return le(r,l); 00325 } 00326 00327 int_spec_t 00328 eq(int_spec_t const * l, int_spec_t const *r) 00329 { 00330 int_spec_t result = {INT_UNION_INITOR,INT_INT}; 00331 result.val.i = l->val.ll == r->val.ll; 00332 return result; 00333 } 00334 00335 int_spec_t 00336 ne(int_spec_t const * l, int_spec_t const *r) 00337 { 00338 int_spec_t result = {INT_UNION_INITOR,INT_INT}; 00339 result.val.i = l->val.ll != r->val.ll; 00340 return result; 00341 00342 } 00343 00344 int_spec_t 00345 bit_and(int_spec_t const * l, int_spec_t const *r) 00346 { 00347 int_spec_t result = INT_SPEC_INITOR; 00348 int_spec_t cl,cr; 00349 do_usual_conversions(l,r,&cl,&cr); 00350 result.type = cl.type; 00351 result.val.ll = cl.val.ll & cr.val.ll; 00352 return result; 00353 } 00354 00355 int_spec_t 00356 bit_or(int_spec_t const * l, int_spec_t const *r) 00357 { 00358 int_spec_t result = INT_SPEC_INITOR; 00359 int_spec_t cl,cr; 00360 do_usual_conversions(l,r,&cl,&cr); 00361 result.type = cl.type; 00362 result.val.ll = cl.val.ll | cr.val.ll; 00363 return result; 00364 } 00365 00366 int_spec_t 00367 bit_xor(int_spec_t const * l, int_spec_t const *r) 00368 { 00369 int_spec_t result = INT_SPEC_INITOR; 00370 int_spec_t cl,cr; 00371 do_usual_conversions(l,r,&cl,&cr); 00372 result.type = cl.type; 00373 result.val.ll = cl.val.ll ^ cr.val.ll; 00374 return result; 00375 } 00376 00377 int_spec_t 00378 complement(int_spec_t const * int_spec) 00379 { 00380 int_spec_t result = INT_SPEC_INITOR; 00381 result.type = int_spec->type; 00382 switch(result.type) { 00383 case INT_INT: 00384 case INT_UINT: 00385 result.val.ui = ~int_spec->val.ui; 00386 break; 00387 case INT_LONG: 00388 case INT_ULONG: 00389 result.val.ul = ~int_spec->val.ul; 00390 break; 00391 case INT_LLONG: 00392 case INT_ULLONG: 00393 result.val.ull = ~int_spec->val.ull; 00394 default: 00395 assert(false); 00396 } 00397 return result; 00398 } 00399 00400 int_spec_t 00401 minus(int_spec_t const * int_spec) 00402 { 00403 int_spec_t result = INT_SPEC_INITOR; 00404 result.type = int_spec->type; 00405 switch(result.type) { 00406 case INT_INT: 00407 result.val.i = -int_spec->val.i; 00408 break; 00409 case INT_UINT: 00410 result.val.ui = -int_spec->val.ui; 00411 break; 00412 case INT_LONG: 00413 result.val.l = -int_spec->val.l; 00414 break; 00415 case INT_ULONG: 00416 result.val.ul = -int_spec->val.ul; 00417 break; 00418 case INT_LLONG: 00419 result.val.ll = -int_spec->val.ll; 00420 break; 00421 case INT_ULLONG: 00422 result.val.ull = -int_spec->val.ull; 00423 break; 00424 default: 00425 assert(false); 00426 } 00427 return result; 00428 } 00429 00430 int_spec_t 00431 lshift(int_spec_t const * l, int_spec_t const *r) 00432 { 00433 int_spec_t result = INT_SPEC_INITOR; 00434 int_type type = l->type; 00435 bool valid_shift = check_shift_validity("left",type,r); 00436 if (valid_shift) { 00437 result.type = type; 00438 switch(type) { 00439 case INT_INT: 00440 result.val.i = l->val.i << r->val.i; 00441 break; 00442 case INT_UINT: 00443 result.val.ui = l->val.ui << r->val.i; 00444 break; 00445 case INT_LONG: 00446 result.val.l = l->val.l << r->val.i; 00447 break; 00448 case INT_ULONG: 00449 result.val.ul = l->val.ul << r->val.i; 00450 break; 00451 case INT_LLONG: 00452 result.val.ll = l->val.ll << r->val.i; 00453 break; 00454 case INT_ULLONG: 00455 result.val.ull = l->val.ull << r->val.i; 00456 break; 00457 default: 00458 assert(false); 00459 } 00460 } 00461 return result; 00462 } 00463 00464 int_spec_t 00465 rshift(int_spec_t const * l, int_spec_t const *r) 00466 { 00467 int_spec_t result = INT_SPEC_INITOR; 00468 int_type type = l->type; 00469 bool valid_shift = check_shift_validity("left",type,r); 00470 if (valid_shift) { 00471 result.type = type; 00472 switch(type) { 00473 case INT_INT: 00474 result.val.i = l->val.i >> r->val.i; 00475 break; 00476 case INT_UINT: 00477 result.val.ui = l->val.ui >> r->val.i; 00478 break; 00479 case INT_LONG: 00480 result.val.l = l->val.l >> r->val.i; 00481 break; 00482 case INT_ULONG: 00483 result.val.ul = l->val.ul >> r->val.i; 00484 break; 00485 case INT_LLONG: 00486 result.val.ll = l->val.ll >> r->val.i; 00487 break; 00488 case INT_ULLONG: 00489 result.val.ull = l->val.ull >> r->val.i; 00490 break; 00491 default: 00492 assert(false); 00493 } 00494 } 00495 return result; 00496 } 00497 00498 int_spec_t 00499 add(int_spec_t const * l, int_spec_t const *r) 00500 { 00501 int_spec_t result = INT_SPEC_INITOR; 00502 int_spec_t cl,cr; 00503 do_usual_conversions(l,r,&cl,&cr); 00504 result.type = cl.type; 00505 switch(result.type) { 00506 case INT_INT: 00507 result.val.i = cl.val.i + cr.val.i; 00508 break; 00509 case INT_UINT: 00510 result.val.ui = cl.val.ui + cr.val.ui; 00511 break; 00512 case INT_LONG: 00513 result.val.l = cl.val.l + cr.val.l; 00514 break; 00515 case INT_ULONG: 00516 result.val.ul = cl.val.ul + cr.val.ul; 00517 break; 00518 case INT_LLONG: 00519 result.val.ll = cl.val.ll + cr.val.ll; 00520 break; 00521 case INT_ULLONG: 00522 result.val.ull = cl.val.ull + cr.val.ull; 00523 break; 00524 default: 00525 assert(false); 00526 } 00527 return result; 00528 } 00529 00530 int_spec_t 00531 subtract(int_spec_t const * l, int_spec_t const *r) 00532 { 00533 int_spec_t result = INT_SPEC_INITOR; 00534 int_spec_t cl,cr; 00535 do_usual_conversions(l,r,&cl,&cr); 00536 result.type = cl.type; 00537 switch(result.type) { 00538 case INT_INT: 00539 result.val.i = cl.val.i - cr.val.i; 00540 break; 00541 case INT_UINT: 00542 result.val.ui = cl.val.ui - cr.val.ui; 00543 break; 00544 case INT_LONG: 00545 result.val.l = cl.val.l - cr.val.l; 00546 break; 00547 case INT_ULONG: 00548 result.val.ul = cl.val.ul - cr.val.ul; 00549 break; 00550 case INT_LLONG: 00551 result.val.ll = cl.val.ll - cr.val.ll; 00552 break; 00553 case INT_ULLONG: 00554 result.val.ull = cl.val.ull - cr.val.ull; 00555 break; 00556 default: 00557 assert(false); 00558 } 00559 return result; 00560 } 00561 00562 int_spec_t 00563 multiply(int_spec_t const * l, int_spec_t const *r) 00564 { 00565 int_spec_t result = INT_SPEC_INITOR; 00566 int_spec_t cl,cr; 00567 do_usual_conversions(l,r,&cl,&cr); 00568 result.type = cl.type; 00569 switch(result.type) { 00570 case INT_INT: 00571 result.val.i = cl.val.i * cr.val.i; 00572 break; 00573 case INT_UINT: 00574 result.val.ui = cl.val.ui * cr.val.ui; 00575 break; 00576 case INT_LONG: 00577 result.val.l = cl.val.l * cr.val.l; 00578 break; 00579 case INT_ULONG: 00580 result.val.ul = cl.val.ul * cr.val.ul; 00581 break; 00582 case INT_LLONG: 00583 result.val.ll = cl.val.ll * cr.val.ll; 00584 break; 00585 case INT_ULLONG: 00586 result.val.ull = cl.val.ull * cr.val.ull; 00587 break; 00588 default: 00589 assert(false); 00590 } 00591 return result; 00592 } 00593 00594 int_spec_t 00595 divide(int_spec_t const * l, int_spec_t const *r) 00596 { 00597 int_spec_t result = INT_SPEC_INITOR; 00598 int_spec_t cl,cr; 00599 do_usual_conversions(l,r,&cl,&cr); 00600 result.type = cl.type; 00601 switch(result.type) { 00602 case INT_INT: 00603 result.val.i = cl.val.i / cr.val.i; 00604 break; 00605 case INT_UINT: 00606 result.val.ui = cl.val.ui / cr.val.ui; 00607 break; 00608 case INT_LONG: 00609 result.val.l = cl.val.l / cr.val.l; 00610 break; 00611 case INT_ULONG: 00612 result.val.ul = cl.val.ul / cr.val.ul; 00613 break; 00614 case INT_LLONG: 00615 result.val.ll = cl.val.ll / cr.val.ll; 00616 break; 00617 case INT_ULLONG: 00618 result.val.ull = cl.val.ull / cr.val.ull; 00619 break; 00620 default: 00621 assert(false); 00622 } 00623 return result; 00624 } 00625 00626 int_spec_t 00627 modulus(int_spec_t const * l, int_spec_t const *r) 00628 { 00629 int_spec_t result = INT_SPEC_INITOR; 00630 int_spec_t cl,cr; 00631 do_usual_conversions(l,r,&cl,&cr); 00632 result.type = cl.type; 00633 switch(result.type) { 00634 case INT_INT: 00635 result.val.i = cl.val.i % cr.val.i; 00636 break; 00637 case INT_UINT: 00638 result.val.ui = cl.val.ui % cr.val.ui; 00639 break; 00640 case INT_LONG: 00641 result.val.l = cl.val.l % cr.val.l; 00642 break; 00643 case INT_ULONG: 00644 result.val.ul = cl.val.ul % cr.val.ul; 00645 break; 00646 case INT_LLONG: 00647 result.val.ll = cl.val.ll % cr.val.ll; 00648 break; 00649 case INT_ULLONG: 00650 result.val.ull = cl.val.ull % cr.val.ull; 00651 break; 00652 default: 00653 assert(false); 00654 } 00655 return result; 00656 } 00657 00663 int_spec_t 00664 boolean_and(int_spec_t const * l, int_spec_t const *r) 00665 { 00666 int_spec_t result = {INT_UNION_INITOR,INT_INT}; 00667 result.val.i = l->val.ull && r->val.ull; 00668 return result; 00669 } 00670 00676 int_spec_t 00677 boolean_or(int_spec_t const * l, int_spec_t const *r) 00678 { 00679 int_spec_t result = {INT_UNION_INITOR,INT_INT}; 00680 result.val.i = l->val.ull || r->val.ull; 00681 return result; 00682 } 00683 00684 00689 int_spec_t 00690 negate(int_spec_t const * int_spec) 00691 { 00692 int_spec_t result = {INT_UNION_INITOR,INT_INT}; 00693 result.val.i = !int_spec->val.ull; 00694 return result; 00695 } 00696 00697 00698 /* EOF*/ 00699 00700