-/*-----------------------------------------------------------------*/
-/* geniCodeDivision - gen intermediate code for division */
-/*-----------------------------------------------------------------*/
-operand *geniCodeDivision (operand *left, operand *right)
-{
- iCode *ic ;
- int p2 = 0;
- link *resType;
- link *rtype = operandType(right);
- link *retype= getSpec(rtype);
- link *ltype = operandType(left);
- link *letype= getSpec(ltype);
-
- resType = computeType (ltype,rtype) ;
- left = geniCodeCast(resType,left,TRUE);
- right= geniCodeCast(resType,right,TRUE);
-
- /* if the right is a literal & power of 2 */
- /* then make it a right shift */
- if (IS_LITERAL(retype) &&
- !IS_FLOAT(letype) &&
- (p2 = powof2 ((unsigned long)
- floatFromVal(right->operand.valOperand))))
- ic = newiCode(RIGHT_OP, left,operandFromLit(p2)); /* right shift */
- else {
- ic = newiCode('/',left,right); /* normal division */
- /* if the size left or right > 1 then support routine */
- if (getSize(ltype) > 1 || getSize(rtype) > 1)
- ic->supportRtn = 1;
- }
- IC_RESULT(ic) = newiTempOperand(resType,0);
-
- ADDTOCHAIN(ic);
- return IC_RESULT(ic) ;
-}
-/*-----------------------------------------------------------------*/
-/* geniCodeModulus - gen intermediate code for modulus */
-/*-----------------------------------------------------------------*/
-operand *geniCodeModulus (operand *left, operand *right)
-{
- iCode *ic ;
- link *resType;
- LRTYPE ;
-
- /* if they are both literal then we know the result */
- if (IS_LITERAL(letype) && IS_LITERAL(retype))
- return operandFromValue (valMod(left->operand.valOperand,
- right->operand.valOperand));
-
- resType = computeType (ltype,rtype) ;
- left = geniCodeCast(resType,left,TRUE);
- right= geniCodeCast(resType,right,TRUE);
-
- /* now they are the same size */
- ic = newiCode('%',left,right);
-
- /* if the size left or right > 1 then support routine */
- if (getSize(ltype) > 1 || getSize(rtype) > 1)
+ return ctype;
+ }
+
+ *op1 = usualUnaryConversions (*op1);
+ *op2 = usualUnaryConversions (*op2);
+
+ /* Try to make the two operands of the same type, following
+ * the "usual binary conversions" promotion rules.
+ *
+ * NB: floating point types are not yet properly handled; we
+ * follow the "classic" behavior.
+ */
+
+ if (IS_FLOAT (operandType (*op1)) || IS_FLOAT (operandType (*op2)))
+ {
+ return newFloatLink ();
+ }
+
+ if (!IS_INTEGRAL (operandType (*op1)) || !IS_INTEGRAL (operandType (*op2)))
+ {
+ /* if either is not an integer type, we're done. */
+ return copyLinkChain (operandType (*op1)); /* Punt! we should never get here. */
+ }
+
+ /* If either is an unsigned long, make sure both are. */
+ if (SPEC_USIGN (operandType (*op1)) && IS_LONG (operandType (*op1)))
+ {
+ if (!SPEC_USIGN (operandType (*op2)) || !IS_LONG (operandType (*op2)))
+ {
+ *op2 = geniCodeCast (ULONGTYPE, *op2, TRUE);
+ }
+ return copyLinkChain (operandType (*op1));
+ }
+
+ if (SPEC_USIGN (operandType (*op2)) && IS_LONG (operandType (*op2)))
+ {
+ if (!SPEC_USIGN (operandType (*op1)) || !IS_LONG (operandType (*op1)))
+ {
+ *op1 = geniCodeCast (ULONGTYPE, *op1, TRUE);
+ }
+ return copyLinkChain (operandType (*op2));
+ }
+
+ /* Next, if one is long and the other is int (signed or un),
+ * cast both to long.
+ *
+ * Note that because in our environment a long can hold all
+ * the values of an unsigned int, the "long/unsigned int" pair
+ * in the ANSI conversion table is unnecessary; this test
+ * handles that case implicitly.
+ */
+ if (IS_LONG (operandType (*op1)))
+ {
+ /* NB: because of the unary conversions, op2 cannot
+ * be smaller than int. Therefore, if it is not
+ * long, it is a regular int.
+ */
+ if (!IS_LONG (operandType (*op2)))
+ {
+ *op2 = geniCodeCast (LONGTYPE, *op2, TRUE);
+ }
+ return copyLinkChain (operandType (*op1));
+ }
+
+ if (IS_LONG (operandType (*op2)))
+ {
+ /* NB: because of the unary conversions, op2 cannot
+ * be smaller than int. Therefore, if it is not
+ * long, it is a regular int.
+ */
+ if (!IS_LONG (operandType (*op1)))
+ {
+ *op1 = geniCodeCast (LONGTYPE, *op1, TRUE);
+ }
+ return copyLinkChain (operandType (*op2));
+ }
+
+ /* All right, neither is long; they must both be integers.
+
+ * Only remaining issue is signed vs. unsigned; if one is unsigned
+ * and the other isn't, convert both to unsigned.
+ */
+ if (SPEC_USIGN (operandType (*op1)))
+ {
+ if (!SPEC_USIGN (operandType (*op2)))
+ {
+ *op2 = geniCodeCast (UINTTYPE, *op2, TRUE);
+ }
+ return copyLinkChain (operandType (*op1));
+ }
+
+ if (SPEC_USIGN (operandType (*op2)))
+ {
+ if (!SPEC_USIGN (operandType (*op1)))
+ {
+ *op1 = geniCodeCast (UINTTYPE, *op1, TRUE);
+ }
+ return copyLinkChain (operandType (*op2));
+ }
+
+ /* Done! */
+ return copyLinkChain (operandType (*op1));
+}
+
+
+/*-----------------------------------------------------------------*/
+/* geniCodeValueAtAddress - generate intermeditate code for value */
+/* at address */
+/*-----------------------------------------------------------------*/
+operand *
+geniCodeRValue (operand * op, bool force)
+{
+ iCode *ic;
+ sym_link *type = operandType (op);
+ sym_link *etype = getSpec (type);
+
+ /* if this is an array & already */
+ /* an address then return this */
+ if (IS_AGGREGATE (type) ||
+ (IS_PTR (type) && !force && !op->isaddr))
+ return operandFromOperand (op);
+
+ /* if this is not an address then must be */
+ /* rvalue already so return this one */
+ if (!op->isaddr)
+ return op;
+
+ /* if this is not a temp symbol then */
+ if (!IS_ITEMP (op) &&
+ !force &&
+ !IN_FARSPACE (SPEC_OCLS (etype)))
+ {
+ op = operandFromOperand (op);
+ op->isaddr = 0;
+ return op;
+ }
+
+ if (IS_SPEC (type) &&
+ IS_TRUE_SYMOP (op) &&
+ (!IN_FARSPACE (SPEC_OCLS (etype)) || TARGET_IS_DS390))
+ {
+ op = operandFromOperand (op);
+ op->isaddr = 0;
+ return op;
+ }
+
+ ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
+ if (IS_PTR (type) && op->isaddr && force)
+ type = type->next;
+
+ type = copyLinkChain (type);
+
+ IC_RESULT (ic) = newiTempOperand (type, 1);
+ IC_RESULT (ic)->isaddr = 0;
+
+/* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
+
+ /* if the right is a symbol */
+ if (op->type == SYMBOL)
+ IC_RESULT (ic)->operand.symOperand->args =
+ op->operand.symOperand->args;
+ ADDTOCHAIN (ic);
+
+ return IC_RESULT (ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* geniCodeCast - changes the value from one type to another */
+/*-----------------------------------------------------------------*/
+operand *
+geniCodeCast (sym_link * type, operand * op, bool implicit)
+{
+ iCode *ic;
+ sym_link *optype;
+ sym_link *opetype = getSpec (optype = operandType (op));
+ sym_link *restype;
+
+ /* one of them has size zero then error */
+ if (IS_VOID (optype))
+ {
+ werror (E_CAST_ZERO);
+ return op;
+ }
+
+ /* if the operand is already the desired type then do nothing */
+ if (checkType (type, optype) == 1)
+ return op;
+
+ /* if this is a literal then just change the type & return */
+ if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
+ return operandFromValue (valCastLiteral (type,
+ operandLitValue (op)));
+
+ /* if casting to some pointer type &&
+ the destination is not a generic pointer
+ then give a warning : (only for implicit casts) */
+ if (IS_PTR (optype) && implicit &&
+ (DCL_TYPE (optype) != DCL_TYPE (type)) &&
+ !IS_GENPTR (type))
+ {
+ werror (E_INCOMPAT_CAST);
+ werror (E_CONTINUE, "from type '");
+ printTypeChain (optype, stderr);
+ fprintf (stderr, "' to type '");
+ printTypeChain (type, stderr);
+ fprintf (stderr, "'\n");
+ }
+
+ /* if they are the same size create an assignment */
+ if (getSize (type) == getSize (optype) &&
+ !IS_BITFIELD (type) &&
+ !IS_FLOAT (type) &&
+ !IS_FLOAT (optype) &&
+ ((IS_SPEC (type) && IS_SPEC (optype)) ||
+ (!IS_SPEC (type) && !IS_SPEC (optype))))
+ {
+
+ ic = newiCode ('=', NULL, op);
+ IC_RESULT (ic) = newiTempOperand (type, 0);
+ SPIL_LOC (IC_RESULT (ic)) =
+ (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
+ IC_RESULT (ic)->isaddr = 0;
+ }
+ else
+ {
+ ic = newiCode (CAST, operandFromLink (type),
+ geniCodeRValue (op, FALSE));
+
+ IC_RESULT (ic) = newiTempOperand (type, 0);
+ }
+
+ /* preserve the storage class & output class */
+ /* of the original variable */
+ restype = getSpec (operandType (IC_RESULT (ic)));
+ SPEC_SCLS (restype) = SPEC_SCLS (opetype);
+ SPEC_OCLS (restype) = SPEC_OCLS (opetype);
+
+ ADDTOCHAIN (ic);
+ return IC_RESULT (ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* geniCodeLabel - will create a Label */
+/*-----------------------------------------------------------------*/
+void
+geniCodeLabel (symbol * label)
+{
+ iCode *ic;
+
+ ic = newiCodeLabelGoto (LABEL, label);
+ ADDTOCHAIN (ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* geniCodeGoto - will create a Goto */
+/*-----------------------------------------------------------------*/
+void
+geniCodeGoto (symbol * label)
+{
+ iCode *ic;
+
+ ic = newiCodeLabelGoto (GOTO, label);
+ ADDTOCHAIN (ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* geniCodeMultiply - gen intermediate code for multiplication */
+/*-----------------------------------------------------------------*/
+operand *
+geniCodeMultiply (operand * left, operand * right,int resultIsInt)
+{
+ iCode *ic;
+ int p2 = 0;
+ int saveOption=0;
+ sym_link *resType;
+ LRTYPE;
+
+ /* if they are both literal then we know the result */
+ if (IS_LITERAL (letype) && IS_LITERAL (retype))
+ return operandFromValue (valMult (left->operand.valOperand,
+ right->operand.valOperand));
+
+ if (IS_LITERAL(retype)) {
+ p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
+ }
+
+ if (resultIsInt)
+ {
+ saveOption = options.ANSIint;
+ options.ANSIint = 0;
+ }
+ resType = usualBinaryConversions (&left, &right);
+#if 1
+ rtype = operandType (right);
+ retype = getSpec (rtype);
+ ltype = operandType (left);
+ letype = getSpec (ltype);
+#endif
+ if (resultIsInt)
+ {
+ options.ANSIint = saveOption;
+ SPEC_NOUN(getSpec(resType))=V_INT;
+ SPEC_SHORT(getSpec(resType))=0;
+ }
+
+ /* if the right is a literal & power of 2 */
+ /* then make it a left shift */
+ /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
+ efficient in most cases than 2 bytes result = 2 bytes << literal
+ if port has 1 byte muldiv */
+ if (p2 && !IS_FLOAT (letype) &&
+ !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
+ (port->muldiv.native_below == 1)))
+ {
+ if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
+ {
+ /* LEFT_OP need same size for left and result, */
+ left = geniCodeCast (resType, left, TRUE);
+ ltype = operandType (left);
+ }
+ ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
+ }
+ else
+ {
+ ic = newiCode ('*', left, right); /* normal multiplication */
+ /* if the size left or right > 1 then support routine */
+ if (getSize (ltype) > 1 || getSize (rtype) > 1)