コード例 #1
0
AsmBlock* NStructureResolutionOperator::compile(AsmGenerator& context)
{
    AsmBlock* block = new AsmBlock();

    // Add file and line information.
    *block << this->getFileAndLineState();

    // Use our reference function to generate the location.
    AsmBlock* expr = this->reference(context);

    IType* fieldType = this->m_structType->getStructFieldType(this->rhs.name);

    // return the value of the field
    *block <<   *expr;
    *block <<   *(fieldType->loadFromRef(context, 'A', 'A'));
    delete expr;

    return block;
}
コード例 #2
0
ファイル: NPostIncDec.cpp プロジェクト: Beliaar/DCPUToolchain
AsmBlock* NPostIncDec::compile(AsmGenerator& context)
{
	AsmBlock* block = new AsmBlock();

	// We have to compile and reference, but the reference function allready compiles
	// and evaluates, thus we use the reference not the value.
	AsmBlock* reference = this->expr.reference(context);
	*block <<   *reference;
	delete reference;

	// get type
	IType* exprType = this->expr.getExpressionType(context);

	// Type checking
	if ((!exprType->isPointer()) && (!exprType->isBasicType()))
	{
		throw new CompilerException(this->line, this->file,
					    "Invalid operand to post increase/decrease operation. (have '"
					    + exprType->getName() + "')");
	}

	*block <<	"	SET B, A" << std::endl;
	// return old value in A
	*block << *(exprType->loadFromRef(context, 'B', 'A'));

	// increment/decrement
	switch (this->op)
	{
		case INCREMENT:
			*block << *(exprType->inc(context, 'B'));
			break;

		case DECREMENT:
			*block << *(exprType->dec(context, 'B'));
			break;

		default:
			throw new CompilerException(this->line, this->file, "Unknown Post-Increase-Decrease operation requested.");
	}

	return block;
}
コード例 #3
0
ファイル: NIdentifier.cpp プロジェクト: Beliaar/DCPUToolchain
AsmBlock* NIdentifier::compile(AsmGenerator& context)
{
	AsmBlock* block = new AsmBlock();

	// Add file and line information.
	*block << this->getFileAndLineState();

	// Get the position and type of the variable.
	TypePosition result = context.m_CurrentFrame->getPositionOfVariable(this->name);
	IType* type = context.m_CurrentFrame->getTypeOfVariable(this->name);

	if (!result.isFound())
		throw new CompilerException(this->line, this->file, "The variable '" + this->name + "' was not found in the scope.");

	if (result.isFunction())
		throw new CompilerException(this->line, this->file, "Can not get value representation of function '" + this->name + "'; did you want a reference instead?");

	// Load the value of the variable into register A.
	*block << result.pushAddress('I');
	*block << *(type->loadFromRef(context, 'I', 'A'));
	//*block <<	"	SET A, [I]" << std::endl;

	return block;
}
コード例 #4
0
ファイル: NAssignment.cpp プロジェクト: jathd/DCPUToolchain
AsmBlock* NAssignment::compile(AsmGenerator& context)
{
    AsmBlock* block = new AsmBlock();

    // Add file and line information.
    *block << this->getFileAndLineState();

    // When an assignment expression is referenced, the memory
    // address of the target goes into A.
    AsmBlock* las = this->lhs.reference(context);
    *block << *las;

    // get lhs type
    IType* lhsType = this->lhs.getExpressionType(context);

    // push memory address
    *block <<   "   SET PUSH, A" << std::endl;
    delete las;

    // handle regular assignment as special case
    if (this->op == ASSIGN_EQUAL)
    {
        // When an expression is evaluated, the result goes into the A register.
        AsmBlock* rhs = this->rhs.compile(context);
        *block <<   *rhs;
        delete rhs;

        // get rhs type
        IType* rhsType = this->rhs.getExpressionType(context);

        // cast to rhs to lhs type
        if (rhsType->implicitCastable(context, lhsType))
        {
            *block << *(rhsType->implicitCast(context, lhsType, 'A'));
        }
        else
        {
            throw new CompilerException(this->line, this->file,
                                        "Unable to implicitly cast '" + rhsType->getName()
                                        + "' to '" + lhsType->getName() + "'");
        }

        // Pop the address of lhs into B
        if (context.isAssemblerDebug())
        {
            // Put the value into B and clear the
            // stack positions as we do so.
            *block <<   "   SET B, PEEK" << std::endl;
            *block <<   "   SET PEEK, 0" << std::endl;
            *block <<   "   ADD SP, 1" << std::endl;
        }
        else
        {
            // Not debugging, put the values into B.
            *block <<   "   SET B, POP" << std::endl;
        }

        // save the value A to [B]
        *block << *(lhsType->saveToRef(context, 'A', 'B'));
    }
    else
    {
        // When an expression is evaluated, the result goes into the A register.
        AsmBlock* rhs = this->rhs.compile(context);
        *block <<   *rhs;
        delete rhs;

        // get rhs type
        IType* rhsType = this->rhs.getExpressionType(context);

        // Check if both types are of a basic type
        bool isPointerOp = false;
        if (lhsType->isPointer() && rhsType->isBasicType())
        {
            // pointer op: p += i, or p -= i
            isPointerOp = true;
            if (this->op != ASSIGN_ADD && this->op != ASSIGN_SUBTRACT)
            {
                throw new CompilerException(this->line, this->file,
                                            "Invalid operands to assign operation. (have '"
                                            + lhsType->getName() + "' and '" + rhsType->getName() + "')");
            }
        }
        else if ((!rhsType->isBasicType()) || (!lhsType->isBasicType()))
        {
            throw new CompilerException(this->line, this->file,
                                        "Invalid operands to assign operation. (have '"
                                        + lhsType->getName() + "' and '" + rhsType->getName() + "')");
        }

        if (!isPointerOp)
        {
            // cast to rhs to lhs type
            if (rhsType->implicitCastable(context, lhsType))
            {
                *block << *(rhsType->implicitCast(context, lhsType, 'A'));
            }
            else
            {
                throw new CompilerException(this->line, this->file,
                                            "Unable to implicitly cast '" + rhsType->getName()
                                            + "' to '" + lhsType->getName() + "'");
            }
        }

        // move rhs over to register B
        *block <<   "   SET B, A" << std::endl;

        // get referenced value and put it in A
        *block <<   "   SET A, PEEK" << std::endl;
        *block << *(lhsType->loadFromRef(context, 'A', 'A'));

        // Now do the appropriate operation.
        // TODO a lot of assignment operations are missing !!
        // TODO type specific ops
        switch (this->op)
        {
            case ASSIGN_ADD:
                *block << *(lhsType->add(context, 'A', 'B'));
                break;

            case ASSIGN_SUBTRACT:
                *block << *(lhsType->sub(context, 'A', 'B'));
                break;

            case ASSIGN_MULTIPLY:
                *block << *(lhsType->mul(context, 'A', 'B'));
                break;

            case ASSIGN_DIVIDE:
                *block << *(lhsType->div(context, 'A', 'B'));
                break;

            case ASSIGN_MOD:
                *block << *(lhsType->mod(context, 'A', 'B'));
                break;

            case ASSIGN_BAND:
                *block << *(lhsType->band(context, 'A', 'B'));
                break;

            case ASSIGN_BOR:
                *block << *(lhsType->bor(context, 'A', 'B'));
                break;

            case ASSIGN_BXOR:
                *block << *(lhsType->bxor(context, 'A', 'B'));
                break;

            case ASSIGN_SHL:
                *block << *(lhsType->shl(context, 'A', 'B'));
                break;

            case ASSIGN_SHR:
                *block << *(lhsType->shr(context, 'A', 'B'));
                break;

            default:
                throw new CompilerException(this->line, this->file, "Unknown assignment operation requested.");
        }

        // Pop reference from stack
        // If debugging, clear the value as we POP them.
        if (context.isAssemblerDebug())
        {
            // Put the value into B and clear the
            // stack position as we do so.
            *block <<   "   SET B, PEEK" << std::endl;
            *block <<   "   SET PEEK, 0" << std::endl;
            *block <<   "   ADD SP, 1" << std::endl;
        }
        else
        {
            // Not debugging, put the values into B.
            *block <<   "   SET B, POP" << std::endl;
        }

        // Move the value into the target address.
        *block << *(lhsType->saveToRef(context, 'A', 'B'));
    }
    return block;
}