@@ -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 ();
0 commit comments