conversion.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /*
  2. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  3. * See the copyright notice in the ACK home directory, in the file "Copyright".
  4. */
  5. /* $Id$ */
  6. /* C O N V E R S I O N - C O D E G E N E R A T O R */
  7. #include "lint.h"
  8. #ifndef LINT
  9. #include <em.h>
  10. #include "arith.h"
  11. #include "type.h"
  12. #include "sizes.h"
  13. #include "Lpars.h"
  14. #define T_SIGNED 1
  15. #define T_UNSIGNED 2
  16. #define T_FLOATING 3
  17. /* conversion() generates the EM code for a conversion between
  18. the types char, short, int, long, float, double and pointer.
  19. There are three conversion types: signed, unsigned and floating.
  20. The EM code to obtain this conversion looks like:
  21. LOC sizeof(from_type)
  22. LOC sizeof(to_type)
  23. C??
  24. */
  25. static int convtype(struct type *tp);
  26. void conversion(struct type *from_type, struct type *to_type)
  27. {
  28. arith from_size = from_type->tp_size;
  29. arith to_size = to_type->tp_size;
  30. int from_cnvtype = convtype(from_type);
  31. int to_cnvtype = convtype(to_type);
  32. if ((int)to_size < (int)word_size) to_size = word_size;
  33. if ((int)from_size != (int)to_size || from_cnvtype != to_cnvtype) {
  34. switch (from_cnvtype) {
  35. case T_SIGNED:
  36. switch (to_cnvtype) {
  37. case T_SIGNED:
  38. C_loc(from_size);
  39. C_loc(to_size);
  40. C_cii();
  41. break;
  42. case T_UNSIGNED:
  43. case T_FLOATING:
  44. if ((int)from_size < (int)word_size) {
  45. C_loc(from_size);
  46. C_loc(word_size);
  47. C_cii();
  48. from_size = word_size;
  49. }
  50. /* 3.2.1.2 */
  51. if (to_cnvtype == T_UNSIGNED
  52. && (int)from_size < (int)to_size) {
  53. C_loc(from_size);
  54. C_loc(to_size);
  55. C_cii();
  56. from_size = to_size;
  57. }
  58. C_loc(from_size);
  59. C_loc(to_size);
  60. if (to_cnvtype == T_UNSIGNED) C_ciu();
  61. else C_cif();
  62. break;
  63. }
  64. break;
  65. case T_UNSIGNED:
  66. if ((int)from_size < (int)word_size) from_size = word_size;
  67. C_loc(from_size);
  68. C_loc(to_size);
  69. switch (to_cnvtype) {
  70. case T_SIGNED:
  71. C_cui();
  72. break;
  73. case T_UNSIGNED:
  74. C_cuu();
  75. break;
  76. case T_FLOATING:
  77. C_cuf();
  78. break;
  79. }
  80. break;
  81. case T_FLOATING:
  82. C_loc(from_size);
  83. C_loc(to_size);
  84. switch (to_cnvtype) {
  85. case T_SIGNED:
  86. C_cfi();
  87. break;
  88. case T_UNSIGNED:
  89. C_cfu();
  90. break;
  91. case T_FLOATING:
  92. C_cff();
  93. break;
  94. }
  95. break;
  96. default:
  97. crash("(conversion) illegal type conversion");
  98. /*NOTREACHED*/
  99. }
  100. }
  101. if ((int)(to_type->tp_size) < (int)word_size
  102. && to_cnvtype != T_FLOATING
  103. ) {
  104. extern arith full_mask[];
  105. if (to_cnvtype == T_SIGNED) {
  106. C_loc(to_type->tp_size);
  107. C_loc(word_size);
  108. C_cii();
  109. }
  110. else {
  111. C_loc((arith) full_mask[(int)(to_type->tp_size)]);
  112. C_and(word_size);
  113. }
  114. }
  115. }
  116. /* convtype() returns in which category a given type falls:
  117. signed, unsigned or floating
  118. */
  119. static int convtype(struct type *tp)
  120. {
  121. switch (tp->tp_fund) {
  122. case CHAR:
  123. case SHORT:
  124. case INT:
  125. case ERRONEOUS:
  126. case LONG:
  127. case ENUM:
  128. return tp->tp_unsigned ? T_UNSIGNED : T_SIGNED;
  129. case FLOAT:
  130. case DOUBLE:
  131. case LNGDBL:
  132. return T_FLOATING;
  133. case POINTER:
  134. return T_UNSIGNED;
  135. }
  136. return 0;
  137. }
  138. #endif /* LINT */