| 1073 | } |
| 1074 | |
| 1075 | CeOperand CeBuilder::EmitNumericCast(const CeOperand& ceValue, BeType* toType, bool valSigned, bool toSigned) |
| 1076 | { |
| 1077 | if (ceValue.mKind == CeOperandKind_Immediate) |
| 1078 | { |
| 1079 | CeOperand newVal = ceValue; |
| 1080 | newVal.mType = toType; |
| 1081 | return newVal; |
| 1082 | } |
| 1083 | |
| 1084 | CeOperand result; |
| 1085 | auto fromType = ceValue.mType; |
| 1086 | |
| 1087 | if (fromType == toType) |
| 1088 | { |
| 1089 | // If it's just a sign change then leave it alone |
| 1090 | result = ceValue; |
| 1091 | } |
| 1092 | else |
| 1093 | { |
| 1094 | if ((toType->IsIntable()) && (fromType->IsIntable()) && (toType->mSize <= fromType->mSize)) |
| 1095 | { |
| 1096 | // For truncating values, no actual instructions are needed |
| 1097 | // Note that a copy is not needed because of SSA rules |
| 1098 | result = ceValue; |
| 1099 | result.mType = toType; |
| 1100 | } |
| 1101 | else |
| 1102 | { |
| 1103 | result = FrameAlloc(toType); |
| 1104 | |
| 1105 | CeOp op = CeOp_InvalidOp; |
| 1106 | |
| 1107 | BeTypeCode fromTypeCode = fromType->mTypeCode; |
| 1108 | BeTypeCode toTypeCode = toType->mTypeCode; |
| 1109 | |
| 1110 | if ((valSigned) && (toSigned)) |
| 1111 | { |
| 1112 | switch (fromTypeCode) |
| 1113 | { |
| 1114 | case BeTypeCode_Int8: |
| 1115 | switch (toTypeCode) |
| 1116 | { |
| 1117 | case BeTypeCode_Int16: |
| 1118 | op = CeOp_Conv_I8_I16; |
| 1119 | break; |
| 1120 | case BeTypeCode_Int32: |
| 1121 | op = CeOp_Conv_I8_I32; |
| 1122 | break; |
| 1123 | case BeTypeCode_Int64: |
| 1124 | op = CeOp_Conv_I8_I64; |
| 1125 | break; |
| 1126 | case BeTypeCode_Float: |
| 1127 | op = CeOp_Conv_I8_F32; |
| 1128 | break; |
| 1129 | case BeTypeCode_Double: |
| 1130 | op = CeOp_Conv_I8_F64; |
| 1131 | break; |
| 1132 | } |