Example #1
0
        public override AstNode Visit(BinaryOperation node)
        {
            // Begin the node.
            builder.BeginNode(node);

            // Get the expressions.
            Expression left = node.GetLeftExpression();
            Expression right = node.GetRightExpression();

            // Get the types.
            IChelaType leftType = left.GetNodeType();
            IChelaType rightType = right.GetNodeType();
            IChelaType coercionType = node.GetCoercionType();
            IChelaType secondCoercion = node.GetSecondCoercion();
            IChelaType operationType = node.GetOperationType();
            IChelaType destType = node.GetNodeType();

            // Special pipeline for operator overloading.
            Function overload = node.GetOverload();
            if(overload != null)
            {
                FunctionType overloadType = overload.GetFunctionType();
                coercionType = overloadType.GetArgument(0);
                secondCoercion = overloadType.GetArgument(1);

                // Send first the left operand.
                left.Accept(this);
                if(leftType != coercionType)
                    Cast(node, left.GetNodeValue(), leftType, coercionType);

                // Now send the right operand.
                right.Accept(this);
                if(rightType != secondCoercion)
                    Cast(node, right.GetNodeValue(), rightType, secondCoercion);

                // Perform the call.
                builder.CreateCall(overload, 2);

                // Return the node.
                return builder.EndNode();
            }

            // Send the left operand.
            left.Accept(this);
            if(leftType != coercionType)
                Cast(node, left.GetNodeValue(), leftType, coercionType);

            // Short circuit operations has special evaluation orders.
            if(node.GetOperation() == BinaryOperation.OpLAnd ||
               node.GetOperation() == BinaryOperation.OpLOr)
            {
                BasicBlock continueBlock = CreateBasicBlock();
                continueBlock.SetName("shc");

                BasicBlock stopBlock = CreateBasicBlock();
                stopBlock.SetName("shs");

                BasicBlock mergeBlock = CreateBasicBlock();
                mergeBlock.SetName("shm");

                // Perform left branch.
                if(node.GetOperation() == BinaryOperation.OpLAnd)
                    builder.CreateBr(continueBlock, stopBlock);
                else
                    builder.CreateBr(stopBlock, continueBlock);

                // Build stop.
                builder.SetBlock(stopBlock);
                builder.CreateLoadBool(node.GetOperation() == BinaryOperation.OpLOr);
                builder.CreateJmp(mergeBlock);

                // Build continue block.
                builder.SetBlock(continueBlock);

                // Send the right operand verbatim.
                right.Accept(this);
                if(rightType != secondCoercion)
                    Cast(node, right.GetNodeValue(), rightType, secondCoercion);
                builder.CreateJmp(mergeBlock);

                // Continue with the control flow.
                builder.SetBlock(mergeBlock);
                return builder.EndNode();
            }

            // Send the right operand.
            right.Accept(this);
            if(rightType != secondCoercion)
                Cast(node, right.GetNodeValue(), rightType, secondCoercion);

            switch(node.GetOperation())
            {
            case BinaryOperation.OpAdd:
                builder.CreateAdd();
                break;
            case BinaryOperation.OpSub:
                builder.CreateSub();
                break;
            case BinaryOperation.OpMul:
                if(node.IsMatrixMul())
                    builder.CreateMatMul();
                else
                    builder.CreateMul();
                break;
            case BinaryOperation.OpDiv:
                builder.CreateDiv();
                break;
            case BinaryOperation.OpMod:
                builder.CreateMod();
                break;
            case BinaryOperation.OpBitAnd:
                builder.CreateAnd();
                break;
            case BinaryOperation.OpBitOr:
                builder.CreateOr();
                break;
            case BinaryOperation.OpBitXor:
                builder.CreateXor();
                break;
            case BinaryOperation.OpBitLeft:
                builder.CreateShLeft();
                break;
            case BinaryOperation.OpBitRight:
                builder.CreateShRight();
                break;
            case BinaryOperation.OpLT:
                builder.CreateCmpLT();
                break;
            case BinaryOperation.OpGT:
                builder.CreateCmpGT();
                break;
            case BinaryOperation.OpEQ:
                builder.CreateCmpEQ();
                break;
            case BinaryOperation.OpNEQ:
                builder.CreateCmpNE();
                break;
            case BinaryOperation.OpLEQ:
                builder.CreateCmpLE();
                break;
            case BinaryOperation.OpGEQ:
                builder.CreateCmpGE();
                break;
            case BinaryOperation.OpLAnd:
            case BinaryOperation.OpLOr:
                // Shouldn't reach here.
                break;
            }

            // Cast the result.
            if(operationType != destType)
                Cast(node, null, operationType, destType);

            return builder.EndNode();
        }