conversion.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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();
  26. conversion(from_type, to_type)
  27. register struct type *from_type, *to_type;
  28. {
  29. register arith from_size = from_type->tp_size;
  30. register arith to_size = to_type->tp_size;
  31. int from_cnvtype = convtype(from_type);
  32. int to_cnvtype = convtype(to_type);
  33. if ((int)to_size < (int)word_size) to_size = word_size;
  34. if ((int)from_size != (int)to_size || from_cnvtype != to_cnvtype) {
  35. switch (from_cnvtype) {
  36. case T_SIGNED:
  37. switch (to_cnvtype) {
  38. case T_SIGNED:
  39. C_loc(from_size);
  40. C_loc(to_size);
  41. C_cii();
  42. break;
  43. case T_UNSIGNED:
  44. case T_FLOATING:
  45. if ((int)from_size < (int)word_size) {
  46. C_loc(from_size);
  47. C_loc(word_size);
  48. C_cii();
  49. from_size = word_size;
  50. }
  51. /* 3.2.1.2 */
  52. if (to_cnvtype == T_UNSIGNED
  53. && (int)from_size < (int)to_size) {
  54. C_loc(from_size);
  55. C_loc(to_size);
  56. C_cii();
  57. from_size = to_size;
  58. }
  59. C_loc(from_size);
  60. C_loc(to_size);
  61. if (to_cnvtype == T_UNSIGNED) C_ciu();
  62. else C_cif();
  63. break;
  64. }
  65. break;
  66. case T_UNSIGNED:
  67. if ((int)from_size < (int)word_size) from_size = word_size;
  68. C_loc(from_size);
  69. C_loc(to_size);
  70. switch (to_cnvtype) {
  71. case T_SIGNED:
  72. C_cui();
  73. break;
  74. case T_UNSIGNED:
  75. C_cuu();
  76. break;
  77. case T_FLOATING:
  78. C_cuf();
  79. break;
  80. }
  81. break;
  82. case T_FLOATING:
  83. C_loc(from_size);
  84. C_loc(to_size);
  85. switch (to_cnvtype) {
  86. case T_SIGNED:
  87. C_cfi();
  88. break;
  89. case T_UNSIGNED:
  90. C_cfu();
  91. break;
  92. case T_FLOATING:
  93. C_cff();
  94. break;
  95. }
  96. break;
  97. default:
  98. crash("(conversion) illegal type conversion");
  99. /*NOTREACHED*/
  100. }
  101. }
  102. if ((int)(to_type->tp_size) < (int)word_size
  103. && to_cnvtype != T_FLOATING
  104. ) {
  105. extern arith full_mask[];
  106. if (to_cnvtype == T_SIGNED) {
  107. C_loc(to_type->tp_size);
  108. C_loc(word_size);
  109. C_cii();
  110. }
  111. else {
  112. C_loc((arith) full_mask[(int)(to_type->tp_size)]);
  113. C_and(word_size);
  114. }
  115. }
  116. }
  117. /* convtype() returns in which category a given type falls:
  118. signed, unsigned or floating
  119. */
  120. static int
  121. convtype(tp)
  122. register struct type *tp;
  123. {
  124. switch (tp->tp_fund) {
  125. case CHAR:
  126. case SHORT:
  127. case INT:
  128. case ERRONEOUS:
  129. case LONG:
  130. case ENUM:
  131. return tp->tp_unsigned ? T_UNSIGNED : T_SIGNED;
  132. case FLOAT:
  133. case DOUBLE:
  134. case LNGDBL:
  135. return T_FLOATING;
  136. case POINTER:
  137. return T_UNSIGNED;
  138. }
  139. return 0;
  140. }
  141. #endif /* LINT */