TType *TCodeGenerator::EmitSimpleExpression(void) { TType *pOperandType; // ptr to operand's type TType *pResultType; // ptr to result type TTokenCode op; // operator TTokenCode unaryOp = tcPlus; // unary operator //--Unary + or - if (TokenIn(token, tlUnaryOps)) { unaryOp = token; GetToken(); } //--Emit code for the first term. pResultType = EmitTerm(); //--If there was a unary operator, negate in integer value in ax //--with the neg instruction, or negate a real value in dx:ax //--by calling _FloatNegate. if (unaryOp == tcMinus) { if (pResultType->Base() == pIntegerType) Emit1(neg, Reg(ax)) else if (pResultType == pRealType) { EmitPushOperand(pResultType); Emit1(call, NameLit(FLOAT_NEGATE)); Emit2(add, Reg(sp), IntegerLit(4)); } } //--Loop to execute subsequent additive operators and terms. while (TokenIn(token, tlAddOps)) { op = token; pResultType = pResultType->Base(); EmitPushOperand(pResultType); GetToken(); pOperandType = EmitTerm()->Base(); //--Perform the operation, and push the resulting value //--onto the stack. if (op == tcOR) { //--boolean OR boolean => boolean //--ax = ax OR dx Emit1(pop, Reg(dx)); Emit2(or, Reg(ax), Reg(dx)); pResultType = pBooleanType; } else if ((pResultType == pIntegerType) && (pOperandType == pIntegerType)) { //--integer +|- integer => integer Emit1(pop, Reg(dx)); if (op == tcPlus) Emit2(add, Reg(ax), Reg(dx)) else { Emit2(sub, Reg(dx), Reg(ax)); Emit2(mov, Reg(ax), Reg(dx)); } pResultType = pIntegerType; } else {
TType *TCodeGenerator::EmitExpression(void) { TType *pOperand1Type; // ptr to first operand's type TType *pOperand2Type; // ptr to second operand's type TType *pResultType; // ptr to result type TTokenCode op; // operator TInstruction jumpOpcode; // jump instruction opcode int jumpLabelIndex; // assembly jump label index //--Emit code for the first simple expression. pResultType = EmitSimpleExpression(); //--If we now see a relational operator, //--emit code for the second simple expression. if (TokenIn(token, tlRelOps)) { EmitPushOperand(pResultType); op = token; pOperand1Type = pResultType->Base(); GetToken(); pOperand2Type = EmitSimpleExpression()->Base(); //--Perform the operation, and push the resulting value //--onto the stack. if ( ((pOperand1Type == pIntegerType) && (pOperand2Type == pIntegerType)) || ((pOperand1Type == pCharType) && (pOperand2Type == pCharType)) || (pOperand1Type->form == fcEnum)) { //--integer <op> integer //--boolean <op> boolean //--char <op> char //--enum <op> enum //--Compare dx (operand 1) to ax (operand 2). Emit1(pop, Reg(dx)); Emit2(cmp, Reg(dx), Reg(ax)); } else if ((pOperand1Type == pRealType) || (pOperand2Type == pRealType)) { //--real <op> real //--real <op> integer //--integer <op> real //--Convert the integer operand to real. //--Call _FloatCompare to do the comparison, which //--returns -1 (less), 0 (equal), or +1 (greater). EmitPushOperand(pOperand2Type); EmitPromoteToReal(pOperand1Type, pOperand2Type); Emit1(call, NameLit(FLOAT_COMPARE)); Emit2(add, Reg(sp), IntegerLit(8)); Emit2(cmp, Reg(ax), IntegerLit(0)); } else { //--string <op> string //--Compare the string pointed to by si (operand 1) //--to the string pointed to by di (operand 2). Emit1(pop, Reg(di)); Emit1(pop, Reg(si)); Emit2(mov, Reg(ax), Reg(ds)); Emit2(mov, Reg(es), Reg(ax)); Emit0(cld); Emit2(mov, Reg(cx), IntegerLit(pOperand1Type->array.elmtCount)); Emit0(repe_cmpsb); } Emit2(mov, Reg(ax), IntegerLit(1)); // default: load 1 switch (op) { case tcLt: jumpOpcode = jl; break; case tcLe: jumpOpcode = jle; break; case tcEqual: jumpOpcode = je; break; case tcNe: jumpOpcode = jne; break; case tcGe: jumpOpcode = jge; break; case tcGt: jumpOpcode = jg; break; } jumpLabelIndex = ++asmLabelIndex; Emit1(jumpOpcode, Label(STMT_LABEL_PREFIX, jumpLabelIndex)); Emit2(sub, Reg(ax), Reg(ax)); // load 0 if false EmitStatementLabel(jumpLabelIndex); pResultType = pBooleanType; } return pResultType; }