| ... | ... | @@ -1034,7 +1034,7 @@ static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *blo |
| 1034 | 1034 | // unsigned/float division uses the operator |
| 1035 | 1035 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeMod, stmt->getRHS()); |
| 1036 | 1036 | } else { |
| 1037 | | // signed integer division uses @divTrunc |
| 1037 | // signed integer division uses @rem |
| 1038 | 1038 | AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "rem"); |
| 1039 | 1039 | AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue); |
| 1040 | 1040 | if (lhs == nullptr) return nullptr; |
| ... | ... | @@ -1081,36 +1081,6 @@ static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *blo |
| 1081 | 1081 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS()); |
| 1082 | 1082 | case BO_Assign: |
| 1083 | 1083 | return trans_create_assign(c, result_used, block, stmt->getLHS(), stmt->getRHS()); |
| 1084 | | case BO_MulAssign: |
| 1085 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_MulAssign"); |
| 1086 | | return nullptr; |
| 1087 | | case BO_DivAssign: |
| 1088 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_DivAssign"); |
| 1089 | | return nullptr; |
| 1090 | | case BO_RemAssign: |
| 1091 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_RemAssign"); |
| 1092 | | return nullptr; |
| 1093 | | case BO_AddAssign: |
| 1094 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_AddAssign"); |
| 1095 | | return nullptr; |
| 1096 | | case BO_SubAssign: |
| 1097 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_SubAssign"); |
| 1098 | | return nullptr; |
| 1099 | | case BO_ShlAssign: |
| 1100 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_ShlAssign"); |
| 1101 | | return nullptr; |
| 1102 | | case BO_ShrAssign: |
| 1103 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_ShrAssign"); |
| 1104 | | return nullptr; |
| 1105 | | case BO_AndAssign: |
| 1106 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_AndAssign"); |
| 1107 | | return nullptr; |
| 1108 | | case BO_XorAssign: |
| 1109 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_XorAssign"); |
| 1110 | | return nullptr; |
| 1111 | | case BO_OrAssign: |
| 1112 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_OrAssign"); |
| 1113 | | return nullptr; |
| 1114 | 1084 | case BO_Comma: |
| 1115 | 1085 | { |
| 1116 | 1086 | block = trans_create_node(c, NodeTypeBlock); |
| ... | ... | @@ -1123,112 +1093,181 @@ static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *blo |
| 1123 | 1093 | block->data.block.last_statement_is_result_expression = true; |
| 1124 | 1094 | return block; |
| 1125 | 1095 | } |
| 1126 | | } |
| 1127 | | |
| 1128 | | zig_unreachable(); |
| 1129 | | } |
| 1130 | | |
| 1131 | | static AstNode *trans_compound_assign_operator(Context *c, bool result_used, AstNode *block, CompoundAssignOperator *stmt) { |
| 1132 | | switch (stmt->getOpcode()) { |
| 1133 | 1096 | case BO_MulAssign: |
| 1134 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_MulAssign"); |
| 1135 | | return nullptr; |
| 1136 | 1097 | case BO_DivAssign: |
| 1137 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_DivAssign"); |
| 1138 | | return nullptr; |
| 1139 | 1098 | case BO_RemAssign: |
| 1140 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_RemAssign"); |
| 1141 | | return nullptr; |
| 1142 | 1099 | case BO_AddAssign: |
| 1143 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_AddAssign"); |
| 1144 | | return nullptr; |
| 1145 | 1100 | case BO_SubAssign: |
| 1146 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_SubAssign"); |
| 1147 | | return nullptr; |
| 1148 | 1101 | case BO_ShlAssign: |
| 1149 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_ShlAssign"); |
| 1150 | | return nullptr; |
| 1151 | | case BO_ShrAssign: { |
| 1152 | | BinOpType bin_op = BinOpTypeBitShiftRight; |
| 1102 | case BO_ShrAssign: |
| 1103 | case BO_AndAssign: |
| 1104 | case BO_XorAssign: |
| 1105 | case BO_OrAssign: |
| 1106 | zig_unreachable(); |
| 1107 | } |
| 1153 | 1108 | |
| 1154 | | const SourceLocation &rhs_location = stmt->getRHS()->getLocStart(); |
| 1155 | | AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location); |
| 1109 | zig_unreachable(); |
| 1110 | } |
| 1156 | 1111 | |
| 1157 | | bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr(); |
| 1158 | | if (!use_intermediate_casts && !result_used) { |
| 1159 | | // simple common case, where the C and Zig are identical: |
| 1160 | | // lhs >>= rh* s |
| 1161 | | AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue); |
| 1162 | | if (lhs == nullptr) return nullptr; |
| 1112 | static AstNode *trans_create_compound_assign_shift(Context *c, bool result_used, AstNode *block, CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) { |
| 1113 | const SourceLocation &rhs_location = stmt->getRHS()->getLocStart(); |
| 1114 | AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location); |
| 1163 | 1115 | |
| 1164 | | AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransRValue); |
| 1165 | | if (rhs == nullptr) return nullptr; |
| 1166 | | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); |
| 1116 | bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr(); |
| 1117 | if (!use_intermediate_casts && !result_used) { |
| 1118 | // simple common case, where the C and Zig are identical: |
| 1119 | // lhs >>= rhs |
| 1120 | AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue); |
| 1121 | if (lhs == nullptr) return nullptr; |
| 1167 | 1122 | |
| 1168 | | return trans_create_node_bin_op(c, lhs, BinOpTypeAssignBitShiftRight, coerced_rhs); |
| 1169 | | } else { |
| 1170 | | // need more complexity. worst case, this looks like this: |
| 1171 | | // c: lhs >>= rhs |
| 1172 | | // zig: { |
| 1173 | | // zig: const _ref = &lhs; |
| 1174 | | // zig: *_ref = result_type(operation_type(*_ref) >> u5(rhs)); |
| 1175 | | // zig: *_ref |
| 1176 | | // zig: } |
| 1177 | | // where u5 is the appropriate type |
| 1123 | AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransRValue); |
| 1124 | if (rhs == nullptr) return nullptr; |
| 1125 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); |
| 1178 | 1126 | |
| 1179 | | // TODO: avoid mess when we don't need the assignment value for chained assignments or anything. |
| 1180 | | AstNode *child_block = trans_create_node(c, NodeTypeBlock); |
| 1127 | return trans_create_node_bin_op(c, lhs, assign_op, coerced_rhs); |
| 1128 | } else { |
| 1129 | // need more complexity. worst case, this looks like this: |
| 1130 | // c: lhs >>= rhs |
| 1131 | // zig: { |
| 1132 | // zig: const _ref = &lhs; |
| 1133 | // zig: *_ref = result_type(operation_type(*_ref) >> u5(rhs)); |
| 1134 | // zig: *_ref |
| 1135 | // zig: } |
| 1136 | // where u5 is the appropriate type |
| 1181 | 1137 | |
| 1182 | | // const _ref = &lhs; |
| 1183 | | AstNode *lhs = trans_expr(c, true, child_block, stmt->getLHS(), TransLValue); |
| 1184 | | if (lhs == nullptr) return nullptr; |
| 1185 | | AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs); |
| 1186 | | // TODO: avoid name collisions with generated variable names |
| 1187 | | Buf* tmp_var_name = buf_create_from_str("_ref"); |
| 1188 | | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, addr_of_lhs); |
| 1189 | | child_block->data.block.statements.append(tmp_var_decl); |
| 1138 | AstNode *child_block = trans_create_node(c, NodeTypeBlock); |
| 1190 | 1139 | |
| 1191 | | // *_ref = result_type(operation_type(*_ref) >> u5(rhs)); |
| 1140 | // const _ref = &lhs; |
| 1141 | AstNode *lhs = trans_expr(c, true, child_block, stmt->getLHS(), TransLValue); |
| 1142 | if (lhs == nullptr) return nullptr; |
| 1143 | AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs); |
| 1144 | // TODO: avoid name collisions with generated variable names |
| 1145 | Buf* tmp_var_name = buf_create_from_str("_ref"); |
| 1146 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, addr_of_lhs); |
| 1147 | child_block->data.block.statements.append(tmp_var_decl); |
| 1192 | 1148 | |
| 1193 | | AstNode *rhs = trans_expr(c, true, child_block, stmt->getRHS(), TransRValue); |
| 1194 | | if (rhs == nullptr) return nullptr; |
| 1195 | | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); |
| 1149 | // *_ref = result_type(operation_type(*_ref) >> u5(rhs)); |
| 1196 | 1150 | |
| 1197 | | AstNode *assign_statement = trans_create_node_bin_op(c, |
| 1198 | | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1199 | | trans_create_node_symbol(c, tmp_var_name)), |
| 1200 | | BinOpTypeAssign, |
| 1151 | AstNode *rhs = trans_expr(c, true, child_block, stmt->getRHS(), TransRValue); |
| 1152 | if (rhs == nullptr) return nullptr; |
| 1153 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); |
| 1154 | |
| 1155 | AstNode *assign_statement = trans_create_node_bin_op(c, |
| 1156 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1157 | trans_create_node_symbol(c, tmp_var_name)), |
| 1158 | BinOpTypeAssign, |
| 1159 | trans_c_cast(c, rhs_location, |
| 1160 | stmt->getComputationResultType(), |
| 1161 | trans_create_node_bin_op(c, |
| 1201 | 1162 | trans_c_cast(c, rhs_location, |
| 1202 | | stmt->getComputationResultType(), |
| 1203 | | trans_create_node_bin_op(c, |
| 1204 | | trans_c_cast(c, rhs_location, |
| 1205 | | stmt->getComputationLHSType(), |
| 1206 | | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1207 | | trans_create_node_symbol(c, tmp_var_name))), |
| 1208 | | bin_op, |
| 1209 | | coerced_rhs))); |
| 1210 | | child_block->data.block.statements.append(assign_statement); |
| 1211 | | |
| 1212 | | if (result_used) { |
| 1213 | | // *_ref |
| 1214 | | child_block->data.block.statements.append( |
| 1163 | stmt->getComputationLHSType(), |
| 1215 | 1164 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1216 | | trans_create_node_symbol(c, tmp_var_name))); |
| 1217 | | child_block->data.block.last_statement_is_result_expression = true; |
| 1218 | | } |
| 1219 | | |
| 1220 | | return child_block; |
| 1221 | | } |
| 1165 | trans_create_node_symbol(c, tmp_var_name))), |
| 1166 | bin_op, |
| 1167 | coerced_rhs))); |
| 1168 | child_block->data.block.statements.append(assign_statement); |
| 1169 | |
| 1170 | if (result_used) { |
| 1171 | // *_ref |
| 1172 | child_block->data.block.statements.append( |
| 1173 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1174 | trans_create_node_symbol(c, tmp_var_name))); |
| 1175 | child_block->data.block.last_statement_is_result_expression = true; |
| 1222 | 1176 | } |
| 1223 | | case BO_AndAssign: |
| 1224 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_AndAssign"); |
| 1177 | |
| 1178 | return child_block; |
| 1179 | } |
| 1180 | } |
| 1181 | |
| 1182 | static AstNode *trans_create_compound_assign(Context *c, bool result_used, AstNode *block, CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) { |
| 1183 | if (!result_used) { |
| 1184 | // simple common case, where the C and Zig are identical: |
| 1185 | // lhs += rhs |
| 1186 | AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue); |
| 1187 | if (lhs == nullptr) return nullptr; |
| 1188 | AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransRValue); |
| 1189 | if (rhs == nullptr) return nullptr; |
| 1190 | return trans_create_node_bin_op(c, lhs, assign_op, rhs); |
| 1191 | } else { |
| 1192 | // need more complexity. worst case, this looks like this: |
| 1193 | // c: lhs += rhs |
| 1194 | // zig: { |
| 1195 | // zig: const _ref = &lhs; |
| 1196 | // zig: *_ref = *_ref + rhs; |
| 1197 | // zig: *_ref |
| 1198 | // zig: } |
| 1199 | |
| 1200 | AstNode *child_block = trans_create_node(c, NodeTypeBlock); |
| 1201 | |
| 1202 | // const _ref = &lhs; |
| 1203 | AstNode *lhs = trans_expr(c, true, child_block, stmt->getLHS(), TransLValue); |
| 1204 | if (lhs == nullptr) return nullptr; |
| 1205 | AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs); |
| 1206 | // TODO: avoid name collisions with generated variable names |
| 1207 | Buf* tmp_var_name = buf_create_from_str("_ref"); |
| 1208 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, addr_of_lhs); |
| 1209 | child_block->data.block.statements.append(tmp_var_decl); |
| 1210 | |
| 1211 | // *_ref = *_ref + rhs; |
| 1212 | |
| 1213 | AstNode *rhs = trans_expr(c, true, child_block, stmt->getRHS(), TransRValue); |
| 1214 | if (rhs == nullptr) return nullptr; |
| 1215 | |
| 1216 | AstNode *assign_statement = trans_create_node_bin_op(c, |
| 1217 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1218 | trans_create_node_symbol(c, tmp_var_name)), |
| 1219 | BinOpTypeAssign, |
| 1220 | trans_create_node_bin_op(c, |
| 1221 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1222 | trans_create_node_symbol(c, tmp_var_name)), |
| 1223 | bin_op, |
| 1224 | rhs)); |
| 1225 | child_block->data.block.statements.append(assign_statement); |
| 1226 | |
| 1227 | // *_ref |
| 1228 | child_block->data.block.statements.append( |
| 1229 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1230 | trans_create_node_symbol(c, tmp_var_name))); |
| 1231 | child_block->data.block.last_statement_is_result_expression = true; |
| 1232 | |
| 1233 | return child_block; |
| 1234 | } |
| 1235 | } |
| 1236 | |
| 1237 | |
| 1238 | static AstNode *trans_compound_assign_operator(Context *c, bool result_used, AstNode *block, CompoundAssignOperator *stmt) { |
| 1239 | switch (stmt->getOpcode()) { |
| 1240 | case BO_MulAssign: |
| 1241 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1242 | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignTimesWrap, BinOpTypeMultWrap); |
| 1243 | else |
| 1244 | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignTimes, BinOpTypeMult); |
| 1245 | case BO_DivAssign: |
| 1246 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_DivAssign"); |
| 1225 | 1247 | return nullptr; |
| 1226 | | case BO_XorAssign: |
| 1227 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_XorAssign"); |
| 1248 | case BO_RemAssign: |
| 1249 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_RemAssign"); |
| 1228 | 1250 | return nullptr; |
| 1251 | case BO_AddAssign: |
| 1252 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1253 | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignPlusWrap, BinOpTypeAddWrap); |
| 1254 | else |
| 1255 | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignPlus, BinOpTypeAdd); |
| 1256 | case BO_SubAssign: |
| 1257 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1258 | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignMinusWrap, BinOpTypeSubWrap); |
| 1259 | else |
| 1260 | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignMinus, BinOpTypeSub); |
| 1261 | case BO_ShlAssign: |
| 1262 | return trans_create_compound_assign_shift(c, result_used, block, stmt, BinOpTypeAssignBitShiftLeft, BinOpTypeBitShiftLeft); |
| 1263 | case BO_ShrAssign: |
| 1264 | return trans_create_compound_assign_shift(c, result_used, block, stmt, BinOpTypeAssignBitShiftRight, BinOpTypeBitShiftRight); |
| 1265 | case BO_AndAssign: |
| 1266 | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignBitAnd, BinOpTypeBinAnd); |
| 1267 | case BO_XorAssign: |
| 1268 | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignBitXor, BinOpTypeBinXor); |
| 1229 | 1269 | case BO_OrAssign: |
| 1230 | | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_OrAssign"); |
| 1231 | | return nullptr; |
| 1270 | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignBitOr, BinOpTypeBinOr); |
| 1232 | 1271 | case BO_PtrMemD: |
| 1233 | 1272 | case BO_PtrMemI: |
| 1234 | 1273 | case BO_Assign: |
| ... | ... | @@ -1251,7 +1290,7 @@ static AstNode *trans_compound_assign_operator(Context *c, bool result_used, Ast |
| 1251 | 1290 | case BO_LAnd: |
| 1252 | 1291 | case BO_LOr: |
| 1253 | 1292 | case BO_Comma: |
| 1254 | | zig_panic("compound assign expected to be handled by binary operator"); |
| 1293 | zig_unreachable(); |
| 1255 | 1294 | } |
| 1256 | 1295 | |
| 1257 | 1296 | zig_unreachable(); |