1515#include " Scope.h"
1616#include " WhyInstructions.h"
1717
18- using Argument = std::variant<ExprPtr, VregPtr>;
19-
2018void compileCall (VregPtr destination, Function &function, ScopePtr scope, FunctionPtr fnptr,
21- std::initializer_list<Argument> arguments, const ASTLocation &location) {
19+ std::initializer_list<Argument> arguments, const ASTLocation &location, size_t multiplier ) {
2220 if (arguments.size () != fnptr->argumentCount ())
2321 throw GenericError (location, " Invalid number of arguments in call to " + fnptr->name + " at " +
2422 std::string (location) + " : " + std::to_string (arguments.size ()) + " (expected " +
@@ -32,10 +30,10 @@ void compileCall(VregPtr destination, Function &function, ScopePtr scope, Functi
3230 size_t i = 0 ;
3331
3432 for (const auto &argument: arguments) {
35- auto argument_register = function.precolored (i);
33+ auto argument_register = function.precolored (Why::argumentOffset + i);
3634 auto &fn_arg_type = *fnptr->getArgumentType (i);
37- if (std::holds_alternative<ExprPtr >(argument)) {
38- auto expr = std::get<ExprPtr >(argument);
35+ if (std::holds_alternative<Expr * >(argument)) {
36+ auto expr = std::get<Expr * >(argument);
3937 auto argument_type = expr->getType (scope);
4038 if (argument_type->isStruct ())
4139 throw GenericError (expr->getLocation (), " Structs cannot be directly passed to functions; "
@@ -67,8 +65,13 @@ void compileCall(VregPtr destination, Function &function, ScopePtr scope, Functi
6765 for (size_t i = arguments.size (); 0 < i; --i)
6866 function.add <StackPopInstruction>(function.precolored (Why::argumentOffset + i - 1 ))->setDebug (debug);
6967
70- if (!fnptr->returnType ->isVoid () && destination)
71- function.add <MoveInstruction>(function.precolored (Why::returnValueOffset), destination)->setDebug (debug);
68+ if (!fnptr->returnType ->isVoid () && destination) {
69+ auto r0 = function.precolored (Why::returnValueOffset);
70+ if (multiplier == 1 )
71+ function.add <MoveInstruction>(r0, destination)->setDebug (debug);
72+ else
73+ function.add <MultIInstruction>(r0, destination, multiplier)->setDebug (debug);
74+ }
7275}
7376
7477std::string stringify (const Expr *expr) {
@@ -396,29 +399,33 @@ std::ostream & operator<<(std::ostream &os, const Expr &expr) {
396399}
397400
398401void PlusExpr::compile (VregPtr destination, Function &function, ScopePtr scope, ssize_t multiplier) {
399- VregPtr left_var = function.newVar (), right_var = function.newVar ();
400402 auto left_type = left->getType (scope), right_type = right->getType (scope);
401-
402- if (left_type->isPointer () && right_type->isInt ()) {
403- if (multiplier != 1 )
404- throw GenericError (getLocation (), " Cannot multiply in pointer arithmetic PlusExpr" );
405- auto *left_subtype = dynamic_cast <PointerType &>(*left_type).subtype ;
406- left->compile (left_var, function, scope, 1 );
407- right->compile (right_var, function, scope, left_subtype->getSize ());
408- } else if (left_type->isInt () && right_type->isPointer ()) {
409- if (multiplier != 1 )
410- throw GenericError (getLocation (), " Cannot multiply in pointer arithmetic PlusExpr" );
411- auto *right_subtype = dynamic_cast <PointerType &>(*right_type).subtype ;
412- left->compile (left_var, function, scope, right_subtype->getSize ());
413- right->compile (right_var, function, scope, 1 );
414- } else if (!(*left_type && *right_type)) {
415- throw ImplicitConversionError (TypePtr (left_type->copy ()), TypePtr (right_type->copy ()), getLocation ());
403+ if (auto fnptr = function.program .getOperator ({left_type.get (), right_type.get ()}, CMMTOK_PLUS, getLocation ())) {
404+ compileCall (destination, function, scope, fnptr, {left.get (), right.get ()}, getLocation (), multiplier);
416405 } else {
417- left->compile (left_var, function, scope);
418- right->compile (right_var, function, scope);
419- }
406+ VregPtr left_var = function.newVar (), right_var = function.newVar ();
407+
408+ if (left_type->isPointer () && right_type->isInt ()) {
409+ if (multiplier != 1 )
410+ throw GenericError (getLocation (), " Cannot multiply in pointer arithmetic PlusExpr" );
411+ auto *left_subtype = dynamic_cast <PointerType &>(*left_type).subtype ;
412+ left->compile (left_var, function, scope, 1 );
413+ right->compile (right_var, function, scope, left_subtype->getSize ());
414+ } else if (left_type->isInt () && right_type->isPointer ()) {
415+ if (multiplier != 1 )
416+ throw GenericError (getLocation (), " Cannot multiply in pointer arithmetic PlusExpr" );
417+ auto *right_subtype = dynamic_cast <PointerType &>(*right_type).subtype ;
418+ left->compile (left_var, function, scope, right_subtype->getSize ());
419+ right->compile (right_var, function, scope, 1 );
420+ } else if (!(*left_type && *right_type)) {
421+ throw ImplicitConversionError (TypePtr (left_type->copy ()), TypePtr (right_type->copy ()), getLocation ());
422+ } else {
423+ left->compile (left_var, function, scope, multiplier);
424+ right->compile (right_var, function, scope, multiplier);
425+ }
420426
421- function.add <AddRInstruction>(left_var, right_var, destination)->setDebug (*this );
427+ function.add <AddRInstruction>(left_var, right_var, destination)->setDebug (*this );
428+ }
422429}
423430
424431std::optional<ssize_t > PlusExpr::evaluate (ScopePtr scope) const {
0 commit comments