| ... | @@ -1034,7 +1034,7 @@ static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *blo | ... | @@ -1034,7 +1034,7 @@ static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *blo |
| 1034 | // unsigned/float division uses the operator | 1034 | // unsigned/float division uses the operator |
| 1035 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeMod, stmt->getRHS()); | 1035 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeMod, stmt->getRHS()); |
| 1036 | } else { | 1036 | } else { |
| 1037 | // signed integer division uses @divTrunc | 1037 | // signed integer division uses @rem |
| 1038 | AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "rem"); | 1038 | AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "rem"); |
| 1039 | AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue); | 1039 | AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue); |
| 1040 | if (lhs == nullptr) return nullptr; | 1040 | if (lhs == nullptr) return nullptr; |
| ... | @@ -1081,36 +1081,6 @@ static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *blo | ... | @@ -1081,36 +1081,6 @@ static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *blo |
| 1081 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS()); | 1081 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS()); |
| 1082 | case BO_Assign: | 1082 | case BO_Assign: |
| 1083 | return trans_create_assign(c, result_used, block, stmt->getLHS(), stmt->getRHS()); | 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 | case BO_Comma: | 1084 | case BO_Comma: |
| 1115 | { | 1085 | { |
| 1116 | block = trans_create_node(c, NodeTypeBlock); | 1086 | block = trans_create_node(c, NodeTypeBlock); |
| ... | @@ -1123,112 +1093,181 @@ static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *blo | ... | @@ -1123,112 +1093,181 @@ static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *blo |
| 1123 | block->data.block.last_statement_is_result_expression = true; | 1093 | block->data.block.last_statement_is_result_expression = true; |
| 1124 | return block; | 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 | case BO_MulAssign: | 1096 | case BO_MulAssign: |
| 1134 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_MulAssign"); | | |
| 1135 | return nullptr; | | |
| 1136 | case BO_DivAssign: | 1097 | case BO_DivAssign: |
| 1137 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_DivAssign"); | | |
| 1138 | return nullptr; | | |
| 1139 | case BO_RemAssign: | 1098 | case BO_RemAssign: |
| 1140 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_RemAssign"); | | |
| 1141 | return nullptr; | | |
| 1142 | case BO_AddAssign: | 1099 | case BO_AddAssign: |
| 1143 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_AddAssign"); | | |
| 1144 | return nullptr; | | |
| 1145 | case BO_SubAssign: | 1100 | case BO_SubAssign: |
| 1146 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_SubAssign"); | | |
| 1147 | return nullptr; | | |
| 1148 | case BO_ShlAssign: | 1101 | case BO_ShlAssign: |
| 1149 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_ShlAssign"); | 1102 | case BO_ShrAssign: |
| 1150 | return nullptr; | 1103 | case BO_AndAssign: |
| 1151 | case BO_ShrAssign: { | 1104 | case BO_XorAssign: |
| 1152 | BinOpType bin_op = BinOpTypeBitShiftRight; | 1105 | case BO_OrAssign: |
| | 1106 | zig_unreachable(); |
| | 1107 | } |
| 1153 | | 1108 | |
| 1154 | const SourceLocation &rhs_location = stmt->getRHS()->getLocStart(); | 1109 | zig_unreachable(); |
| 1155 | AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location); | 1110 | } |
| 1156 | | 1111 | |
| 1157 | bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr(); | 1112 | static AstNode *trans_create_compound_assign_shift(Context *c, bool result_used, AstNode *block, CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) { |
| 1158 | if (!use_intermediate_casts && !result_used) { | 1113 | const SourceLocation &rhs_location = stmt->getRHS()->getLocStart(); |
| 1159 | // simple common case, where the C and Zig are identical: | 1114 | AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location); |
| 1160 | // lhs >>= rh* s | | |
| 1161 | AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue); | | |
| 1162 | if (lhs == nullptr) return nullptr; | | |
| 1163 | | 1115 | |
| 1164 | AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransRValue); | 1116 | bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr(); |
| 1165 | if (rhs == nullptr) return nullptr; | 1117 | if (!use_intermediate_casts && !result_used) { |
| 1166 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); | 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); | 1123 | AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransRValue); |
| 1169 | } else { | 1124 | if (rhs == nullptr) return nullptr; |
| 1170 | // need more complexity. worst case, this looks like this: | 1125 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); |
| 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 | | |
| 1178 | | 1126 | |
| 1179 | // TODO: avoid mess when we don't need the assignment value for chained assignments or anything. | 1127 | return trans_create_node_bin_op(c, lhs, assign_op, coerced_rhs); |
| 1180 | AstNode *child_block = trans_create_node(c, NodeTypeBlock); | 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; | 1138 | AstNode *child_block = trans_create_node(c, NodeTypeBlock); |
| 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); | | |
| 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); | 1149 | // *_ref = result_type(operation_type(*_ref) >> u5(rhs)); |
| 1194 | if (rhs == nullptr) return nullptr; | | |
| 1195 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); | | |
| 1196 | | 1150 | |
| 1197 | AstNode *assign_statement = trans_create_node_bin_op(c, | 1151 | AstNode *rhs = trans_expr(c, true, child_block, stmt->getRHS(), TransRValue); |
| 1198 | trans_create_node_prefix_op(c, PrefixOpDereference, | 1152 | if (rhs == nullptr) return nullptr; |
| 1199 | trans_create_node_symbol(c, tmp_var_name)), | 1153 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); |
| 1200 | BinOpTypeAssign, | 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 | trans_c_cast(c, rhs_location, | 1162 | trans_c_cast(c, rhs_location, |
| 1202 | stmt->getComputationResultType(), | 1163 | stmt->getComputationLHSType(), |
| 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( | | |
| 1215 | trans_create_node_prefix_op(c, PrefixOpDereference, | 1164 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1216 | trans_create_node_symbol(c, tmp_var_name))); | 1165 | trans_create_node_symbol(c, tmp_var_name))), |
| 1217 | child_block->data.block.last_statement_is_result_expression = true; | 1166 | bin_op, |
| 1218 | } | 1167 | coerced_rhs))); |
| 1219 | | 1168 | child_block->data.block.statements.append(assign_statement); |
| 1220 | return child_block; | 1169 | |
| 1221 | } | 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: | 1177 | |
| 1224 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_AndAssign"); | 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 | return nullptr; | 1247 | return nullptr; |
| 1226 | case BO_XorAssign: | 1248 | case BO_RemAssign: |
| 1227 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_XorAssign"); | 1249 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_RemAssign"); |
| 1228 | return nullptr; | 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 | case BO_OrAssign: | 1269 | case BO_OrAssign: |
| 1230 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_OrAssign"); | 1270 | return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignBitOr, BinOpTypeBinOr); |
| 1231 | return nullptr; | | |
| 1232 | case BO_PtrMemD: | 1271 | case BO_PtrMemD: |
| 1233 | case BO_PtrMemI: | 1272 | case BO_PtrMemI: |
| 1234 | case BO_Assign: | 1273 | case BO_Assign: |
| ... | @@ -1251,7 +1290,7 @@ static AstNode *trans_compound_assign_operator(Context *c, bool result_used, Ast | ... | @@ -1251,7 +1290,7 @@ static AstNode *trans_compound_assign_operator(Context *c, bool result_used, Ast |
| 1251 | case BO_LAnd: | 1290 | case BO_LAnd: |
| 1252 | case BO_LOr: | 1291 | case BO_LOr: |
| 1253 | case BO_Comma: | 1292 | case BO_Comma: |
| 1254 | zig_panic("compound assign expected to be handled by binary operator"); | 1293 | zig_unreachable(); |
| 1255 | } | 1294 | } |
| 1256 | | 1295 | |
| 1257 | zig_unreachable(); | 1296 | zig_unreachable(); |