const ACTION: INT_ABS is action "INT_ABS";
const ACTION: INT_ADD is action "INT_ADD";
const ACTION: INT_ADD_ASSIGN is action "INT_ADD_ASSIGN";
const ACTION: INT_BINOM is action "INT_BINOM";
const ACTION: INT_BIT_LENGTH is action "INT_BIT_LENGTH";
const ACTION: INT_BYTES_BE_2_INT is action "INT_BYTES_BE_2_INT";
const ACTION: INT_BYTES_BE_2_UINT is action "INT_BYTES_BE_2_UINT";
const ACTION: INT_BYTES_BE_SIGNED is action "INT_BYTES_BE_SIGNED";
const ACTION: INT_BYTES_BE_UNSIGNED is action "INT_BYTES_BE_UNSIGNED";
const ACTION: INT_BYTES_LE_2_INT is action "INT_BYTES_LE_2_INT";
const ACTION: INT_BYTES_LE_2_UINT is action "INT_BYTES_LE_2_UINT";
const ACTION: INT_BYTES_LE_SIGNED is action "INT_BYTES_LE_SIGNED";
const ACTION: INT_BYTES_LE_UNSIGNED is action "INT_BYTES_LE_UNSIGNED";
const ACTION: INT_CMP is action "INT_CMP";
const ACTION: INT_CPY is action "INT_CPY";
const ACTION: INT_DECR is action "INT_DECR";
const ACTION: INT_DIV is action "INT_DIV";
const ACTION: INT_EQ is action "INT_EQ";
const ACTION: INT_FACT is action "INT_FACT";
const ACTION: INT_GE is action "INT_GE";
const ACTION: INT_GT is action "INT_GT";
const ACTION: INT_HASHCODE is action "INT_HASHCODE";
const ACTION: INT_ICONV1 is action "INT_ICONV1";
const ACTION: INT_ICONV3 is action "INT_ICONV3";
const ACTION: INT_INCR is action "INT_INCR";
const ACTION: INT_LE is action "INT_LE";
const ACTION: INT_LOG10 is action "INT_LOG10";
const ACTION: INT_LOG2 is action "INT_LOG2";
const ACTION: INT_LOWEST_SET_BIT is action "INT_LOWEST_SET_BIT";
const ACTION: INT_LPAD0 is action "INT_LPAD0";
const ACTION: INT_LSHIFT is action "INT_LSHIFT";
const ACTION: INT_LSHIFT_ASSIGN is action "INT_LSHIFT_ASSIGN";
const ACTION: INT_LT is action "INT_LT";
const ACTION: INT_MDIV is action "INT_MDIV";
const ACTION: INT_MOD is action "INT_MOD";
const ACTION: INT_MULT is action "INT_MULT";
const ACTION: INT_MULT_ASSIGN is action "INT_MULT_ASSIGN";
const ACTION: INT_NE is action "INT_NE";
const ACTION: INT_NEGATE is action "INT_NEGATE";
const ACTION: INT_N_BYTES_BE_SIGNED is action "INT_N_BYTES_BE_SIGNED";
const ACTION: INT_N_BYTES_BE_UNSIGNED is action "INT_N_BYTES_BE_UNSIGNED";
const ACTION: INT_N_BYTES_LE_SIGNED is action "INT_N_BYTES_LE_SIGNED";
const ACTION: INT_N_BYTES_LE_UNSIGNED is action "INT_N_BYTES_LE_UNSIGNED";
const ACTION: INT_ODD is action "INT_ODD";
const ACTION: INT_PARSE1 is action "INT_PARSE1";
const ACTION: INT_PLUS is action "INT_PLUS";
const ACTION: INT_POW is action "INT_POW";
const ACTION: INT_PRED is action "INT_PRED";
const ACTION: INT_radix is action "INT_radix";
const ACTION: INT_RADIX is action "INT_RADIX";
const ACTION: INT_RAND is action "INT_RAND";
const ACTION: INT_REM is action "INT_REM";
const ACTION: INT_RSHIFT is action "INT_RSHIFT";
const ACTION: INT_RSHIFT_ASSIGN is action "INT_RSHIFT_ASSIGN";
const ACTION: INT_SBTR is action "INT_SBTR";
const ACTION: INT_SBTR_ASSIGN is action "INT_SBTR_ASSIGN";
const ACTION: INT_SQRT is action "INT_SQRT";
const ACTION: INT_STR is action "INT_STR";
const ACTION: INT_SUCC is action "INT_SUCC";
const ACTION: INT_VALUE is action "INT_VALUE";
const proc: int_prototypes (inout file: c_prog) is func
begin
declareExtern(c_prog, "void setupRand (void);");
if inlineFunctions and
(ccConf.INTTYPE_SIZE = 32 and ccConf.UINT64TYPE <> "") or
(ccConf.INTTYPE_SIZE = 64 and ccConf.UINT128TYPE <> "") then
if ccConf.INTTYPE_SIZE = 32 then
declareExtern(c_prog, ccConf.UINT64TYPE <& " seed;");
elsif ccConf.INTTYPE_SIZE = 64 then
declareExtern(c_prog, ccConf.UINT128TYPE <& " seed;");
end if;
writeln(c_prog, "#define RAND_MULTIPLIER " <& ccConf.RAND_MULTIPLIER);
writeln(c_prog, "#define RAND_INCREMENT " <& ccConf.RAND_INCREMENT);
writeln(c_prog, "#define uintRand() \
\(seed = seed * RAND_MULTIPLIER + RAND_INCREMENT, \
\(uintType) (seed >> " <&
ccConf.INTTYPE_SIZE <& "))");
writeln(c_prog, "#define uintRandMantissa() \
\(seed = seed * RAND_MULTIPLIER + RAND_INCREMENT, \
\(uintType) (seed >> " <&
2 * ccConf.INTTYPE_SIZE - ccConf.FLOATTYPE_MANTISSA_BITS <& "))");
if ccConf.STMT_BLOCK_IN_PARENTHESES_OK then
writeln(c_prog, "#define uintRandLimited(rand_max) \
\({uintType rand_val; \
\do {rand_val = uintRand();} while (rand_val > (rand_max)); \
\rand_val;})");
else
declareExtern(c_prog, "uintType uintRandLimited (uintType);");
end if;
else
declareExtern(c_prog, "uintType uintRand (void);");
declareExtern(c_prog, "uintType uintRandMantissa (void);");
declareExtern(c_prog, "uintType uintRandLimited (uintType);");
end if;
declareExtern(c_prog, "intType intBinom (intType, intType);");
declareExtern(c_prog, "uintType uintBinomNoChk (uintType, intType);");
declareExtern(c_prog, "intType intBitLength (intType);");
declareExtern(c_prog, "striType intBytesBe (intType, boolType);");
declareExtern(c_prog, "intType intBytesBe2Int (const const_striType);");
declareExtern(c_prog, "intType intBytesBe2UInt (const const_striType);");
declareExtern(c_prog, "striType intBytesLe (intType, boolType);");
declareExtern(c_prog, "intType intBytesLe2Int (const const_striType);");
declareExtern(c_prog, "intType intBytesLe2UInt (const const_striType);");
declareExtern(c_prog, "intType intCmp (intType, intType);");
declareExtern(c_prog, "intType intCmpGeneric (const genericType, const genericType);");
declareExtern(c_prog, "intType intLog10 (intType);");
declareExtern(c_prog, "intType intLog2 (intType);");
declareExtern(c_prog, "intType intLowestSetBit (intType);");
declareExtern(c_prog, "striType intLpad0 (intType, const intType);");
declareExtern(c_prog, "striType intNBytesBeSigned (intType, intType);");
declareExtern(c_prog, "striType intNBytesBeUnsigned (intType, intType);");
declareExtern(c_prog, "striType intNBytesLeSigned (intType, intType);");
declareExtern(c_prog, "striType intNBytesLeUnsigned (intType, intType);");
declareExtern(c_prog, "intType intParse (const const_striType);");
declareExtern(c_prog, "intType intPow (intType, intType);");
declareExtern(c_prog, "intType intPowOvfChk (intType, intType);");
declareExtern(c_prog, "striType intRadix (intType, intType, boolType);");
declareExtern(c_prog, "striType intRadixPow2 (intType, int, int, boolType);");
declareExtern(c_prog, "intType intRand (intType, intType);");
declareExtern(c_prog, "intType intSqrt (intType);");
declareExtern(c_prog, "striType intStr (intType);");
declareExtern(c_prog, "striType intStrToBuffer (intType, striType);");
declareExtern(c_prog, "intType intValue (const const_objRefType);");
end func;
const array integer: maxExponentOfBase is [-8] (
21, 22, 24, 27, 31, 39, 63,
integer.last, integer.last, integer.last,
62, 39, 31, 27, 24, 22, 20);
const array integer: minBaseOfExponent is [2] (
-3037000499, -2097152, -55108, -6208, -1448, -512, -234, -128,
-78, -52, -38, -28, -22, -18, -15, -13, -11, -9, -8, -8, -7);
const array integer: maxBaseOfExponent is [2] (
3037000499, 2097151, 55108, 6208, 1448, 511, 234, 127,
78, 52, 38, 28, 22, 18, 15, 13, 11, 9, 8, 7, 7);
const type: addSubIntElementType is new struct
var boolean: doAdd is TRUE;
var reference: summand is NIL;
var integer: constSummand is 0;
end struct;
const type: addSubIntListType is array addSubIntElementType;
const proc: generateAddSubParamList (inout addSubIntListType: addSubParamList,
in var reference: leftParam) is func
local
var boolean: actionFound is FALSE;
var ref_list: subExprParams is ref_list.EMPTY;
var addSubIntElementType: addSubElement is addSubIntElementType.value;
begin
repeat
actionFound := FALSE;
if category(leftParam) = CALLOBJECT then
subExprParams := getValue(leftParam, ref_list);
if category(subExprParams[1]) = ACTOBJECT then
if str(getValue(subExprParams[1], ACTION)) = "INT_ADD" then
leftParam := subExprParams[2];
addSubElement.doAdd := TRUE;
addSubElement.summand := subExprParams[4];
addSubParamList := [] (addSubElement) & addSubParamList;
actionFound := TRUE;
elsif str(getValue(subExprParams[1], ACTION)) = "INT_SBTR" then
leftParam := subExprParams[2];
addSubElement.doAdd := FALSE;
addSubElement.summand := subExprParams[4];
addSubParamList := [] (addSubElement) & addSubParamList;
actionFound := TRUE;
end if;
end if;
end if;
until not actionFound;
if category(leftParam) = CALLOBJECT then
subExprParams := getValue(leftParam, ref_list);
if category(subExprParams[1]) = ACTOBJECT then
if str(getValue(subExprParams[1], ACTION)) = "INT_SUCC" then
addSubElement.doAdd := TRUE;
addSubElement.summand := NIL;
addSubElement.constSummand := 1;
addSubParamList := [] (addSubElement) & addSubParamList;
generateAddSubParamList(addSubParamList, subExprParams[2]);
actionFound := TRUE;
elsif str(getValue(subExprParams[1], ACTION)) = "INT_PRED" then
addSubElement.doAdd := FALSE;
addSubElement.summand := NIL;
addSubElement.constSummand := 1;
addSubParamList := [] (addSubElement) & addSubParamList;
generateAddSubParamList(addSubParamList, subExprParams[2]);
actionFound := TRUE;
end if;
end if;
end if;
if not actionFound then
addSubElement.doAdd := TRUE;
addSubElement.summand := leftParam;
addSubParamList := [] (addSubElement) & addSubParamList;
end if;
end func;
const func addSubIntListType: getAddSubParamList (in ref_list: params,
in boolean: doAdd) is func
result
var addSubIntListType: addSubParamList is 0 times addSubIntElementType.value;
local
var addSubIntElementType: addSubElement is addSubIntElementType.value;
begin
addSubElement.doAdd := doAdd;
addSubElement.summand := params[3];
addSubParamList := [] (addSubElement);
generateAddSubParamList(addSubParamList, params[1]);
end func;
const func addSubIntListType: getAddSubParamList (in reference: summand1,
in integer: summand2) is func
result
var addSubIntListType: addSubParamList is 0 times addSubIntElementType.value;
local
var addSubIntElementType: addSubElement is addSubIntElementType.value;
begin
addSubElement.constSummand := summand2;
addSubParamList := [] (addSubElement);
generateAddSubParamList(addSubParamList, summand1);
end func;
const proc: processNegations (inout addSubIntListType: addSubParamList,
inout expr_type: c_expr) is func
local
var integer: index is 1;
var boolean: doAdd is TRUE;
var reference: summand is NIL;
begin
for key index range addSubParamList do
if index > 1 and addSubParamList[index].summand <> NIL then
doAdd := addSubParamList[index].doAdd;
summand := addSubParamList[index].summand;
while isActionExpression(summand, "INT_NEGATE") or
isActionExpression(summand, "INT_PLUS") do
if isActionExpression(summand, "INT_NEGATE") then
countOverflowOptimizations(c_expr);
doAdd := not doAdd;
end if;
summand := getActionParameter(summand, 2);
end while;
addSubParamList[index].doAdd := doAdd;
addSubParamList[index].summand := summand;
end if;
end for;
end func;
const proc: summarizeConstants (inout addSubIntListType: addSubParamList) is func
local
var integer: index is 1;
var integer: paramValue is 0;
var bigInteger: bigSum is 0_;
begin
while index <= length(addSubParamList) do
if addSubParamList[index].summand = NIL then
paramValue := addSubParamList[index].constSummand;
if index < length(addSubParamList) and
addSubParamList[succ(index)].summand = NIL then
if addSubParamList[index].doAdd then
bigSum := bigInteger(paramValue);
else
bigSum := -bigInteger(paramValue);
end if;
if addSubParamList[succ(index)].doAdd then
bigSum +:= bigInteger(addSubParamList[succ(index)].constSummand);
else
bigSum -:= bigInteger(addSubParamList[succ(index)].constSummand);
end if;
if bigSum > bigInteger(integer.first) and bigSum < 0_ then
incr(countOptimizations);
if index > 1 then
addSubParamList[index].doAdd := FALSE;
addSubParamList[index].constSummand := -ord(bigSum);
else
addSubParamList[index].doAdd := TRUE;
addSubParamList[index].constSummand := ord(bigSum);
end if;
ignore(remove(addSubParamList, succ(index)));
elsif bigSum > 0_ and bigSum <= bigInteger(integer.last) then
incr(countOptimizations);
addSubParamList[index].doAdd := TRUE;
addSubParamList[index].constSummand := ord(bigSum);
ignore(remove(addSubParamList, succ(index)));
elsif bigSum = 0_ then
incr(countOptimizations);
if index > 1 or length(addSubParamList) = 2 or
addSubParamList[3].doAdd then
ignore(remove(addSubParamList, index));
ignore(remove(addSubParamList, index));
else
addSubParamList[index].doAdd := TRUE;
addSubParamList[index].constSummand := 0;
ignore(remove(addSubParamList, succ(index)));
end if;
elsif bigSum = bigInteger(integer.first) then
incr(countOptimizations);
addSubParamList[index].doAdd := TRUE;
addSubParamList[index].constSummand := integer.first;
ignore(remove(addSubParamList, succ(index)));
elsif bigSum = -bigInteger(integer.first) then
incr(countOptimizations);
if index > 1 then
addSubParamList[index].doAdd := FALSE;
addSubParamList[index].constSummand := integer.first;
ignore(remove(addSubParamList, succ(index)));
else
incr(index);
end if;
else
incr(index);
end if;
elsif paramValue = 0 then
if index > 1 or index = length(addSubParamList) or
addSubParamList[succ(index)].doAdd then
incr(countOptimizations);
ignore(remove(addSubParamList, index));
else
incr(index);
end if;
else
incr(index);
end if;
else
incr(index);
end if;
end while;
end func;
const proc: evaluateConstants (inout addSubIntListType: addSubParamList) is func
local
var integer: index is 1;
var reference: evaluatedParam is NIL;
var integer: paramValue is 0;
begin
for key index range addSubParamList do
if addSubParamList[index].summand <> NIL then
if getConstant(addSubParamList[index].summand, INTOBJECT, evaluatedParam) then
paramValue := getValue(evaluatedParam, integer);
addSubParamList[index].summand := NIL;
end if;
else
paramValue := addSubParamList[index].constSummand;
end if;
if addSubParamList[index].summand = NIL then
if index > 1 and paramValue > integer.first and paramValue < 0 then
addSubParamList[index].doAdd := not addSubParamList[index].doAdd;
addSubParamList[index].constSummand := -paramValue;
else
addSubParamList[index].constSummand := paramValue;
end if;
end if;
end for;
end func;
const proc: computeConstants (inout addSubIntListType: addSubParamList) is func
begin
summarizeConstants(addSubParamList);
if length(addSubParamList) >= 2 and
addSubParamList[1].doAdd and addSubParamList[1].summand = NIL and
addSubParamList[2].doAdd and addSubParamList[2].summand <> NIL then
addSubParamList[1].summand := addSubParamList[2].summand;
addSubParamList[2].summand := NIL;
addSubParamList[2].constSummand := addSubParamList[1].constSummand;
summarizeConstants(addSubParamList);
end if;
end func;
const proc: checkIfOutsideRange (in string: number_name, in integer: lowerBound,
in integer: upperBound, inout expr_type: c_expr) is func
begin
if ccConf.TWOS_COMPLEMENT_INTTYPE then
c_expr.expr &:= "(uintType)";
c_expr.expr &:= number_name;
if lowerBound < 0 then
c_expr.expr &:= "+(uintType)";
c_expr.expr &:= integerLiteral(-lowerBound);
elsif lowerBound > 0 then
c_expr.expr &:= "-(uintType)";
c_expr.expr &:= integerLiteral(lowerBound);
end if;
c_expr.expr &:= ">(uintType)";
c_expr.expr &:= integerLiteral(upperBound - lowerBound);
else
c_expr.expr &:= number_name;
c_expr.expr &:= "<";
c_expr.expr &:= integerLiteral(lowerBound);
c_expr.expr &:= "||";
c_expr.expr &:= number_name;
c_expr.expr &:= ">";
c_expr.expr &:= integerLiteral(upperBound);
end if;
end func;
const proc: const_int_add_with_overflow_check (in expr_type: summand1Expr, in integer: summand2,
inout expr_type: c_expr) is func
local
var string: sumName is "";
var string: summand1Name is "";
begin
if summand2 <> -1 and ccConf.BUILTIN_ADD_OVERFLOW <> "" then
sumName := defineTempVariable("intType", "sum_", c_expr);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= ccConf.BUILTIN_ADD_OVERFLOW;
c_expr.expr &:= "(";
c_expr.expr &:= summand1Expr.expr;
c_expr.expr &:= ", ";
c_expr.expr &:= integerLiteral(summand2);
c_expr.expr &:= ", &";
c_expr.expr &:= sumName;
c_expr.expr &:= "))?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= sumName;
else
c_expr.expr &:= "(";
summand1Name := defineTempVariable("intType", "summand1_", summand1Expr, c_expr);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= summand1Name;
if summand2 = -1 then
c_expr.expr &:= "==";
c_expr.expr &:= integerLiteral(integer.first);
elsif summand2 = 1 then
c_expr.expr &:= "==";
c_expr.expr &:= integerLiteral(integer.last);
elsif summand2 < 0 then
c_expr.expr &:= "<";
c_expr.expr &:= integerLiteral(integer.first - summand2);
else
c_expr.expr &:= ">";
c_expr.expr &:= integerLiteral(integer.last - summand2);
end if;
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= summand1Name;
c_expr.expr &:= " + ";
c_expr.expr &:= integerLiteral(summand2);
c_expr.expr &:= ")";
end if;
end func;
const proc: const_int_sbtr_with_overflow_check (in expr_type: minuendExpr, in integer: subtrahend,
inout expr_type: c_expr) is func
local
var string: differenceName is "";
var string: minuendName is "";
begin
if subtrahend <> 1 and ccConf.BUILTIN_SUB_OVERFLOW <> "" then
differenceName := defineTempVariable("intType", "difference_", c_expr);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= ccConf.BUILTIN_SUB_OVERFLOW;
c_expr.expr &:= "(";
c_expr.expr &:= minuendExpr.expr;
c_expr.expr &:= ", ";
c_expr.expr &:= integerLiteral(subtrahend);
c_expr.expr &:= ", &";
c_expr.expr &:= differenceName;
c_expr.expr &:= "))?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= differenceName;
else
c_expr.expr &:= "(";
minuendName := defineTempVariable("intType", "minuend_", minuendExpr, c_expr);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= minuendName;
if subtrahend = -1 then
c_expr.expr &:= "==";
c_expr.expr &:= integerLiteral(integer.last);
elsif subtrahend = 1 then
c_expr.expr &:= "==";
c_expr.expr &:= integerLiteral(integer.first);
elsif subtrahend < 0 then
c_expr.expr &:= ">";
c_expr.expr &:= integerLiteral(integer.last + subtrahend);
else
c_expr.expr &:= "<";
c_expr.expr &:= integerLiteral(integer.first + subtrahend);
end if;
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= minuendName;
c_expr.expr &:= " - ";
c_expr.expr &:= integerLiteral(subtrahend);
c_expr.expr &:= ")";
end if;
end func;
const proc: const_int_sbtr_with_overflow_check (in integer: minuend, in expr_type: subtrahendExpr,
inout expr_type: c_expr) is func
local
var string: differenceName is "";
var string: subtrahendName is "";
begin
if ccConf.BUILTIN_SUB_OVERFLOW <> "" then
differenceName := defineTempVariable("intType", "difference_", c_expr);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= ccConf.BUILTIN_SUB_OVERFLOW;
c_expr.expr &:= "(";
c_expr.expr &:= integerLiteral(minuend);
c_expr.expr &:= ", ";
c_expr.expr &:= subtrahendExpr.expr;
c_expr.expr &:= ", &";
c_expr.expr &:= differenceName;
c_expr.expr &:= "))?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= differenceName;
else
c_expr.expr &:= "(";
subtrahendName := defineTempVariable("intType", "subtrahend_", subtrahendExpr, c_expr);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= subtrahendName;
if minuend < 0 then
c_expr.expr &:= ">";
c_expr.expr &:= integerLiteral(-(integer.first - minuend));
elsif minuend = 0 then
c_expr.expr &:= "==";
c_expr.expr &:= integerLiteral(integer.first);
else
c_expr.expr &:= "<";
c_expr.expr &:= integerLiteral(-(integer.last - minuend));
end if;
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
if minuend <> 0 then
c_expr.expr &:= integerLiteral(minuend);
end if;
c_expr.expr &:= " - ";
c_expr.expr &:= subtrahendName;
c_expr.expr &:= ")";
end if;
end func;
const proc: int_add_with_overflow_check (in expr_type: summand1Expr, in reference: summand2,
inout expr_type: c_expr) is func
local
var string: sumName is "";
var string: summand1Name is "";
var string: summand2Name is "";
begin
if ccConf.BUILTIN_ADD_OVERFLOW <> "" then
sumName := defineTempVariable("intType", "sum_", c_expr);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= ccConf.BUILTIN_ADD_OVERFLOW;
c_expr.expr &:= "(";
c_expr.expr &:= summand1Expr.expr;
c_expr.expr &:= ", ";
process_expr(summand2, c_expr);
c_expr.expr &:= ", &";
c_expr.expr &:= sumName;
c_expr.expr &:= "))?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= sumName;
else
c_expr.expr &:= "(";
summand1Name := defineTempVariable("intType", "summand1_", summand1Expr, c_expr);
summand2Name := getParameterAsVariable("intType", "summand2_", summand2, c_expr);
sumName := defineTempVariable("intType", "sum_", c_expr);
c_expr.expr &:= sumName;
c_expr.expr &:= "=(intType)((uintType)";
c_expr.expr &:= summand1Name;
c_expr.expr &:= "+(uintType)";
c_expr.expr &:= summand2Name;
c_expr.expr &:= "), ";
c_expr.expr &:= "ovfChk((intType)(~(";
c_expr.expr &:= summand1Name;
c_expr.expr &:= "^";
c_expr.expr &:= summand2Name;
c_expr.expr &:= ")&(";
c_expr.expr &:= sumName;
c_expr.expr &:= "^";
c_expr.expr &:= summand1Name;
c_expr.expr &:= "))<0)?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= sumName;
c_expr.expr &:= ")";
end if;
end func;
const proc: int_sbtr_with_overflow_check (in expr_type: minuendExpr, in reference: subtrahend,
inout expr_type: c_expr) is func
local
var string: differenceName is "";
var string: minuendName is "";
var string: subtrahendName is "";
begin
if ccConf.BUILTIN_SUB_OVERFLOW <> "" then
differenceName := defineTempVariable("intType", "difference_", c_expr);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= ccConf.BUILTIN_SUB_OVERFLOW;
c_expr.expr &:= "(";
c_expr.expr &:= minuendExpr.expr;
c_expr.expr &:= ", ";
process_expr(subtrahend, c_expr);
c_expr.expr &:= ", &";
c_expr.expr &:= differenceName;
c_expr.expr &:= "))?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= differenceName;
else
c_expr.expr &:= "(";
minuendName := defineTempVariable("intType", "minuend_", minuendExpr, c_expr);
subtrahendName := getParameterAsVariable("intType", "subtrahend_", subtrahend, c_expr);
differenceName := defineTempVariable("intType", "difference_", c_expr);
c_expr.expr &:= differenceName;
c_expr.expr &:= "=(intType)((uintType)";
c_expr.expr &:= minuendName;
c_expr.expr &:= "-(uintType)";
c_expr.expr &:= subtrahendName;
c_expr.expr &:= "), ";
c_expr.expr &:= "ovfChk((intType)((";
c_expr.expr &:= minuendName;
c_expr.expr &:= "^";
c_expr.expr &:= subtrahendName;
c_expr.expr &:= ")&(";
c_expr.expr &:= differenceName;
c_expr.expr &:= "^";
c_expr.expr &:= minuendName;
c_expr.expr &:= "))<0)?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= differenceName;
c_expr.expr &:= ")";
end if;
end func;
const proc: int_mult_with_overflow_check (in reference: factor1, in reference: factor2,
inout expr_type: c_expr) is func
local
var intRange: factor1_range is intRange.value;
var intRange: factor2_range is intRange.value;
var string: factor1_name is "";
var string: factor2_name is "";
var string: product_name is "";
begin
if ccConf.BUILTIN_MULT_OVERFLOW <> "" then
product_name := defineTempVariable("intType", "product_", c_expr);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= ccConf.BUILTIN_MULT_OVERFLOW;
c_expr.expr &:= "(";
process_expr(factor1, c_expr);
c_expr.expr &:= ", ";
process_expr(factor2, c_expr);
c_expr.expr &:= ", &";
c_expr.expr &:= product_name;
c_expr.expr &:= "))?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= product_name;
elsif ccConf.INTTYPE_SIZE = 64 and ccConf.INT128TYPE <> "" or
ccConf.INTTYPE_SIZE = 32 then
product_name := defineTempVariable("doubleIntType", "product_", c_expr);
c_expr.expr &:= product_name;
c_expr.expr &:= "=(doubleIntType)(";
process_expr(factor1, c_expr);
c_expr.expr &:= ") * (doubleIntType)(";
process_expr(factor2, c_expr);
c_expr.expr &:= "),ovfChk(!inIntTypeRange(";
c_expr.expr &:= product_name;
c_expr.expr &:= "))?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":(intType)";
c_expr.expr &:= product_name;
else
factor1_range := getIntRange(factor1);
factor2_range := getIntRange(factor2);
factor1_name := getParameterAsVariable("intType", "factor1_", factor1, c_expr);
factor2_name := getParameterAsVariable("intType", "factor2_", factor2, c_expr);
c_expr.expr &:= "ovfChk(";
if factor1_range.minValue < 0 then
c_expr.expr &:= factor1_name;
c_expr.expr &:= "<0?";
if factor2_range.maxValue < 0 then
c_expr.expr &:= factor1_name;
c_expr.expr &:= "<";
c_expr.expr &:= integerLiteral(integer.last);
c_expr.expr &:= "/";
c_expr.expr &:= factor2_name;
elsif factor2_range.minValue < 0 then
c_expr.expr &:= factor2_name;
c_expr.expr &:= "<0";
if factor2_range.minValue < 0 and factor2_range.maxValue > 0 then
c_expr.expr &:= "?";
else
c_expr.expr &:= "&&";
end if;
c_expr.expr &:= factor1_name;
c_expr.expr &:= "<";
c_expr.expr &:= integerLiteral(integer.last);
c_expr.expr &:= "/";
c_expr.expr &:= factor2_name;
end if;
if factor2_range.minValue < 0 and factor2_range.maxValue > 0 then
c_expr.expr &:= ":(";
end if;
if factor2_range.minValue > 0 then
c_expr.expr &:= factor1_name;
c_expr.expr &:= "<";
c_expr.expr &:= integerLiteral(integer.first);
c_expr.expr &:= "/";
c_expr.expr &:= factor2_name;
elsif factor2_range.maxValue > 0 then
c_expr.expr &:= factor2_name;
c_expr.expr &:= ">0";
c_expr.expr &:= "&&";
c_expr.expr &:= factor1_name;
c_expr.expr &:= "<";
c_expr.expr &:= integerLiteral(integer.first);
c_expr.expr &:= "/";
c_expr.expr &:= factor2_name;
end if;
if factor2_range.minValue < 0 and factor2_range.maxValue > 0 then
c_expr.expr &:= ")";
end if;
if factor1_range.maxValue <= 0 then
c_expr.expr &:= ":0";
end if;
end if;
if factor1_range.minValue < 0 and factor1_range.maxValue > 0 then
c_expr.expr &:= ":(";
end if;
if factor1_range.maxValue > 0 then
c_expr.expr &:= factor1_name;
c_expr.expr &:= ">0?";
if factor2_range.maxValue < 0 then
c_expr.expr &:= factor2_name;
c_expr.expr &:= "<";
c_expr.expr &:= integerLiteral(integer.first);
c_expr.expr &:= "/";
c_expr.expr &:= factor1_name;
elsif factor2_range.minValue < 0 then
c_expr.expr &:= factor2_name;
c_expr.expr &:= "<0";
if factor2_range.minValue < 0 and factor2_range.maxValue > 0 then
c_expr.expr &:= "?";
else
c_expr.expr &:= "&&";
end if;
c_expr.expr &:= factor2_name;
c_expr.expr &:= "<";
c_expr.expr &:= integerLiteral(integer.first);
c_expr.expr &:= "/";
c_expr.expr &:= factor1_name;
end if;
if factor2_range.minValue < 0 and factor2_range.maxValue > 0 then
c_expr.expr &:= ":(";
end if;
if factor2_range.minValue > 0 then
c_expr.expr &:= factor2_name;
c_expr.expr &:= ">";
c_expr.expr &:= integerLiteral(integer.last);
c_expr.expr &:= "/";
c_expr.expr &:= factor1_name;
elsif factor2_range.maxValue > 0 then
c_expr.expr &:= factor2_name;
c_expr.expr &:= ">0";
c_expr.expr &:= "&&";
c_expr.expr &:= factor2_name;
c_expr.expr &:= ">";
c_expr.expr &:= integerLiteral(integer.last);
c_expr.expr &:= "/";
c_expr.expr &:= factor1_name;
end if;
if factor2_range.minValue < 0 and factor2_range.maxValue > 0 then
c_expr.expr &:= ")";
end if;
if factor1_range.minValue >= 0 then
c_expr.expr &:= ":0";
end if;
end if;
if factor1_range.minValue < 0 and factor1_range.maxValue > 0 then
c_expr.expr &:= ":0)";
end if;
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= factor1_name;
c_expr.expr &:= " * ";
c_expr.expr &:= factor2_name;
end if;
end func;
const proc: negate (in reference: number, inout expr_type: c_expr) is func
local
var intRange: number_range is intRange.value;
var string: number_name is "";
begin
if reduceOverflowChecks and
isActionExpression(number, "INT_NEGATE") then
countOverflowOptimizations(c_expr);
c_expr.expr &:= "/*no_overflow_check_negate_of_negate*/";
process_expr(getActionParameter(number, 2), c_expr);
elsif check_int_arithmetic_overflow and ccConf.TWOS_COMPLEMENT_INTTYPE then
number_range := getIntRange(number);
if number_range.minValue >= -integer.last then
countOverflowOptimizations(c_expr);
c_expr.expr &:= "/*no_overflow_check_negate*/-(";
process_expr(number, c_expr);
c_expr.expr &:= ")";
else
incr(countOverflowChecks);
c_expr.expr &:= "(";
number_name := getParameterAsVariable("intType", "number_", number, c_expr);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= number_name;
c_expr.expr &:= "==";
c_expr.expr &:= integerLiteral(integer.first);
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ": -";
c_expr.expr &:= number_name;
c_expr.expr &:= ")";
end if;
else
if ccConf.TWOS_COMPLEMENT_INTTYPE then
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
end if;
c_expr.expr &:= "-(";
process_expr(number, c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: process_const_int_add (in reference: summand1, in integer: summand2,
inout expr_type: c_expr) is func
local
var integer: minAllowedSummand1 is 0;
var integer: maxAllowedSummand1 is 0;
var reference: evaluatedParam is NIL;
var integer: summand1_value is 0;
var intRange: summand1_range is intRange.value;
var expr_type: summand1Expr is expr_type.value;
begin
if summand2 < 0 then
minAllowedSummand1 := integer.first - summand2;
maxAllowedSummand1 := integer.last;
else
minAllowedSummand1 := integer.first;
maxAllowedSummand1 := integer.last - summand2;
end if;
if getConstant(summand1, INTOBJECT, evaluatedParam) then
incr(countOptimizations);
summand1_value := getValue(evaluatedParam, integer);
if summand1_value < minAllowedSummand1 or
summand1_value > maxAllowedSummand1 then
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
else
c_expr.expr &:= integerLiteral(summand1_value + summand2);
end if;
elsif summand2 = 0 then
incr(countOptimizations);
process_expr(summand1, c_expr);
elsif check_int_arithmetic_overflow then
incr(countOptimizations);
summand1_range := getIntRange(summand1);
if summand1_range <> intRange.value and
summand1_range.minValue >= minAllowedSummand1 and
summand1_range.maxValue <= maxAllowedSummand1 then
countOverflowOptimizations(c_expr);
c_expr.expr &:= "/*no_overflow_check_add*/(";
process_expr(summand1, c_expr);
c_expr.expr &:= ") + ";
c_expr.expr &:= integerLiteral(summand2);
else
incr(countOverflowChecks);
summand1Expr.temp_num := c_expr.temp_num;
process_expr(summand1, summand1Expr);
c_expr.temp_num := summand1Expr.temp_num;
c_expr.temp_decls &:= summand1Expr.temp_decls;
c_expr.temp_assigns &:= summand1Expr.temp_assigns;
c_expr.temp_frees &:= summand1Expr.temp_frees;
c_expr.temp_to_null &:= summand1Expr.temp_to_null;
const_int_add_with_overflow_check(summand1Expr, summand2, c_expr);
end if;
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
c_expr.expr &:= "(";
process_expr(summand1, c_expr);
c_expr.expr &:= ") + ";
c_expr.expr &:= integerLiteral(summand2);
end if;
end func;
const proc: process_int_add (in reference: summand1, in reference: summand2,
inout expr_type: c_expr) is func
local
var intRange: summand1_range is intRange.value;
var intRange: summand2_range is intRange.value;
var integer: minAllowedSummand2 is 0;
var integer: maxAllowedSummand2 is 0;
var boolean: fullOverflowCheck is FALSE;
var expr_type: summand1Expr is expr_type.value;
var string: summand1_name is "";
var string: summand2_name is "";
begin
if check_int_arithmetic_overflow then
summand1_range := getIntRange(summand1);
summand2_range := getIntRange(summand2);
if summand1_range <> intRange.value and summand2_range <> intRange.value then
if summand1_range.minValue < 0 then
minAllowedSummand2 := integer.first - summand1_range.minValue;
else
minAllowedSummand2 := integer.first;
end if;
if summand1_range.maxValue > 0 then
maxAllowedSummand2 := integer.last - summand1_range.maxValue;
else
maxAllowedSummand2 := integer.last;
end if;
if summand2_range.minValue >= minAllowedSummand2 and
summand2_range.maxValue <= maxAllowedSummand2 then
countOverflowOptimizations(c_expr);
c_expr.expr &:= "/*no_overflow_check_add*/(";
process_expr(summand1, c_expr);
c_expr.expr &:= ") + (";
process_expr(summand2, c_expr);
c_expr.expr &:= ")";
elsif summand2_range.minValue >= minAllowedSummand2 or
summand2_range.maxValue <= maxAllowedSummand2 then
incr(countOverflowChecks);
c_expr.expr &:= "/*simplified_overflow_check_add*/(";
summand1_name := getParameterAsVariable("intType", "summand1_", summand1, c_expr);
summand2_name := getParameterAsVariable("intType", "summand2_", summand2, c_expr);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= summand2_name;
if summand2_range.maxValue <= maxAllowedSummand2 then
c_expr.expr &:= "<0&&";
c_expr.expr &:= summand1_name;
c_expr.expr &:= "<";
c_expr.expr &:= integerLiteral(integer.first);
else
c_expr.expr &:= ">=0&&";
c_expr.expr &:= summand1_name;
c_expr.expr &:= ">";
c_expr.expr &:= integerLiteral(integer.last);
end if;
c_expr.expr &:= "-";
c_expr.expr &:= summand2_name;
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= summand1_name;
c_expr.expr &:= " + ";
c_expr.expr &:= summand2_name;
c_expr.expr &:= ")";
else
fullOverflowCheck := TRUE;
end if;
else
fullOverflowCheck := TRUE;
end if;
if fullOverflowCheck then
incr(countOverflowChecks);
if summand1 = summand2 then
incr(countOptimizations);
c_expr.expr &:= "(";
summand1_name := getParameterAsVariable("intType", "summand1_", summand1, c_expr);
c_expr.expr &:= "ovfChk(";
checkIfOutsideRange(summand1_name, integer.first div 2,
integer.last div 2, c_expr);
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= summand1_name;
c_expr.expr &:= " + ";
c_expr.expr &:= summand1_name;
c_expr.expr &:= ")";
else
summand1Expr.temp_num := c_expr.temp_num;
process_expr(summand1, summand1Expr);
c_expr.temp_num := summand1Expr.temp_num;
c_expr.temp_decls &:= summand1Expr.temp_decls;
c_expr.temp_assigns &:= summand1Expr.temp_assigns;
c_expr.temp_frees &:= summand1Expr.temp_frees;
c_expr.temp_to_null &:= summand1Expr.temp_to_null;
int_add_with_overflow_check(summand1Expr, summand2, c_expr);
end if;
end if;
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
c_expr.expr &:= "(";
process_expr(summand1, c_expr);
c_expr.expr &:= ") + (";
process_expr(summand2, c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: process_const_int_sbtr (in reference: minuend, in integer: subtrahend,
inout expr_type: c_expr) is func
local
var integer: minAllowedMinuend is 0;
var integer: maxAllowedMinuend is 0;
var reference: evaluatedParam is NIL;
var integer: minuend_value is 0;
var intRange: minuend_range is intRange.value;
var expr_type: minuendExpr is expr_type.value;
begin
if subtrahend < 0 then
minAllowedMinuend := integer.first;
maxAllowedMinuend := integer.last + subtrahend;
else
minAllowedMinuend := integer.first + subtrahend;
maxAllowedMinuend := integer.last;
end if;
if getConstant(minuend, INTOBJECT, evaluatedParam) then
incr(countOptimizations);
minuend_value := getValue(evaluatedParam, integer);
if minuend_value < minAllowedMinuend or
minuend_value > maxAllowedMinuend then
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
else
c_expr.expr &:= integerLiteral(minuend_value - subtrahend);
end if;
elsif subtrahend = 0 then
incr(countOptimizations);
process_expr(minuend, c_expr);
elsif check_int_arithmetic_overflow then
incr(countOptimizations);
minuend_range := getIntRange(minuend);
if minuend_range <> intRange.value and
minuend_range.minValue >= minAllowedMinuend and
minuend_range.maxValue <= maxAllowedMinuend then
countOverflowOptimizations(c_expr);
c_expr.expr &:= "/*no_overflow_check_sbtr*/(";
process_expr(minuend, c_expr);
c_expr.expr &:= ") - ";
c_expr.expr &:= integerLiteral(subtrahend);
else
incr(countOverflowChecks);
minuendExpr.temp_num := c_expr.temp_num;
process_expr(minuend, minuendExpr);
c_expr.temp_num := minuendExpr.temp_num;
c_expr.temp_decls &:= minuendExpr.temp_decls;
c_expr.temp_assigns &:= minuendExpr.temp_assigns;
c_expr.temp_frees &:= minuendExpr.temp_frees;
c_expr.temp_to_null &:= minuendExpr.temp_to_null;
const_int_sbtr_with_overflow_check(minuendExpr, subtrahend, c_expr);
end if;
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
c_expr.expr &:= "(";
process_expr(minuend, c_expr);
c_expr.expr &:= ") - ";
c_expr.expr &:= integerLiteral(subtrahend);
end if;
end func;
const proc: process_const_int_sbtr (in integer: minuend, in reference: subtrahend,
inout expr_type: c_expr) is func
local
var integer: minAllowedSubtrahend is 0;
var integer: maxAllowedSubtrahend is 0;
var intRange: subtrahend_range is intRange.value;
var expr_type: subtrahendExpr is expr_type.value;
begin
if minuend < 0 then
minAllowedSubtrahend := integer.first;
maxAllowedSubtrahend := minuend - integer.first;
else
minAllowedSubtrahend := minuend - integer.last;
maxAllowedSubtrahend := integer.last;
end if;
if minuend = 0 then
negate(subtrahend, c_expr);
elsif check_int_arithmetic_overflow then
incr(countOptimizations);
subtrahend_range := getIntRange(subtrahend);
if subtrahend_range <> intRange.value and
subtrahend_range.minValue >= minAllowedSubtrahend and
subtrahend_range.maxValue <= maxAllowedSubtrahend then
countOverflowOptimizations(c_expr);
c_expr.expr &:= "/*no_overflow_check_sbtr*/ ";
c_expr.expr &:= integerLiteral(minuend);
c_expr.expr &:= " - (";
process_expr(subtrahend, c_expr);
c_expr.expr &:= ")";
else
incr(countOverflowChecks);
subtrahendExpr.temp_num := c_expr.temp_num;
process_expr(subtrahend, subtrahendExpr);
c_expr.temp_num := subtrahendExpr.temp_num;
c_expr.temp_decls &:= subtrahendExpr.temp_decls;
c_expr.temp_assigns &:= subtrahendExpr.temp_assigns;
c_expr.temp_frees &:= subtrahendExpr.temp_frees;
c_expr.temp_to_null &:= subtrahendExpr.temp_to_null;
const_int_sbtr_with_overflow_check(minuend, subtrahendExpr, c_expr);
end if;
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
c_expr.expr &:= integerLiteral(minuend);
c_expr.expr &:= " - (";
process_expr(subtrahend, c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: process_int_sbtr (in reference: minuend, in reference: subtrahend,
inout expr_type: c_expr) is func
local
var intRange: minuend_range is intRange.value;
var intRange: subtrahend_range is intRange.value;
var integer: minAllowedSubtrahend is 0;
var integer: maxAllowedSubtrahend is 0;
var boolean: fullOverflowCheck is FALSE;
var expr_type: minuendExpr is expr_type.value;
var string: minuend_name is "";
var string: subtrahend_name is "";
begin
if minuend = subtrahend then
incr(countOptimizations);
c_expr.expr &:= "0";
elsif check_int_arithmetic_overflow then
minuend_range := getIntRange(minuend);
subtrahend_range := getIntRange(subtrahend);
if minuend_range <> intRange.value and subtrahend_range <> intRange.value then
if minuend_range.maxValue > 0 then
minAllowedSubtrahend := minuend_range.maxValue - integer.last;
else
minAllowedSubtrahend := -integer.last;
end if;
if minuend_range.minValue < 0 then
maxAllowedSubtrahend := minuend_range.minValue - integer.first;
else
maxAllowedSubtrahend := integer.last;
end if;
if subtrahend_range.minValue >= minAllowedSubtrahend and
subtrahend_range.maxValue <= maxAllowedSubtrahend then
countOverflowOptimizations(c_expr);
c_expr.expr &:= "/*no_overflow_check_sbtr*/(";
process_expr(minuend, c_expr);
c_expr.expr &:= ") - (";
process_expr(subtrahend, c_expr);
c_expr.expr &:= ")";
elsif subtrahend_range.minValue >= minAllowedSubtrahend or
subtrahend_range.maxValue <= maxAllowedSubtrahend then
incr(countOverflowChecks);
c_expr.expr &:= "/*simplified_overflow_check_sbtr*/(";
minuend_name := getParameterAsVariable("intType", "minuend_", minuend, c_expr);
subtrahend_name := getParameterAsVariable("intType", "subtrahend_", subtrahend, c_expr);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= subtrahend_name;
if subtrahend_range.minValue >= minAllowedSubtrahend then
c_expr.expr &:= "<0&&";
c_expr.expr &:= minuend_name;
c_expr.expr &:= ">";
c_expr.expr &:= integerLiteral(integer.last);
else
c_expr.expr &:= ">=0&&";
c_expr.expr &:= minuend_name;
c_expr.expr &:= "<";
c_expr.expr &:= integerLiteral(integer.first);
end if;
c_expr.expr &:= "+";
c_expr.expr &:= subtrahend_name;
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= minuend_name;
c_expr.expr &:= " - ";
c_expr.expr &:= subtrahend_name;
c_expr.expr &:= ")";
else
fullOverflowCheck := TRUE;
end if;
else
fullOverflowCheck := TRUE;
end if;
if fullOverflowCheck then
incr(countOverflowChecks);
minuendExpr.temp_num := c_expr.temp_num;
process_expr(minuend, minuendExpr);
c_expr.temp_num := minuendExpr.temp_num;
c_expr.temp_decls &:= minuendExpr.temp_decls;
c_expr.temp_assigns &:= minuendExpr.temp_assigns;
c_expr.temp_frees &:= minuendExpr.temp_frees;
c_expr.temp_to_null &:= minuendExpr.temp_to_null;
int_sbtr_with_overflow_check(minuendExpr, subtrahend, c_expr);
end if;
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
c_expr.expr &:= "(";
process_expr(minuend, c_expr);
c_expr.expr &:= ") - (";
process_expr(subtrahend, c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: optimize_int_add (in addSubIntElementType: summand,
inout intRange: sumRange, inout expr_type: c_expr) is func
begin
if summand.summand = NIL then
if summand.doAdd then
sumRange := getIntRange(summand.constSummand);
c_expr.expr &:= integerLiteral(summand.constSummand);
else
sumRange := getIntNegateRange(getIntRange(summand.constSummand));
if summand.constSummand < -integer.last then
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
else
c_expr.expr &:= integerLiteral(-summand.constSummand);
end if;
end if;
else
if summand.doAdd then
sumRange := getIntRange(summand.summand);
process_expr(summand.summand, c_expr);
else
sumRange := getIntNegateRange(getIntRange(summand.summand));
negate(summand.summand, c_expr);
end if;
end if;
end func;
const proc: optimize_int_add (in addSubIntListType: addSubParamList,
inout intRange: sumRange, inout expr_type: c_expr) is func
local
var intRange: summand1Range is intRange.value;
var intRange: summand2Range is intRange.value;
var expr_type: summand1Expr is expr_type.value;
var reference: summand2Ref is NIL;
var integer: summand2Value is 0;
var boolean: doAdd is FALSE;
begin
if length(addSubParamList) >= 2 then
incr(countOptimizations);
if check_int_arithmetic_overflow then
summand1Expr.temp_num := c_expr.temp_num;
optimize_int_add(addSubParamList[.. pred(length(addSubParamList))], summand1Range, summand1Expr);
c_expr.temp_num := summand1Expr.temp_num;
c_expr.temp_decls &:= summand1Expr.temp_decls;
c_expr.temp_assigns &:= summand1Expr.temp_assigns;
c_expr.temp_frees &:= summand1Expr.temp_frees;
c_expr.temp_to_null &:= summand1Expr.temp_to_null;
doAdd := addSubParamList[length(addSubParamList)].doAdd;
summand2Ref := addSubParamList[length(addSubParamList)].summand;
if summand2Ref = NIL then
summand2Value := addSubParamList[length(addSubParamList)].constSummand;
if summand2Value = 0 then
writeln(" ***** Problem in optimize_int_add (1)");
sumRange := summand1Range;
c_expr.expr &:= summand1Expr.expr;
else
summand2Range := getIntRange(summand2Value);
if doAdd then
sumRange := getIntAddRange(summand1Range, summand2Range);
else
sumRange := getIntSbtrRange(summand1Range, summand2Range);
end if;
if not sumRange.mayOverflow then
countOverflowOptimizations(c_expr);
if doAdd then
c_expr.expr &:= "/*no_overflow_check_add*/(";
c_expr.expr &:= summand1Expr.expr;
c_expr.expr &:= ") + ";
else
c_expr.expr &:= "/*no_overflow_check_sbtr*/(";
c_expr.expr &:= summand1Expr.expr;
c_expr.expr &:= ") - ";
end if;
c_expr.expr &:= integerLiteral(summand2Value);
elsif sumRange.minValue = 0 and sumRange.maxValue = -1 and sumRange.mayOverflow then
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
else
incr(countOverflowChecks);
if doAdd then
const_int_add_with_overflow_check(summand1Expr, summand2Value, c_expr);
else
const_int_sbtr_with_overflow_check(summand1Expr, summand2Value, c_expr);
end if;
end if;
end if;
else
summand2Range := getIntRange(summand2Ref);
if doAdd then
sumRange := getIntAddRange(summand1Range, summand2Range);
else
sumRange := getIntSbtrRange(summand1Range, summand2Range);
end if;
if not sumRange.mayOverflow then
countOverflowOptimizations(c_expr);
if doAdd then
c_expr.expr &:= "/*no_overflow_check_add*/(";
c_expr.expr &:= summand1Expr.expr;
c_expr.expr &:= ") + (";
else
c_expr.expr &:= "/*no_overflow_check_sbtr*/(";
c_expr.expr &:= summand1Expr.expr;
c_expr.expr &:= ") - (";
end if;
process_expr(summand2Ref, c_expr);
c_expr.expr &:= ")";
elsif sumRange.minValue = 0 and sumRange.maxValue = -1 then
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
else
incr(countOverflowChecks);
if doAdd then
int_add_with_overflow_check(summand1Expr, summand2Ref, c_expr);
else
int_sbtr_with_overflow_check(summand1Expr, summand2Ref, c_expr);
end if;
end if;
end if;
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
c_expr.expr &:= "(";
optimize_int_add(addSubParamList[.. pred(length(addSubParamList))], summand1Range, c_expr);
if addSubParamList[length(addSubParamList)].doAdd then
c_expr.expr &:= ") + ";
else
c_expr.expr &:= ") - ";
end if;
if addSubParamList[length(addSubParamList)].summand = NIL then
c_expr.expr &:= integerLiteral(addSubParamList[length(addSubParamList)].constSummand);
else
c_expr.expr &:= "(";
process_expr(addSubParamList[length(addSubParamList)].summand, c_expr);
c_expr.expr &:= ")";
end if;
end if;
elsif length(addSubParamList) = 1 then
incr(countOptimizations);
optimize_int_add(addSubParamList[1], sumRange, c_expr);
else
incr(countOptimizations);
sumRange := getIntRange(0);
c_expr.expr &:= integerLiteral(0);
end if;
end func;
const proc: optimize_int_add (in ref_list: params, in boolean: doAdd,
inout expr_type: c_expr) is func
local
var addSubIntListType: addSubParamList is 0 times addSubIntElementType.value;
var intRange: sumRange is intRange.value;
begin
addSubParamList := getAddSubParamList(params, doAdd);
processNegations(addSubParamList, c_expr);
evaluateConstants(addSubParamList);
computeConstants(addSubParamList);
optimize_int_add(addSubParamList, sumRange, c_expr);
end func;
const proc: optimize_int_add (in reference: summand1, in integer: summand2,
inout expr_type: c_expr) is func
local
var addSubIntListType: addSubParamList is 0 times addSubIntElementType.value;
var intRange: sumRange is intRange.value;
begin
addSubParamList := getAddSubParamList(summand1, summand2);
processNegations(addSubParamList, c_expr);
evaluateConstants(addSubParamList);
computeConstants(addSubParamList);
optimize_int_add(addSubParamList, sumRange, c_expr);
end func;
const func boolean: constValueIsEqual (in reference: anExpr, in integer: number) is func
result
var boolean: isEqual is FALSE;
local
var reference: aParam is NIL;
begin
if category(anExpr) = INTOBJECT and
not isVar(anExpr) and
getValue(anExpr, integer) = number then
isEqual := TRUE;
elsif number < 0 then
if isActionExpression(anExpr, "INT_NEGATE") then
aParam := getActionParameter(anExpr, 2);
if category(aParam) = INTOBJECT and
not isVar(aParam) and
getValue(aParam, integer) = -number then
isEqual := TRUE;
end if;
end if;
end if;
end func;
const proc: process_int_str (in reference: param1, inout expr_type: c_expr) is func
local
var string: buffer_name is "";
begin
if ccConf.ALLOW_STRITYPE_SLICES and c_expr.demand < ASSIGN_RESULT then
incr(c_expr.temp_num);
buffer_name := "buffer_" & str(c_expr.temp_num);
c_expr.temp_decls &:= "union {\n";
c_expr.temp_decls &:= " struct striStruct striBuf;\n";
c_expr.temp_decls &:= " char charBuf[SIZ_STRI(INTTYPE_DECIMAL_SIZE)];\n";
c_expr.temp_decls &:= "} ";
c_expr.temp_decls &:= buffer_name;
c_expr.temp_decls &:= ";\n";
c_expr.expr &:= "intStrToBuffer(";
process_expr(param1, c_expr);
c_expr.expr &:= ", &";
c_expr.expr &:= buffer_name;
c_expr.expr &:= ".striBuf)";
else
prepare_stri_result(c_expr);
c_expr.result_expr := "intStr(";
getStdParamToResultExpr(param1, c_expr);
c_expr.result_expr &:= ")";
end if;
end func;
const proc: process (INT_ABS, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var intRange: number_range is intRange.value;
var string: number_name is "";
var string: sign_name is "";
var integer: number is 0;
begin
if getConstant(params[1], INTOBJECT, evaluatedParam) then
incr(countOptimizations);
number := getValue(evaluatedParam, integer);
if number = integer.first and ccConf.TWOS_COMPLEMENT_INTTYPE then
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
else
c_expr.expr &:= integerLiteral(abs(number));
end if;
else
number_range := getIntRange(params[1]);
if check_int_abs_overflow and number_range.minValue = integer.first then
if check_int_arithmetic_overflow then
incr(countOverflowChecks);
c_expr.expr &:= "(";
number_name := getParameterAsVariable("intType", "number_", params[1], c_expr);
if number_range.maxValue <= 0 then
incr(countOptimizations);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= number_name;
c_expr.expr &:= "==";
c_expr.expr &:= integerLiteral(integer.first);
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ": /*abs_of_nonpositive_number*/-";
c_expr.expr &:= number_name;
else
c_expr.expr &:= number_name;
c_expr.expr &:= "<0?";
c_expr.expr &:= "(ovfChk(";
c_expr.expr &:= number_name;
c_expr.expr &:= "==";
c_expr.expr &:= integerLiteral(integer.first);
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ": -";
c_expr.expr &:= number_name;
c_expr.expr &:= "):";
c_expr.expr &:= number_name;
end if;
c_expr.expr &:= ")";
else
if number_range.maxValue <= 0 then
incr(countOptimizations);
c_expr.expr &:= "/*abs_of_nonpositive_number*/-(";
process_expr(params[1], c_expr);
c_expr.expr &:= ")";
else
c_expr.expr &:= "(";
number_name := getParameterAsVariable("intType", "number_", params[1], c_expr);
c_expr.expr &:= number_name;
c_expr.expr &:= "<0?";
c_expr.expr &:= " -";
c_expr.expr &:= number_name;
c_expr.expr &:= ":";
c_expr.expr &:= number_name;
c_expr.expr &:= ")";
end if;
end if;
else
if check_int_abs_overflow and check_int_arithmetic_overflow then
countOverflowOptimizations(c_expr);
end if;
if number_range.minValue >= 0 then
incr(countOptimizations);
c_expr.expr &:= "/*abs_of_nonnegative_number*/";
process_expr(params[1], c_expr);
elsif number_range.maxValue <= 0 then
incr(countOptimizations);
c_expr.expr &:= "/*abs_of_nonpositive_number*/-(";
process_expr(params[1], c_expr);
c_expr.expr &:= ")";
elsif ccConf.INT_SIZE = ccConf.INTTYPE_SIZE then
c_expr.expr &:= "abs(";
process_expr(params[1], c_expr);
c_expr.expr &:= ")";
elsif ccConf.LONG_SIZE = ccConf.INTTYPE_SIZE then
c_expr.expr &:= "labs(";
process_expr(params[1], c_expr);
c_expr.expr &:= ")";
elsif ccConf.TWOS_COMPLEMENT_INTTYPE and ccConf.RSHIFT_DOES_SIGN_EXTEND then
c_expr.expr &:= "(";
number_name := getParameterAsVariable("intType", "number_", params[1], c_expr);
sign_name := defineTempVariable("intType", "sign_", c_expr);
c_expr.expr &:= sign_name;
c_expr.expr &:= " = ";
c_expr.expr &:= number_name;
c_expr.expr &:= " >> ";
c_expr.expr &:= str(pred(ccConf.INTTYPE_SIZE));
c_expr.expr &:= ", (";
c_expr.expr &:= number_name;
c_expr.expr &:= " + ";
c_expr.expr &:= sign_name;
c_expr.expr &:= ") ^ ";
c_expr.expr &:= sign_name;
c_expr.expr &:= ")";
else
c_expr.expr &:= "(";
number_name := getParameterAsVariable("intType", "number_", params[1], c_expr);
c_expr.expr &:= number_name;
c_expr.expr &:= "<0? (intType)(-(uintType)";
c_expr.expr &:= number_name;
c_expr.expr &:= "):";
c_expr.expr &:= number_name;
c_expr.expr &:= ")";
end if;
end if;
end if;
end func;
const proc: process (INT_ADD, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
begin
if callOptimizeIntAdd then
optimize_int_add(params, TRUE, c_expr);
elsif getConstant(params[3], INTOBJECT, evaluatedParam) then
process_const_int_add(params[1], getValue(evaluatedParam, integer), c_expr);
elsif getConstant(params[1], INTOBJECT, evaluatedParam) then
process_const_int_add(params[3], getValue(evaluatedParam, integer), c_expr);
elsif evaluate_const_expr = 0 and
category(params[3]) = INTOBJECT and not isVar(params[3]) and
getValue(params[3], integer) = integer.first then
process_const_int_add(params[1], integer.first, c_expr);
elsif evaluate_const_expr = 0 and
category(params[1]) = INTOBJECT and not isVar(params[1]) and
getValue(params[1], integer) = integer.first then
process_const_int_add(params[3], integer.first, c_expr);
else
process_int_add(params[1], params[3], c_expr);
end if;
end func;
const proc: process_const_int_add_assign (in reference: variable, in integer: delta,
inout expr_type: c_expr) is func
local
var string: variable_name is "";
var expr_type: statement is expr_type.value;
begin
if delta = 0 then
incr(countOptimizations);
c_expr.expr &:= "/* ignore integer +:= 0; */\n";
elsif check_int_arithmetic_overflow then
incr(countOptimizations);
incr(countOverflowChecks);
variable_name := getParameterAsReference("intType", "variable_", variable, statement);
statement.expr &:= "if (ovfChk(";
statement.expr &:= variable_name;
if delta = -1 then
statement.expr &:= "==";
statement.expr &:= integerLiteral(integer.first);
elsif delta = 1 then
statement.expr &:= "==";
statement.expr &:= integerLiteral(integer.last);
elsif delta < 0 then
statement.expr &:= "<";
statement.expr &:= integerLiteral(integer.first - delta);
else
statement.expr &:= ">";
statement.expr &:= integerLiteral(integer.last - delta);
end if;
statement.expr &:= ")) {\n";
statement.expr &:= raiseError("OVERFLOW_ERROR");
statement.expr &:= "} else {\n";
statement.expr &:= variable_name;
statement.expr &:= "+=";
statement.expr &:= integerLiteral(delta);
statement.expr &:= ";\n";
statement.expr &:= "}\n";
doLocalDeclsOfStatement(statement, c_expr);
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
process_expr(variable, statement);
statement.expr &:= "+=";
statement.expr &:= integerLiteral(delta);
statement.expr &:= ";\n";
doLocalDeclsOfStatement(statement, c_expr);
end if;
end func;
const proc: process (INT_ADD_ASSIGN, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var string: variable_name is "";
var string: delta_name is "";
var intRange: deltaRange is intRange.value;
var expr_type: statement is expr_type.value;
begin
if getConstant(params[3], INTOBJECT, evaluatedParam) then
process_const_int_add_assign(params[1], getValue(evaluatedParam, integer), c_expr);
elsif check_int_arithmetic_overflow then
deltaRange := getIntRange(params[3]);
if deltaRange.minValue = 0 and deltaRange.maxValue = 0 then
c_expr.expr &:= "/* ignore integer +:= 0; */\n";
else
incr(countOverflowChecks);
variable_name := getParameterAsReference("intType", "variable_", params[1], statement);
if ccConf.BUILTIN_ADD_OVERFLOW <> "" then
statement.expr &:= "ovfChk(";
statement.expr &:= ccConf.BUILTIN_ADD_OVERFLOW;
statement.expr &:= "(";
statement.expr &:= variable_name;
statement.expr &:= ", ";
process_expr(params[3], statement);
statement.expr &:= ", &(";
statement.expr &:= variable_name;
statement.expr &:= ")))?";
statement.expr &:= intRaiseError("OVERFLOW_ERROR");
statement.expr &:= ":0;\n";
else
delta_name := getParameterAsVariable("intType", "delta_", params[3], statement);
if deltaRange.minValue < 0 or deltaRange.maxValue > 0 then
statement.expr &:= "ovfChk(";
if deltaRange.minValue < 0 and deltaRange.maxValue > 0 then
statement.expr &:= delta_name;
statement.expr &:= "<0&&";
statement.expr &:= variable_name;
statement.expr &:= "<";
statement.expr &:= integerLiteral(integer.first);
statement.expr &:= "-";
statement.expr &:= delta_name;
statement.expr &:= " || ";
statement.expr &:= delta_name;
statement.expr &:= ">=0&&";
statement.expr &:= variable_name;
statement.expr &:= ">";
statement.expr &:= integerLiteral(integer.last);
statement.expr &:= "-";
statement.expr &:= delta_name;
elsif deltaRange.minValue < 0 then
statement.expr &:= variable_name;
statement.expr &:= "<";
statement.expr &:= integerLiteral(integer.first);
statement.expr &:= "-";
statement.expr &:= delta_name;
else
statement.expr &:= variable_name;
statement.expr &:= ">";
statement.expr &:= integerLiteral(integer.last);
statement.expr &:= "-";
statement.expr &:= delta_name;
end if;
statement.expr &:= ")?";
statement.expr &:= intRaiseError("OVERFLOW_ERROR");
statement.expr &:= ":";
end if;
statement.expr &:= "(";
statement.expr &:= variable_name;
statement.expr &:= "+=";
statement.expr &:= delta_name;
statement.expr &:= ");\n";
end if;
doLocalDeclsOfStatement(statement, c_expr);
end if;
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
process_expr(params[1], statement);
statement.expr &:= "+=";
process_expr(params[3], statement);
statement.expr &:= ";\n";
doLocalDeclsOfStatement(statement, c_expr);
end if;
end func;
const proc: process_const_int_binom (in integer: n_number, in reference: k_number,
inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var string: k_name is "";
begin
if getConstant(k_number, INTOBJECT, evaluatedParam) then
incr(countOptimizations);
block
c_expr.expr &:= integerLiteral(n_number ! getValue(evaluatedParam, integer));
exception
catch OVERFLOW_ERROR:
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
end block;
elsif n_number = -1 then
c_expr.expr &:= "(";
k_name := getParameterAsVariable("intType", "k_number_", k_number, c_expr);
c_expr.expr &:= k_name;
c_expr.expr &:= "<0?0:(";
c_expr.expr &:= k_name;
c_expr.expr &:= "&1?-1:1))";
elsif n_number = 0 then
c_expr.expr &:= "(";
process_expr(k_number, c_expr);
c_expr.expr &:= ")==0?1:0";
elsif n_number = 1 then
c_expr.expr &:= "(";
k_name := getParameterAsVariable("intType", "k_number_", k_number, c_expr);
c_expr.expr &:= k_name;
c_expr.expr &:= "==0||";
c_expr.expr &:= k_name;
c_expr.expr &:= "==1?1:0)";
else
if n_number >= 0 and
((ccConf.INTTYPE_SIZE = 32 and n_number <= 30) or
(ccConf.INTTYPE_SIZE = 64 and n_number <= 62)) then
c_expr.expr &:= "(intType) uintBinomNoChk((uintType) ";
else
c_expr.expr &:= "intBinom(";
end if;
c_expr.expr &:= integerLiteral(n_number);
c_expr.expr &:= ", ";
process_expr(k_number, c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: process_const_int_binom (in reference: n_number, in integer: k_number,
inout expr_type: c_expr) is func
begin
if k_number <= 1 then
if k_number < 0 then
c_expr.expr &:= "/* binom(n, negative k) */ ";
c_expr.expr &:= integerLiteral(0);
elsif k_number = 0 then
c_expr.expr &:= "/* binom(n, 0) */ ";
c_expr.expr &:= integerLiteral(1);
else
c_expr.expr &:= "/* binom(n, 1) */ ";
process_expr(n_number, c_expr);
end if;
else
c_expr.expr &:= "intBinom(";
process_expr(n_number, c_expr);
c_expr.expr &:= ", ";
c_expr.expr &:= integerLiteral(k_number);
c_expr.expr &:= ")";
end if;
end func;
const proc: process (INT_BINOM, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
begin
if getConstant(params[1], INTOBJECT, evaluatedParam) then
process_const_int_binom(getValue(evaluatedParam, integer), params[3], c_expr);
elsif getConstant(params[3], INTOBJECT, evaluatedParam) then
process_const_int_binom(params[1], getValue(evaluatedParam, integer), c_expr);
else
c_expr.expr &:= "intBinom(";
process_expr(params[1], c_expr);
c_expr.expr &:= ", ";
process_expr(params[3], c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: process (INT_BIT_LENGTH, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
c_expr.expr &:= "intBitLength(";
process_expr(params[1], c_expr);
c_expr.expr &:= ")";
end func;
const proc: process (INT_BYTES_BE_2_INT, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
c_expr.expr &:= "intBytesBe2Int(";
getAnyParamToExpr(params[1], c_expr);
c_expr.expr &:= ")";
end func;
const proc: optimize_int_bytes_2_uint_length_0 (in reference: stri,
in reference: start, in boolean: fixedLengthSubstring,
inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var boolean: stri_is_variable is TRUE;
var string: stri_name is "";
var integer: stri_length is 0;
var string: stri_size is "";
var intRange: start_range is intRange.value;
var string: start_name is "";
var boolean: raisesException is FALSE;
var string: logicalOr is "";
begin
incr(countOptimizations);
incr(countInlinedFunctions);
start_range := getIntRange(start);
c_expr.expr &:= "(";
if start_range.maxValue < 1 then
warning(DOES_RAISE, "INDEX_ERROR", c_expr);
c_expr.expr &:= intRaiseError("INDEX_ERROR");
raisesException := TRUE;
elsif getConstant(stri, STRIOBJECT, evaluatedParam) then
stri_is_variable := FALSE;
stri_length := length(getValue(evaluatedParam, string));
stri_size := memSizeLiteral(stri_length);
if start_range.minValue > stri_length then
if fixedLengthSubstring then
warning(DOES_RAISE, "INDEX_ERROR", c_expr);
c_expr.expr &:= intRaiseError("INDEX_ERROR");
else
warning(DOES_RAISE, "RANGE_ERROR", c_expr);
c_expr.expr &:= intRaiseError("RANGE_ERROR");
end if;
raisesException := TRUE;
end if;
else
stri_name := getParameterAsVariable("const_striType", "stri_", stri, c_expr);
stri_size := stri_name & "->size";
end if;
if not raisesException then
if getConstant(start, INTOBJECT, evaluatedParam) then
start_name := integerLiteral(getValue(evaluatedParam, integer));
else
start_name := getTempVariable("intType", "start_", start, c_expr);
end if;
if string_index_check then
if start_range.minValue < 1 or (fixedLengthSubstring and
(stri_is_variable or start_range.maxValue > stri_length)) then
incr(countIndexChecks);
c_expr.expr &:= "idxChk(";
if start_range.minValue < 1 then
c_expr.expr &:= start_name;
c_expr.expr &:= "<1";
logicalOr := "||";
end if;
if fixedLengthSubstring and
(stri_is_variable or start_range.maxValue > stri_length) then
c_expr.expr &:= logicalOr;
c_expr.expr &:= start_name;
c_expr.expr &:= ">";
c_expr.expr &:= stri_size;
end if;
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("INDEX_ERROR");
c_expr.expr &:= ":";
else
countIndexOptimizations(c_expr);
end if;
else
incr(countSuppressedIndexChecks);
end if;
c_expr.expr &:= intRaiseError("RANGE_ERROR");
end if;
c_expr.expr &:= ")";
end func;
const proc: optimize_int_bytes_2_uint_length_1 (in reference: stri,
in reference: start, in boolean: fixedLengthSubstring,
inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var boolean: stri_is_variable is TRUE;
var string: stri_name is "";
var string: stri_value is "";
var integer: stri_length is 0;
var string: stri_size is "";
var string: start_name is "";
var integer: start_value is 0;
var intRange: start_range is intRange.value;
var boolean: raisesException is FALSE;
var string: logicalOr is "";
begin
incr(countOptimizations);
incr(countInlinedFunctions);
c_expr.expr &:= "(";
if getConstant(stri, STRIOBJECT, evaluatedParam) then
stri_is_variable := FALSE;
stri_value := getValue(evaluatedParam, string);
stri_name := "(" & stringLiteral(stri_value) & ")";
stri_length := length(stri_value);
stri_size := memSizeLiteral(stri_length);
else
stri_name := getParameterAsVariable("const_striType", "stri_", stri, c_expr);
stri_size := stri_name & "->size";
end if;
start_range := getIntRange(start);
if start_range.maxValue < 1 then
warning(DOES_RAISE, "INDEX_ERROR", c_expr);
c_expr.expr &:= intRaiseError("INDEX_ERROR");
raisesException := TRUE;
elsif not stri_is_variable and start_range.minValue > stri_length then
if fixedLengthSubstring then
warning(DOES_RAISE, "INDEX_ERROR", c_expr);
c_expr.expr &:= intRaiseError("INDEX_ERROR");
else
warning(DOES_RAISE, "RANGE_ERROR", c_expr);
c_expr.expr &:= intRaiseError("RANGE_ERROR");
end if;
raisesException := TRUE;
elsif getConstant(start, INTOBJECT, evaluatedParam) then
start_value := getValue(evaluatedParam, integer);
start_name := integerLiteral(start_value);
else
start_name := getTempVariable("intType", "start_", start, c_expr);
end if;
if not raisesException then
if string_index_check then
if start_range.minValue < 1 or (fixedLengthSubstring and
(stri_is_variable or start_range.maxValue > stri_length)) then
incr(countIndexChecks);
c_expr.expr &:= "idxChk(";
if start_range.minValue < 1 then
c_expr.expr &:= start_name;
c_expr.expr &:= "<1";
logicalOr := "||";
end if;
if fixedLengthSubstring and
(stri_is_variable or start_range.maxValue > stri_length) then
c_expr.expr &:= logicalOr;
c_expr.expr &:= start_name;
c_expr.expr &:= ">";
c_expr.expr &:= stri_size;
end if;
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("INDEX_ERROR");
c_expr.expr &:= ":";
else
countIndexOptimizations(c_expr);
end if;
else
incr(countSuppressedIndexChecks);
end if;
c_expr.expr &:= "(";
if function_range_check then
incr(countRangeChecks);
c_expr.expr &:= "rngChk(";
if not fixedLengthSubstring then
c_expr.expr &:= start_name;
c_expr.expr &:= ">";
c_expr.expr &:= stri_size;
c_expr.expr &:= "||";
end if;
c_expr.expr &:= stri_name;
c_expr.expr &:= "->mem[";
c_expr.expr &:= start_name;
c_expr.expr &:= "-1]>255)?";
c_expr.expr &:= intRaiseError("RANGE_ERROR");
c_expr.expr &:= ":";
else
incr(countNoRangeChecks);
end if;
c_expr.expr &:= "(intType)";
c_expr.expr &:= stri_name;
c_expr.expr &:= "->mem[";
c_expr.expr &:= start_name;
c_expr.expr &:= "-1])";
end if;
c_expr.expr &:= ")";
end func;
const proc: optimize_int_bytes_be_2_uint (in string: stri_name, in integer: length,
inout expr_type: c_expr) is func
local
var integer: index is 0;
begin
for index range 1 to length do
if index <> 1 then
c_expr.expr &:= "|";
end if;
if function_range_check then
incr(countRangeChecks);
c_expr.expr &:= "(rngChk(";
c_expr.expr &:= stri_name;
c_expr.expr &:= "->mem[";
c_expr.expr &:= integerLiteral(pred(index));
c_expr.expr &:= "]>";
if length = 8 and index = 1 then
c_expr.expr &:= "127";
else
c_expr.expr &:= "255";
end if;
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("RANGE_ERROR");
c_expr.expr &:= ":(intType)";
c_expr.expr &:= stri_name;
c_expr.expr &:= "->mem[";
c_expr.expr &:= integerLiteral(pred(index));
c_expr.expr &:= "])";
else
incr(countNoRangeChecks);
c_expr.expr &:= "(intType)";
c_expr.expr &:= stri_name;
c_expr.expr &:= "->mem[";
c_expr.expr &:= integerLiteral(pred(index));
c_expr.expr &:= "]";
end if;
if index < length then
c_expr.expr &:= "<<";
c_expr.expr &:= integerLiteral((length - index) * 8);
end if;
end for;
end func;
const proc: optimize_int_bytes_be_2_uint (in reference: stri, in integer: length,
in boolean: fixedLengthSubstring, inout expr_type: c_expr) is func
local
var string: stri_name is "";
begin
if length < 0 then
warning(DOES_RAISE, "INDEX_ERROR", c_expr);
c_expr.expr &:= intRaiseError("INDEX_ERROR");
elsif length = 0 then
optimize_int_bytes_2_uint_length_0(getValue(stri, ref_list)[2],
getValue(stri, ref_list)[4], fixedLengthSubstring, c_expr);
elsif length = 1 then
optimize_int_bytes_2_uint_length_1(getValue(stri, ref_list)[2],
getValue(stri, ref_list)[4], fixedLengthSubstring, c_expr);
elsif length >= 2 and length <= 8 then
incr(countOptimizations);
incr(countInlinedFunctions);
c_expr.expr &:= "(";
stri_name := getParameterAsVariable("const_striType", "stri_", stri, c_expr);
if fixedLengthSubstring then
optimize_int_bytes_be_2_uint(stri_name, length, c_expr);
else
c_expr.expr &:= stri_name;
c_expr.expr &:= "->size==";
c_expr.expr &:= integerLiteral(length);
c_expr.expr &:= "?(";
optimize_int_bytes_be_2_uint(stri_name, length, c_expr);
c_expr.expr &:= "):intBytesBe2UInt(";
c_expr.expr &:= stri_name;
c_expr.expr &:= ")";
end if;
c_expr.expr &:= ")";
else
c_expr.expr &:= "intBytesBe2UInt(";
getAnyParamToExpr(stri, c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: process (INT_BYTES_BE_2_UINT, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
begin
if inlineFunctions and
isActionExpression(params[1], "STR_SUBSTR") and
getConstant(getActionParameter(params[1], 5), INTOBJECT, evaluatedParam) then
optimize_int_bytes_be_2_uint(params[1],
getValue(evaluatedParam, integer), FALSE, c_expr);
elsif inlineFunctions and
isActionExpression(params[1], "STR_SUBSTR_FIXLEN") and
getConstant(getActionParameter(params[1], 5), INTOBJECT, evaluatedParam) then
optimize_int_bytes_be_2_uint(params[1],
getValue(evaluatedParam, integer), TRUE, c_expr);
else
c_expr.expr &:= "intBytesBe2UInt(";
getAnyParamToExpr(params[1], c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: process (INT_BYTES_BE_SIGNED, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
prepare_stri_result(c_expr);
c_expr.result_expr := "intBytesBe(";
getStdParamToResultExpr(params[1], c_expr);
c_expr.result_expr &:= ", 1)";
end func;
const proc: process (INT_BYTES_BE_UNSIGNED, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
prepare_stri_result(c_expr);
c_expr.result_expr := "intBytesBe(";
getStdParamToResultExpr(params[1], c_expr);
c_expr.result_expr &:= ", 0)";
end func;
const proc: process (INT_BYTES_LE_2_INT, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
c_expr.expr &:= "intBytesLe2Int(";
getAnyParamToExpr(params[1], c_expr);
c_expr.expr &:= ")";
end func;
const proc: optimize_int_bytes_le_2_uint (in string: stri_name, in integer: length,
inout expr_type: c_expr) is func
local
var integer: index is 0;
begin
for index range 1 to length do
if index <> 1 then
c_expr.expr &:= "|";
end if;
if function_range_check then
incr(countRangeChecks);
c_expr.expr &:= "(rngChk(";
c_expr.expr &:= stri_name;
c_expr.expr &:= "->mem[";
c_expr.expr &:= integerLiteral(pred(index));
c_expr.expr &:= "]>";
if length = 8 and index = 8 then
c_expr.expr &:= "127";
else
c_expr.expr &:= "255";
end if;
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("RANGE_ERROR");
c_expr.expr &:= ":(intType)";
c_expr.expr &:= stri_name;
c_expr.expr &:= "->mem[";
c_expr.expr &:= integerLiteral(pred(index));
c_expr.expr &:= "])";
else
incr(countNoRangeChecks);
c_expr.expr &:= "(intType)";
c_expr.expr &:= stri_name;
c_expr.expr &:= "->mem[";
c_expr.expr &:= integerLiteral(pred(index));
c_expr.expr &:= "]";
end if;
if index <> 1 then
c_expr.expr &:= "<<";
c_expr.expr &:= integerLiteral(pred(index) * 8);
end if;
end for;
end func;
const proc: optimize_int_bytes_le_2_uint (in reference: stri, in integer: length,
in boolean: fixedLengthSubstring, inout expr_type: c_expr) is func
local
var string: stri_name is "";
begin
if length < 0 then
warning(DOES_RAISE, "INDEX_ERROR", c_expr);
c_expr.expr &:= intRaiseError("INDEX_ERROR");
elsif length = 0 then
optimize_int_bytes_2_uint_length_0(getValue(stri, ref_list)[2],
getValue(stri, ref_list)[4], fixedLengthSubstring, c_expr);
elsif length = 1 then
optimize_int_bytes_2_uint_length_1(getValue(stri, ref_list)[2],
getValue(stri, ref_list)[4], fixedLengthSubstring, c_expr);
elsif length >= 2 and length <= 8 then
incr(countOptimizations);
incr(countInlinedFunctions);
c_expr.expr &:= "(";
stri_name := getParameterAsVariable("const_striType", "stri_", stri, c_expr);
if fixedLengthSubstring then
optimize_int_bytes_le_2_uint(stri_name, length, c_expr);
else
c_expr.expr &:= stri_name;
c_expr.expr &:= "->size==";
c_expr.expr &:= integerLiteral(length);
c_expr.expr &:= "?(";
optimize_int_bytes_le_2_uint(stri_name, length, c_expr);
c_expr.expr &:= "):intBytesLe2UInt(";
c_expr.expr &:= stri_name;
c_expr.expr &:= ")";
end if;
c_expr.expr &:= ")";
else
c_expr.expr &:= "intBytesLe2UInt(";
getAnyParamToExpr(stri, c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: process (INT_BYTES_LE_2_UINT, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
begin
if inlineFunctions and
isActionExpression(params[1], "STR_SUBSTR") and
getConstant(getActionParameter(params[1], 5), INTOBJECT, evaluatedParam) then
optimize_int_bytes_le_2_uint(params[1],
getValue(evaluatedParam, integer), FALSE, c_expr);
elsif inlineFunctions and
isActionExpression(params[1], "STR_SUBSTR_FIXLEN") and
getConstant(getActionParameter(params[1], 5), INTOBJECT, evaluatedParam) then
optimize_int_bytes_le_2_uint(params[1],
getValue(evaluatedParam, integer), TRUE, c_expr);
else
c_expr.expr &:= "intBytesLe2UInt(";
getAnyParamToExpr(params[1], c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: process (INT_BYTES_LE_SIGNED, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
prepare_stri_result(c_expr);
c_expr.result_expr := "intBytesLe(";
getStdParamToResultExpr(params[1], c_expr);
c_expr.result_expr &:= ", 1)";
end func;
const proc: process (INT_BYTES_LE_UNSIGNED, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
prepare_stri_result(c_expr);
c_expr.result_expr := "intBytesLe(";
getStdParamToResultExpr(params[1], c_expr);
c_expr.result_expr &:= ", 0)";
end func;
const proc: process (INT_CMP, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var string: number1_name is "";
var string: number2_name is "";
begin
if inlineFunctions then
incr(countOptimizations);
incr(countInlinedFunctions);
c_expr.expr &:= "(";
number1_name := getParameterAsVariable("intType", "number1_", params[1], c_expr);
number2_name := getParameterAsVariable("intType", "number2_", params[2], c_expr);
c_expr.expr &:= number1_name;
c_expr.expr &:= "<";
c_expr.expr &:= number2_name;
c_expr.expr &:= "? -1 : ";
c_expr.expr &:= number1_name;
c_expr.expr &:= ">";
c_expr.expr &:= number2_name;
c_expr.expr &:= ")";
else
c_expr.expr &:= "intCmp(";
process_expr(params[1], c_expr);
c_expr.expr &:= ", ";
process_expr(params[2], c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: process (INT_CPY, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var expr_type: statement is expr_type.value;
begin
statement.temp_num := c_expr.temp_num;
process_expr(params[1], statement);
statement.expr &:= "=";
process_expr(params[3], statement);
statement.expr &:= ";\n";
doLocalDeclsOfStatement(statement, c_expr);
c_expr.temp_num := statement.temp_num;
end func;
const proc: process (INT_DECR, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var expr_type: c_param1 is expr_type.value;
var string: variable_name is "";
var expr_type: statement is expr_type.value;
begin
if check_int_arithmetic_overflow then
incr(countOverflowChecks);
if isNormalVariable(params[1]) then
process_expr(params[1], c_param1);
statement.expr &:= "if (ovfChk(";
statement.expr &:= c_param1.expr;
statement.expr &:= "==";
statement.expr &:= integerLiteral(integer.first);
statement.expr &:= ")) {";
statement.expr &:= raiseError("OVERFLOW_ERROR");
statement.expr &:= "} else --(";
statement.expr &:= c_param1.expr;
statement.expr &:= ");\n";
else
incr(statement.temp_num);
variable_name := "var_" & str(statement.temp_num);
statement.temp_decls &:= "intType *";
statement.temp_decls &:= variable_name;
statement.temp_decls &:= ";\n";
statement.expr &:= variable_name;
statement.expr &:= "=&(";
process_expr(params[1], statement);
statement.expr &:= ");\n";
statement.expr &:= "if (ovfChk(*";
statement.expr &:= variable_name;
statement.expr &:= "==";
statement.expr &:= integerLiteral(integer.first);
statement.expr &:= ")) {";
statement.expr &:= raiseError("OVERFLOW_ERROR");
statement.expr &:= "} else --(*";
statement.expr &:= variable_name;
statement.expr &:= ");\n";
end if;
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
statement.expr &:= "--(";
process_expr(params[1], statement);
statement.expr &:= ");\n";
end if;
doLocalDeclsOfStatement(statement, c_expr);
end func;
const proc: process_const_int_mult (in reference: factor1, in integer: factor2,
inout expr_type: c_expr) is forward;
const proc: process_const_int_div (in reference: dividend, in integer: divisor,
inout expr_type: c_expr) is forward;
const func boolean: optimize_div_of_product (in reference: number, in integer: factor,
in integer: divisor, inout expr_type: c_expr) is func
result
var boolean: done is TRUE;
begin
if factor = 0 then
incr(countOptimizations);
c_expr.expr &:= "0";
elsif factor = divisor then
incr(countOptimizations);
countOverflowOptimizations(c_expr);
process_expr(number, c_expr);
elsif factor rem divisor = 0 then
incr(countOptimizations);
process_const_int_mult(number, factor div divisor, c_expr);
elsif divisor rem factor = 0 then
incr(countOptimizations);
countOverflowOptimizations(c_expr);
process_const_int_div(number, divisor div factor, c_expr);
else
done := FALSE;
end if;
end func;
const proc: process_const_int_div (in reference: dividend, in integer: divisor,
inout expr_type: c_expr) is func
local
var reference: evaluatedDividend is NIL;
var reference: evaluatedFactor is NIL;
var integer: dividend_value is 0;
var string: dividend_name is "";
var intRange: dividend_range is intRange.value;
var boolean: done is TRUE;
begin
if divisor = 0 then
incr(countOptimizations);
warning(DOES_RAISE, "NUMERIC_ERROR", c_expr);
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
elsif getConstant(dividend, INTOBJECT, evaluatedDividend) then
incr(countOptimizations);
dividend_value := getValue(evaluatedDividend, integer);
if divisor = -1 and dividend_value < -integer.last then
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
else
c_expr.expr &:= integerLiteral(dividend_value div divisor);
end if;
elsif divisor = 1 then
incr(countOptimizations);
c_expr.expr &:= "(";
process_expr(dividend, c_expr);
c_expr.expr &:= ")";
elsif isActionExpression(dividend, "INT_MULT") and
getConstant(getActionParameter(dividend, 3), INTOBJECT, evaluatedFactor) then
done := optimize_div_of_product(getActionParameter(dividend, 1),
getValue(evaluatedFactor, integer), divisor, c_expr);
elsif isActionExpression(dividend, "INT_MULT") and
getConstant(getActionParameter(dividend, 1), INTOBJECT, evaluatedFactor) then
done := optimize_div_of_product(getActionParameter(dividend, 3),
getValue(evaluatedFactor, integer), divisor, c_expr);
else
done := FALSE;
end if;
if not done then
if divisor = -1 then
incr(countOptimizations);
negate(dividend, c_expr);
elsif divisor > 0 and 2 ** log2(divisor) = divisor then
dividend_range := getIntRange(dividend);
if dividend_range.minValue >= 0 then
incr(countOptimizations);
if ccConf.RSHIFT_DOES_SIGN_EXTEND then
c_expr.expr &:= "(";
process_expr(dividend, c_expr);
c_expr.expr &:= ") >> ";
c_expr.expr &:= integerLiteral(log2(divisor));
else
c_expr.expr &:= "(";
dividend_name := getParameterAsVariable("intType", "dividend_", dividend, c_expr);
doRshift(dividend_name, integerLiteral(log2(divisor)), c_expr);
c_expr.expr &:= ")";
end if;
else
c_expr.expr &:= "(";
process_expr(dividend, c_expr);
c_expr.expr &:= ") / ";
c_expr.expr &:= integerLiteral(divisor);
end if;
elsif divisor < 0 and bitLength(divisor) = lowestSetBit(divisor) then
dividend_range := getIntRange(dividend);
if dividend_range.maxValue <= 0 then
incr(countOptimizations);
c_expr.expr &:= "(intType)(-(uintType)(";
process_expr(dividend, c_expr);
c_expr.expr &:= ") >> ";
c_expr.expr &:= integerLiteral(bitLength(divisor));
c_expr.expr &:= ")";
else
c_expr.expr &:= "(";
process_expr(dividend, c_expr);
c_expr.expr &:= ") / ";
c_expr.expr &:= integerLiteral(divisor);
end if;
else
c_expr.expr &:= "(";
process_expr(dividend, c_expr);
c_expr.expr &:= ") / ";
c_expr.expr &:= integerLiteral(divisor);
end if;
end if;
end func;
const proc: process_const_int_div (in integer: dividend, in reference: divisor,
inout expr_type: c_expr) is func
local
var string: divisor_name is "";
var intRange: divisor_range is intRange.value;
begin
divisor_range := getIntRange(divisor);
if dividend = 0 then
incr(countOptimizations);
if integer_division_check then
if (divisor_range.minValue <= 0 and divisor_range.maxValue >= 0) or
divisor_range.mayRaiseException then
incr(countDivisionChecks);
c_expr.expr &:= "(divChk((";
process_expr(divisor, c_expr);
c_expr.expr &:= ")==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":0)";
else
countDivisionOptimizations(c_expr);
c_expr.expr &:= "0";
end if;
else
c_expr.expr &:= "0";
end if;
elsif check_int_division_overflow and dividend = integer.first then
if divisor_range.maxValue < -1 or divisor_range.minValue > 0 then
countOverflowOptimizations(c_expr);
if check_int_div_by_zero then
countDivisionOptimizations(c_expr);
end if;
c_expr.expr &:= integerLiteral(dividend);
c_expr.expr &:= " / (";
process_expr(divisor, c_expr);
c_expr.expr &:= ")";
else
c_expr.expr &:= "(";
divisor_name := getParameterAsVariable("intType", "divisor_", divisor, c_expr);
if divisor_range.minValue <= -1 and divisor_range.maxValue >= -1 then
incr(countOverflowChecks);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "==-1)?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
else
countOverflowOptimizations(c_expr);
end if;
if check_int_div_by_zero then
if divisor_range.minValue <= 0 and divisor_range.maxValue >= 0 then
incr(countDivisionChecks);
c_expr.expr &:= "divChk(";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":";
else
countDivisionOptimizations(c_expr);
end if;
end if;
c_expr.expr &:= integerLiteral(dividend);
c_expr.expr &:= " / ";
c_expr.expr &:= divisor_name;
c_expr.expr &:= ")";
end if;
else
if dividend = integer.first then
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
end if;
if check_int_div_by_zero then
if divisor_range.minValue <= 0 and divisor_range.maxValue >= 0 then
incr(countDivisionChecks);
c_expr.expr &:= "(";
divisor_name := getParameterAsVariable("intType", "divisor_", divisor, c_expr);
c_expr.expr &:= "divChk(";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= integerLiteral(dividend);
c_expr.expr &:= " / ";
c_expr.expr &:= divisor_name;
c_expr.expr &:= ")";
else
countDivisionOptimizations(c_expr);
c_expr.expr &:= integerLiteral(dividend);
c_expr.expr &:= " / (";
process_expr(divisor, c_expr);
c_expr.expr &:= ")";
end if;
else
c_expr.expr &:= integerLiteral(dividend);
c_expr.expr &:= " / (";
process_expr(divisor, c_expr);
c_expr.expr &:= ")";
end if;
end if;
end func;
const proc: process (INT_DIV, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var string: dividend_name is "";
var string: divisor_name is "";
var intRange: dividend_range is intRange.value;
var intRange: divisor_range is intRange.value;
begin
if getConstant(params[3], INTOBJECT, evaluatedParam) then
process_const_int_div(params[1], getValue(evaluatedParam, integer), c_expr);
elsif getConstant(params[1], INTOBJECT, evaluatedParam) then
process_const_int_div(getValue(evaluatedParam, integer), params[3], c_expr);
elsif evaluate_const_expr = 0 and
category(params[3]) = INTOBJECT and not isVar(params[3]) and
getValue(params[3], integer) = 0 then
warning(DOES_RAISE, "NUMERIC_ERROR", c_expr);
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
elsif evaluate_const_expr = 0 and check_int_div_zero_by_zero and
category(params[1]) = INTOBJECT and not isVar(params[1]) and
getValue(params[1], integer) = 0 then
incr(countDivisionChecks);
c_expr.expr &:= "(divChk((";
process_expr(params[3], c_expr);
c_expr.expr &:= ")==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":0)";
else
divisor_range := getIntRange(params[3]);
if params[1] = params[3] then
if integer_division_check then
if (divisor_range.minValue <= 0 and divisor_range.maxValue >= 0) or
divisor_range.mayRaiseException then
incr(countDivisionChecks);
c_expr.expr &:= "(divChk((";
process_expr(params[1], c_expr);
c_expr.expr &:= ")==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":1)";
else
countDivisionOptimizations(c_expr);
c_expr.expr &:= "1";
end if;
else
c_expr.expr &:= "1";
end if;
elsif check_int_division_overflow then
dividend_range := getIntRange(params[1]);
if (dividend_range.minValue > integer.first or
divisor_range.maxValue < -1 or divisor_range.minValue > -1) and
(not check_int_div_by_zero or
divisor_range.maxValue < 0 or divisor_range.minValue > 0) then
countOverflowOptimizations(c_expr);
if check_int_div_by_zero then
countDivisionOptimizations(c_expr);
end if;
c_expr.expr &:= "(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") / (";
process_expr(params[3], c_expr);
c_expr.expr &:= ")";
else
c_expr.expr &:= "(";
dividend_name := getParameterAsVariable("intType", "dividend_", params[1], c_expr);
divisor_name := getParameterAsVariable("intType", "divisor_", params[3], c_expr);
if dividend_range.minValue = integer.first and
divisor_range.minValue <= -1 and divisor_range.maxValue >= -1 then
incr(countOverflowChecks);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= dividend_name;
c_expr.expr &:= "==";
c_expr.expr &:= integerLiteral(integer.first);
c_expr.expr &:= "&&";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "==-1";
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
else
countOverflowOptimizations(c_expr);
end if;
if check_int_div_by_zero then
if divisor_range.minValue <= 0 and divisor_range.maxValue >= 0 then
incr(countDivisionChecks);
c_expr.expr &:= "divChk(";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":";
else
countDivisionOptimizations(c_expr);
end if;
end if;
c_expr.expr &:= dividend_name;
c_expr.expr &:= " / ";
c_expr.expr &:= divisor_name;
c_expr.expr &:= ")";
end if;
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
if check_int_div_by_zero then
if divisor_range.minValue <= 0 and divisor_range.maxValue >= 0 then
incr(countDivisionChecks);
c_expr.expr &:= "(";
divisor_name := getParameterAsVariable("intType", "divisor_", params[3], c_expr);
c_expr.expr &:= "divChk(";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") / ";
c_expr.expr &:= divisor_name;
c_expr.expr &:= ")";
else
countDivisionOptimizations(c_expr);
c_expr.expr &:= "(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") / (";
process_expr(params[3], c_expr);
c_expr.expr &:= ")";
end if;
else
c_expr.expr &:= "(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") / (";
process_expr(params[3], c_expr);
c_expr.expr &:= ")";
end if;
end if;
end if;
end func;
const proc: process (INT_EQ, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var intRange: number1Range is intRange.value;
var intRange: number2Range is intRange.value;
var boolean: doCompare is TRUE;
begin
if optimizeComparisons then
number1Range := getIntRange(params[1]);
number2Range := getIntRange(params[3]);
if not number1Range.mayRaiseException and not number2Range.mayRaiseException then
if number1Range.minValue = number1Range.maxValue and
number2Range.minValue = number2Range.maxValue and
number1Range.minValue = number2Range.minValue then
warning(COMPARISON_RESULT_CONSTANT, "=", TRUE, c_expr);
incr(countOptimizations);
c_expr.expr &:= "1";
doCompare := FALSE;
elsif number1Range.maxValue < number2Range.minValue or
number1Range.minValue > number2Range.maxValue then
warning(COMPARISON_RESULT_CONSTANT, "=", FALSE, c_expr);
incr(countOptimizations);
c_expr.expr &:= "0";
doCompare := FALSE;
end if;
end if;
end if;
if doCompare then
c_expr.expr &:= "(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") == (";
process_expr(params[3], c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: process (INT_FACT, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var integer: number is 0;
var integer: limit is 0;
var string: number_name is "";
begin
if getConstant(params[2], INTOBJECT, evaluatedParam) then
number := getValue(evaluatedParam, integer);
if ccConf.INTTYPE_SIZE = 64 then
limit := 20;
else
limit := 12;
end if;
if number < 0 or number > limit then
warning(DOES_RAISE, "NUMERIC_ERROR", c_expr);
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
else
c_expr.expr &:= integerLiteral(!number);
end if;
else
c_expr.expr &:= "(";
number_name := getParameterAsVariable("intType", "number_", params[2], c_expr);
c_expr.expr &:= "numChk(";
checkRangeFromZero(number_name, "sizeof(fact)/sizeof(intType)", c_expr);
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":fact[";
c_expr.expr &:= number_name;
c_expr.expr &:= "])";
end if;
end func;
const proc: process (INT_GE, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var intRange: number1Range is intRange.value;
var intRange: number2Range is intRange.value;
var boolean: doCompare is TRUE;
begin
if optimizeComparisons then
number1Range := getIntRange(params[1]);
number2Range := getIntRange(params[3]);
if not number1Range.mayRaiseException and not number2Range.mayRaiseException then
if number1Range.minValue >= number2Range.maxValue then
warning(COMPARISON_RESULT_CONSTANT, ">=", TRUE, c_expr);
incr(countOptimizations);
c_expr.expr &:= "1";
doCompare := FALSE;
elsif number1Range.maxValue < number2Range.minValue then
warning(COMPARISON_RESULT_CONSTANT, ">=", FALSE, c_expr);
incr(countOptimizations);
c_expr.expr &:= "0";
doCompare := FALSE;
end if;
end if;
end if;
if doCompare then
c_expr.expr &:= "(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") >= (";
process_expr(params[3], c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: process (INT_GT, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var intRange: number1Range is intRange.value;
var intRange: number2Range is intRange.value;
var boolean: doCompare is TRUE;
begin
if optimizeComparisons then
number1Range := getIntRange(params[1]);
number2Range := getIntRange(params[3]);
if not number1Range.mayRaiseException and not number2Range.mayRaiseException then
if number1Range.minValue > number2Range.maxValue then
warning(COMPARISON_RESULT_CONSTANT, ">", TRUE, c_expr);
incr(countOptimizations);
c_expr.expr &:= "1";
doCompare := FALSE;
elsif number1Range.maxValue <= number2Range.minValue then
warning(COMPARISON_RESULT_CONSTANT, ">", FALSE, c_expr);
incr(countOptimizations);
c_expr.expr &:= "0";
doCompare := FALSE;
end if;
end if;
end if;
if doCompare then
c_expr.expr &:= "(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") > (";
process_expr(params[3], c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: process (INT_HASHCODE, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
c_expr.expr &:= "(";
process_expr(params[1], c_expr);
c_expr.expr &:= ")";
end func;
const proc: process (INT_ICONV1, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
c_expr.expr &:= "(";
process_expr(params[1], c_expr);
c_expr.expr &:= ")";
end func;
const proc: process (INT_ICONV3, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
c_expr.expr &:= "(";
process_expr(params[3], c_expr);
c_expr.expr &:= ")";
end func;
const proc: process (INT_INCR, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var expr_type: c_param1 is expr_type.value;
var string: variable_name is "";
var expr_type: statement is expr_type.value;
begin
if check_int_arithmetic_overflow then
incr(countOverflowChecks);
if isNormalVariable(params[1]) then
process_expr(params[1], c_param1);
statement.expr &:= "if (ovfChk(";
statement.expr &:= c_param1.expr;
statement.expr &:= "==";
statement.expr &:= integerLiteral(integer.last);
statement.expr &:= ")) {";
statement.expr &:= raiseError("OVERFLOW_ERROR");
statement.expr &:= "} else ++(";
statement.expr &:= c_param1.expr;
statement.expr &:= ");\n";
else
incr(statement.temp_num);
variable_name := "var_" & str(statement.temp_num);
statement.temp_decls &:= "intType *";
statement.temp_decls &:= variable_name;
statement.temp_decls &:= ";\n";
statement.expr &:= variable_name;
statement.expr &:= "=&(";
process_expr(params[1], statement);
statement.expr &:= ");\n";
statement.expr &:= "if (ovfChk(*";
statement.expr &:= variable_name;
statement.expr &:= "==";
statement.expr &:= integerLiteral(integer.last);
statement.expr &:= ")) {";
statement.expr &:= raiseError("OVERFLOW_ERROR");
statement.expr &:= "} else ++(*";
statement.expr &:= variable_name;
statement.expr &:= ");\n";
end if;
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
statement.expr &:= "++(";
process_expr(params[1], statement);
statement.expr &:= ");\n";
end if;
doLocalDeclsOfStatement(statement, c_expr);
end func;
const proc: process (INT_LE, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var intRange: number1Range is intRange.value;
var intRange: number2Range is intRange.value;
var boolean: doCompare is TRUE;
begin
if optimizeComparisons then
number1Range := getIntRange(params[1]);
number2Range := getIntRange(params[3]);
if not number1Range.mayRaiseException and not number2Range.mayRaiseException then
if number1Range.maxValue <= number2Range.minValue then
warning(COMPARISON_RESULT_CONSTANT, "<=", TRUE, c_expr);
incr(countOptimizations);
c_expr.expr &:= "1";
doCompare := FALSE;
elsif number1Range.minValue > number2Range.maxValue then
warning(COMPARISON_RESULT_CONSTANT, "<=", FALSE, c_expr);
incr(countOptimizations);
c_expr.expr &:= "0";
doCompare := FALSE;
end if;
end if;
end if;
if doCompare then
c_expr.expr &:= "(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") <= (";
process_expr(params[3], c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: process (INT_LOG10, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
c_expr.expr &:= "intLog10(";
process_expr(params[1], c_expr);
c_expr.expr &:= ")";
end func;
const proc: process (INT_LOG2, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
c_expr.expr &:= "intLog2(";
process_expr(params[1], c_expr);
c_expr.expr &:= ")";
end func;
const proc: process (INT_LOWEST_SET_BIT, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
c_expr.expr &:= "intLowestSetBit(";
process_expr(params[1], c_expr);
c_expr.expr &:= ")";
end func;
const proc: process (INT_LPAD0, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
begin
if getConstant(params[3], INTOBJECT, evaluatedParam) and
getValue(evaluatedParam, integer) <= 1 then
incr(countOptimizations);
process_int_str(params[1], c_expr);
else
prepare_stri_result(c_expr);
c_expr.result_expr := "intLpad0(";
getStdParamToResultExpr(params[1], c_expr);
c_expr.result_expr &:= ",";
getStdParamToResultExpr(params[3], c_expr);
c_expr.result_expr &:= ")";
end if;
end func;
const proc: process_const_int_lshift (in reference: number, in integer: lshift,
inout expr_type: c_expr) is func
local
var reference: evaluatedNumber is NIL;
var integer: number_value is 0;
var intRange: number_range is intRange.value;
var string: number_name is "";
var integer: minAllowedNumber is 0;
var integer: maxAllowedNumber is 0;
var boolean: fullOverflowCheck is FALSE;
begin
if lshift < 0 or lshift >= ccConf.INTTYPE_SIZE then
incr(countOptimizations);
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
elsif getConstant(number, INTOBJECT, evaluatedNumber) then
incr(countOptimizations);
number_value := getValue(evaluatedNumber, integer);
if number_value < integer.first >> lshift or
number_value > integer.last >> lshift then
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
else
c_expr.expr &:= integerLiteral(number_value << lshift);
end if;
elsif lshift = 0 then
incr(countOptimizations);
process_expr(number, c_expr);
elsif check_int_shift_overflow then
incr(countOptimizations);
minAllowedNumber := integer.first >> lshift;
maxAllowedNumber := integer.last >> lshift;
number_range := getIntRange(number);
if number_range <> intRange.value then
if number_range.minValue >= minAllowedNumber and
number_range.maxValue <= maxAllowedNumber then
countOverflowOptimizations(c_expr);
c_expr.expr &:= "/*no_overflow_check_lshift*/(";
process_expr(number, c_expr);
c_expr.expr &:= ") << ";
c_expr.expr &:= integerLiteral(lshift);
elsif number_range.minValue >= minAllowedNumber or
number_range.maxValue <= maxAllowedNumber then
incr(countOverflowChecks);
c_expr.expr &:= "/*simplified_overflow_check_lshift*/(";
number_name := getParameterAsVariable("intType", "number_", number, c_expr);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= number_name;
if number_range.minValue >= minAllowedNumber then
c_expr.expr &:= ">";
c_expr.expr &:= integerLiteral(maxAllowedNumber);
else
c_expr.expr &:= "<";
c_expr.expr &:= integerLiteral(minAllowedNumber);
end if;
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= number_name;
c_expr.expr &:= " << ";
c_expr.expr &:= integerLiteral(lshift);
c_expr.expr &:= ")";
else
fullOverflowCheck := TRUE;
end if;
else
fullOverflowCheck := TRUE;
end if;
if fullOverflowCheck then
incr(countOverflowChecks);
c_expr.expr &:= "(";
number_name := getParameterAsVariable("intType", "number_", number, c_expr);
c_expr.expr &:= "ovfChk(";
checkIfOutsideRange(number_name, minAllowedNumber,
maxAllowedNumber, c_expr);
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= number_name;
c_expr.expr &:= " << ";
c_expr.expr &:= integerLiteral(lshift);
c_expr.expr &:= ")";
end if;
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
c_expr.expr &:= "(";
process_expr(number, c_expr);
c_expr.expr &:= ") << ";
c_expr.expr &:= integerLiteral(lshift);
end if;
end func;
const proc: optimize_int_lshift_by_sum (in integer: number, in reference: lshift,
in integer: deltaLshift, inout expr_type: c_expr) is func
local
var string: lshift_name is "";
begin
writeln(c_expr.currentFile <& "(" <& c_expr.currentLine <& ")");
c_expr.expr &:= "(";
lshift_name := defineTempVariable("uintType", "lshift_", c_expr);
c_expr.expr &:= lshift_name;
c_expr.expr &:= "=(uintType)(";
process_expr(lshift, c_expr);
c_expr.expr &:= ")";
if deltaLshift > 0 or deltaLshift = integer.first then
c_expr.expr &:= "+(uintType)";
c_expr.expr &:= integerLiteral(deltaLshift);
elsif deltaLshift < 0 then
c_expr.expr &:= "-(uintType)";
c_expr.expr &:= integerLiteral(-deltaLshift);
end if;
c_expr.expr &:= ",";
c_expr.expr &:= "ovfChk(";
checkRangeFromZero(lshift_name,
integerLiteral(ccConf.INTTYPE_SIZE - bitLength(number)), c_expr);
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
if number = 0 then
c_expr.expr &:= integerLiteral(0);
else
c_expr.expr &:= integerLiteral(number);
c_expr.expr &:= " << ";
c_expr.expr &:= lshift_name;
end if;
c_expr.expr &:= ")";
end func;
const proc: process_const_int_lshift (in integer: number, in reference: lshift,
inout expr_type: c_expr) is func
local
var string: lshift_name is "";
var intRange: lshift_range is intRange.value;
var boolean: raisesException is FALSE;
var boolean: doOverflowCheck is FALSE;
var reference: evaluatedDelta is NIL;
begin
if check_int_shift_overflow then
lshift_range := getIntRange(lshift);
if lshift_range.maxValue < 0 or
lshift_range.minValue >= ccConf.INTTYPE_SIZE - bitLength(number) then
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
raisesException := TRUE;
elsif lshift_range.minValue >= 0 and
lshift_range.maxValue < ccConf.INTTYPE_SIZE - bitLength(number) then
countOverflowOptimizations(c_expr);
c_expr.expr &:= "/*no_overflow_check_lshift*/";
else
incr(countOverflowChecks);
doOverflowCheck := TRUE;
end if;
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
end if;
if not raisesException then
if doOverflowCheck then
c_expr.expr &:= "(";
lshift_name := getParameterAsVariable("intType", "lshift_", lshift, c_expr);
c_expr.expr &:= "ovfChk(";
checkRangeFromZero(lshift_name,
integerLiteral(ccConf.INTTYPE_SIZE - bitLength(number)), c_expr);
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
if number = 0 then
c_expr.expr &:= integerLiteral(0);
else
c_expr.expr &:= integerLiteral(number);
c_expr.expr &:= " << ";
c_expr.expr &:= lshift_name;
end if;
c_expr.expr &:= ")";
else
if number = 0 then
c_expr.expr &:= integerLiteral(0);
else
c_expr.expr &:= integerLiteral(number);
c_expr.expr &:= " << (";
process_expr(lshift, c_expr);
c_expr.expr &:= ")";
end if;
end if;
end if;
end func;
const proc: process (INT_LSHIFT, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var string: number_name is "";
var string: lshift_name is "";
var intRange: number_range is intRange.value;
var intRange: lshift_range is intRange.value;
var boolean: fullOverflowCheck is FALSE;
var reference: evaluatedDelta is NIL;
begin
if getConstant(params[3], INTOBJECT, evaluatedParam) then
process_const_int_lshift(params[1], getValue(evaluatedParam, integer), c_expr);
elsif getConstant(params[1], INTOBJECT, evaluatedParam) then
process_const_int_lshift(getValue(evaluatedParam, integer), params[3], c_expr);
elsif check_int_shift_overflow then
if isActionExpression(params[3], "INT_ADD") and
getConstant(getActionParameter(params[3], 1), INTOBJECT, evaluatedDelta) then
writeln(c_expr.currentFile <& "(" <& c_expr.currentLine <& ")");
elsif isActionExpression(params[3], "INT_ADD") and
getConstant(getActionParameter(params[3], 3), INTOBJECT, evaluatedDelta) then
writeln(c_expr.currentFile <& "(" <& c_expr.currentLine <& ")");
elsif isActionExpression(params[3], "INT_SBTR") and
getConstant(getActionParameter(params[3], 1), INTOBJECT, evaluatedDelta) and
getValue(evaluatedDelta, integer) <> integer.first then
writeln(c_expr.currentFile <& "(" <& c_expr.currentLine <& ")");
elsif isActionExpression(params[3], "INT_SBTR") and
getConstant(getActionParameter(params[3], 3), INTOBJECT, evaluatedDelta) and
getValue(evaluatedDelta, integer) <> integer.first then
writeln(c_expr.currentFile <& "(" <& c_expr.currentLine <& ")");
elsif isActionExpression(params[3], "INT_SUCC") then
writeln(c_expr.currentFile <& "(" <& c_expr.currentLine <& ")");
elsif isActionExpression(params[3], "INT_PRED") then
writeln(c_expr.currentFile <& "(" <& c_expr.currentLine <& ")");
end if;
number_range := getIntRange(params[1]);
lshift_range := getIntRange(params[3]);
if lshift_range.maxValue < 0 or
lshift_range.minValue >= ccConf.INTTYPE_SIZE or
(lshift_range.minValue >= 0 and
lshift_range.minValue < ccConf.INTTYPE_SIZE and
(integer.first >> lshift_range.minValue > number_range.maxValue or
integer.last >> lshift_range.minValue < number_range.minValue)) then
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
elsif lshift_range.maxValue >= 0 and
lshift_range.maxValue < ccConf.INTTYPE_SIZE and
integer.first >> lshift_range.maxValue <= number_range.minValue and
integer.last >> lshift_range.maxValue >= number_range.maxValue then
if lshift_range.minValue >= 0 then
countOverflowOptimizations(c_expr);
c_expr.expr &:= "/*no_overflow_check_lshift*/(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") << (";
process_expr(params[3], c_expr);
c_expr.expr &:= ")";
else
incr(countOverflowChecks);
c_expr.expr &:= "(";
lshift_name := getParameterAsVariable("intType", "lshift_", params[3], c_expr);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= lshift_name;
c_expr.expr &:= "<0)?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") << ";
c_expr.expr &:= lshift_name;
c_expr.expr &:= ")";
end if;
else
fullOverflowCheck := TRUE;
end if;
if fullOverflowCheck then
incr(countOverflowChecks);
c_expr.expr &:= "(";
number_name := getParameterAsVariable("intType", "number_", params[1], c_expr);
lshift_name := getParameterAsVariable("intType", "lshift_", params[3], c_expr);
c_expr.expr &:= "ovfChk(";
if lshift_range.minValue < 0 or
lshift_range.maxValue >= ccConf.INTTYPE_SIZE then
checkRangeFromZero(lshift_name, integerLiteral(ccConf.INTTYPE_SIZE), c_expr);
c_expr.expr &:= "||";
else
countOverflowOptimizations(c_expr);
end if;
c_expr.expr &:= number_name;
c_expr.expr &:= "<";
if ccConf.RSHIFT_DOES_SIGN_EXTEND then
c_expr.expr &:= integerLiteral(integer.first);
c_expr.expr &:= ">>";
c_expr.expr &:= lshift_name;
else
c_expr.expr &:= "~(~";
c_expr.expr &:= integerLiteral(integer.first);
c_expr.expr &:= ">>";
c_expr.expr &:= lshift_name;
c_expr.expr &:= ")";
end if;
c_expr.expr &:= "||";
c_expr.expr &:= number_name;
c_expr.expr &:= ">";
c_expr.expr &:= integerLiteral(integer.last);
c_expr.expr &:= ">>";
c_expr.expr &:= lshift_name;
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= number_name;
c_expr.expr &:= " << ";
c_expr.expr &:= lshift_name;
c_expr.expr &:= ")";
end if;
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
c_expr.expr &:= "(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") << (";
process_expr(params[3], c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: process_const_int_lshift_assign (in reference: variable, in integer: lshift,
inout expr_type: c_expr) is func
local
var string: variable_name is "";
var expr_type: statement is expr_type.value;
begin
if lshift < 0 or lshift >= ccConf.INTTYPE_SIZE then
incr(countOptimizations);
setDiagnosticLine(c_expr);
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= raiseError("OVERFLOW_ERROR");
elsif lshift = 0 then
incr(countOptimizations);
c_expr.expr &:= "/* ignore integer <<:= 0; */\n";
elsif check_int_shift_overflow then
incr(countOptimizations);
incr(countOverflowChecks);
variable_name := getParameterAsReference("intType", "variable_", variable, statement);
statement.expr &:= "if (ovfChk(";
checkIfOutsideRange(variable_name, integer.first >> lshift,
integer.last >> lshift, statement);
statement.expr &:= ")) {\n";
statement.expr &:= raiseError("OVERFLOW_ERROR");
statement.expr &:= "} else {\n";
statement.expr &:= variable_name;
statement.expr &:= "<<=";
statement.expr &:= integerLiteral(lshift);
statement.expr &:= ";\n";
statement.expr &:= "}\n";
doLocalDeclsOfStatement(statement, c_expr);
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
process_expr(variable, statement);
statement.expr &:= "<<=";
statement.expr &:= integerLiteral(lshift);
statement.expr &:= ";\n";
doLocalDeclsOfStatement(statement, c_expr);
end if;
end func;
const proc: process (INT_LSHIFT_ASSIGN, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var string: variable_name is "";
var string: lshift_name is "";
var expr_type: statement is expr_type.value;
begin
if getConstant(params[3], INTOBJECT, evaluatedParam) then
process_const_int_lshift_assign(params[1], getValue(evaluatedParam, integer), c_expr);
elsif check_int_shift_overflow then
incr(countOverflowChecks);
variable_name := getParameterAsReference("intType", "variable_", params[1], statement);
lshift_name := getParameterAsVariable("intType", "lshift_", params[3], statement);
statement.expr &:= "ovfChk(";
checkRangeFromZero(lshift_name, integerLiteral(ccConf.INTTYPE_SIZE), statement);
statement.expr &:= "||";
statement.expr &:= variable_name;
statement.expr &:= "<";
if ccConf.RSHIFT_DOES_SIGN_EXTEND then
statement.expr &:= integerLiteral(integer.first);
statement.expr &:= ">>";
statement.expr &:= lshift_name;
else
statement.expr &:= "~(~";
statement.expr &:= integerLiteral(integer.first);
statement.expr &:= ">>";
statement.expr &:= lshift_name;
statement.expr &:= ")";
end if;
statement.expr &:= "||";
statement.expr &:= variable_name;
statement.expr &:= ">";
statement.expr &:= integerLiteral(integer.last);
statement.expr &:= ">>";
statement.expr &:= lshift_name;
statement.expr &:= ")?";
statement.expr &:= intRaiseError("OVERFLOW_ERROR");
statement.expr &:= ":(";
statement.expr &:= variable_name;
statement.expr &:= "<<=";
statement.expr &:= lshift_name;
statement.expr &:= ");\n";
doLocalDeclsOfStatement(statement, c_expr);
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
process_expr(params[1], statement);
statement.expr &:= "<<=";
process_expr(params[3], statement);
statement.expr &:= ";\n";
doLocalDeclsOfStatement(statement, c_expr);
end if;
end func;
const proc: process (INT_LT, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var intRange: number1Range is intRange.value;
var intRange: number2Range is intRange.value;
var boolean: doCompare is TRUE;
begin
if optimizeComparisons then
number1Range := getIntRange(params[1]);
number2Range := getIntRange(params[3]);
if not number1Range.mayRaiseException and not number2Range.mayRaiseException then
if number1Range.maxValue < number2Range.minValue then
warning(COMPARISON_RESULT_CONSTANT, "<", TRUE, c_expr);
incr(countOptimizations);
c_expr.expr &:= "1";
doCompare := FALSE;
elsif number1Range.minValue >= number2Range.maxValue then
warning(COMPARISON_RESULT_CONSTANT, "<", FALSE, c_expr);
incr(countOptimizations);
c_expr.expr &:= "0";
doCompare := FALSE;
end if;
end if;
end if;
if doCompare then
c_expr.expr &:= "(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") < (";
process_expr(params[3], c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: process_const_int_mdiv (in reference: dividend, in integer: divisor,
inout expr_type: c_expr) is forward;
const func boolean: optimize_mdiv_of_product (in reference: number, in integer: factor,
in integer: divisor, inout expr_type: c_expr) is func
result
var boolean: done is TRUE;
begin
if factor = 0 then
incr(countOptimizations);
c_expr.expr &:= "0";
elsif factor = divisor then
incr(countOptimizations);
countOverflowOptimizations(c_expr);
process_expr(number, c_expr);
elsif factor mod divisor = 0 then
incr(countOptimizations);
process_const_int_mult(number, factor mdiv divisor, c_expr);
elsif divisor mod factor = 0 then
incr(countOptimizations);
countOverflowOptimizations(c_expr);
process_const_int_mdiv(number, divisor mdiv factor, c_expr);
else
done := FALSE;
end if;
end func;
const proc: process_const_int_mdiv (in reference: dividend, in integer: divisor,
inout expr_type: c_expr) is func
local
var reference: evaluatedDividend is NIL;
var reference: evaluatedFactor is NIL;
var integer: dividend_value is 0;
var string: dividend_name is "";
var intRange: dividend_range is intRange.value;
var boolean: done is TRUE;
begin
incr(countOptimizations);
if divisor = 0 then
warning(DOES_RAISE, "NUMERIC_ERROR", c_expr);
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
elsif getConstant(dividend, INTOBJECT, evaluatedDividend) then
dividend_value := getValue(evaluatedDividend, integer);
if divisor = -1 and dividend_value < -integer.last then
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
else
c_expr.expr &:= integerLiteral(dividend_value mdiv divisor);
end if;
elsif divisor = 1 then
c_expr.expr &:= "(";
process_expr(dividend, c_expr);
c_expr.expr &:= ")";
elsif isActionExpression(dividend, "INT_MULT") and
getConstant(getActionParameter(dividend, 3), INTOBJECT, evaluatedFactor) then
done := optimize_mdiv_of_product(getActionParameter(dividend, 1),
getValue(evaluatedFactor, integer), divisor, c_expr);
elsif isActionExpression(dividend, "INT_MULT") and
getConstant(getActionParameter(dividend, 1), INTOBJECT, evaluatedFactor) then
done := optimize_mdiv_of_product(getActionParameter(dividend, 3),
getValue(evaluatedFactor, integer), divisor, c_expr);
else
done := FALSE;
end if;
if not done then
if divisor = -1 then
negate(dividend, c_expr);
elsif divisor > 0 and 2 ** log2(divisor) = divisor then
if ccConf.RSHIFT_DOES_SIGN_EXTEND then
c_expr.expr &:= "(";
process_expr(dividend, c_expr);
c_expr.expr &:= ") >> ";
c_expr.expr &:= integerLiteral(log2(divisor));
else
c_expr.expr &:= "(";
dividend_name := getParameterAsVariable("intType", "dividend_", dividend, c_expr);
doRshift(dividend_name, integerLiteral(log2(divisor)), c_expr);
c_expr.expr &:= ")";
end if;
elsif divisor < 0 and bitLength(divisor) = lowestSetBit(divisor) then
dividend_range := getIntRange(dividend);
if ccConf.TWOS_COMPLEMENT_INTTYPE then
c_expr.expr &:= "(";
dividend_name := getParameterAsVariable("intType", "dividend_", dividend, c_expr);
if dividend_range.minValue = integer.first then
c_expr.expr &:= dividend_name;
c_expr.expr &:= "==";
c_expr.expr &:= integerLiteral(integer.first);
c_expr.expr &:= "?";
c_expr.expr &:= integerLiteral(-(integer.first >> 1) >> pred(bitLength(divisor)));
c_expr.expr &:= ":";
end if;
if ccConf.RSHIFT_DOES_SIGN_EXTEND then
c_expr.expr &:= "-";
c_expr.expr &:= dividend_name;
c_expr.expr &:= " >> ";
c_expr.expr &:= integerLiteral(bitLength(divisor));
else
c_expr.expr &:= "(";
c_expr.expr &:= dividend_name;
c_expr.expr &:= "=-";
c_expr.expr &:= dividend_name;
c_expr.expr &:= ",";
doRshift(dividend_name, integerLiteral(bitLength(divisor)), c_expr);
c_expr.expr &:= ")";
end if;
c_expr.expr &:= ")";
else
if ccConf.RSHIFT_DOES_SIGN_EXTEND then
c_expr.expr &:= "-(";
process_expr(dividend, c_expr);
c_expr.expr &:= ") >> ";
c_expr.expr &:= integerLiteral(bitLength(divisor));
else
dividend_name := defineTempVariable("intType", "dividend_", c_expr);
c_expr.expr &:= "(";
c_expr.expr &:= dividend_name;
c_expr.expr &:= "=-(";
process_expr(dividend, c_expr);
c_expr.expr &:= "),";
doRshift(dividend_name, integerLiteral(bitLength(divisor)), c_expr);
c_expr.expr &:= ")";
end if;
end if;
else
dividend_range := getIntRange(dividend);
if divisor > 0 and dividend_range.minValue >= 0 or
divisor < 0 and dividend_range.maxValue <= 0 then
c_expr.expr &:= "(";
process_expr(dividend, c_expr);
c_expr.expr &:= ")/";
c_expr.expr &:= integerLiteral(divisor);
elsif divisor > 0 and dividend_range.maxValue < 0 then
c_expr.expr &:= "((";
process_expr(dividend, c_expr);
c_expr.expr &:= ")+1)/";
c_expr.expr &:= integerLiteral(divisor);
c_expr.expr &:= "-1";
elsif divisor < 0 and dividend_range.minValue > 0 then
c_expr.expr &:= "((";
process_expr(dividend, c_expr);
c_expr.expr &:= ")-1)/";
c_expr.expr &:= integerLiteral(divisor);
c_expr.expr &:= "-1";
else
c_expr.expr &:= "(";
dividend_name := getParameterAsVariable("intType", "dividend_", dividend, c_expr);
c_expr.expr &:= dividend_name;
if divisor > 0 then
c_expr.expr &:= "<0?(";
c_expr.expr &:= dividend_name;
c_expr.expr &:= "+1)/";
c_expr.expr &:= integerLiteral(divisor);
c_expr.expr &:= "-1:";
else
c_expr.expr &:= ">0?(";
c_expr.expr &:= dividend_name;
c_expr.expr &:= "-1)/";
c_expr.expr &:= integerLiteral(divisor);
c_expr.expr &:= "-1:";
end if;
c_expr.expr &:= dividend_name;
c_expr.expr &:= "/";
c_expr.expr &:= integerLiteral(divisor);
c_expr.expr &:= ")";
end if;
end if;
end if;
end func;
const proc: process_const_int_mdiv (in integer: dividend, in reference: divisor,
inout expr_type: c_expr) is func
local
var string: divisor_name is "";
var intRange: divisor_range is intRange.value;
begin
incr(countOptimizations);
divisor_range := getIntRange(divisor);
if dividend = 0 then
if integer_division_check then
if (divisor_range.minValue <= 0 and divisor_range.maxValue >= 0) or
divisor_range.mayRaiseException then
incr(countDivisionChecks);
c_expr.expr &:= "(divChk((";
process_expr(divisor, c_expr);
c_expr.expr &:= ")==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":0)";
else
countDivisionOptimizations(c_expr);
c_expr.expr &:= "0";
end if;
else
c_expr.expr &:= "0";
end if;
elsif check_int_division_overflow and dividend = integer.first then
if divisor_range.maxValue < -1 then
countOverflowOptimizations(c_expr);
if check_int_div_by_zero then
countDivisionOptimizations(c_expr);
end if;
c_expr.expr &:= integerLiteral(dividend);
c_expr.expr &:= "/(";
process_expr(divisor, c_expr);
c_expr.expr &:= ")";
elsif divisor_range.minValue > 0 then
countOverflowOptimizations(c_expr);
if check_int_div_by_zero then
countDivisionOptimizations(c_expr);
end if;
c_expr.expr &:= integerLiteral(succ(dividend));
c_expr.expr &:= "/(";
process_expr(divisor, c_expr);
c_expr.expr &:= ")-1";
else
c_expr.expr &:= "(";
divisor_name := getParameterAsVariable("intType", "divisor_", divisor, c_expr);
if divisor_range.minValue <= -1 and divisor_range.maxValue >= -1 then
incr(countOverflowChecks);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "==-1)?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
else
countOverflowOptimizations(c_expr);
end if;
if divisor_range.maxValue > 0 then
c_expr.expr &:= divisor_name;
c_expr.expr &:= ">0?";
c_expr.expr &:= integerLiteral(succ(dividend));
c_expr.expr &:= "/";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "-1:";
end if;
if check_int_div_by_zero then
if divisor_range.minValue <= 0 and divisor_range.maxValue >= 0 then
incr(countDivisionChecks);
c_expr.expr &:= "divChk(";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":";
else
countDivisionOptimizations(c_expr);
end if;
end if;
c_expr.expr &:= integerLiteral(dividend);
c_expr.expr &:= "/";
c_expr.expr &:= divisor_name;
c_expr.expr &:= ")";
end if;
else
if dividend = integer.first then
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
end if;
if (dividend <= 0 and
((dividend > integer.first and divisor_range.maxValue < 0) or
divisor_range.maxValue < -1)) or
(dividend >= 0 and divisor_range.minValue > 0) then
c_expr.expr &:= integerLiteral(dividend);
c_expr.expr &:= "/(";
process_expr(divisor, c_expr);
c_expr.expr &:= ")";
elsif dividend > 0 and divisor_range.maxValue < 0 then
c_expr.expr &:= integerLiteral(pred(dividend));
c_expr.expr &:= "/(";
process_expr(divisor, c_expr);
c_expr.expr &:= ")-1";
elsif dividend < 0 and divisor_range.minValue > 0 then
c_expr.expr &:= integerLiteral(succ(dividend));
c_expr.expr &:= "/(";
process_expr(divisor, c_expr);
c_expr.expr &:= ")-1";
else
c_expr.expr &:= "(";
divisor_name := getParameterAsVariable("intType", "divisor_", divisor, c_expr);
if (dividend < 0 or divisor_range.minValue < 0) and
(dividend > 0 or divisor_range.maxValue > 0) then
c_expr.expr &:= divisor_name;
if dividend > 0 then
c_expr.expr &:= "<0?";
c_expr.expr &:= integerLiteral(pred(dividend));
else
c_expr.expr &:= ">0?";
c_expr.expr &:= integerLiteral(succ(dividend));
end if;
c_expr.expr &:= "/";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "-1:";
end if;
if check_int_div_by_zero then
if divisor_range.minValue <= 0 and divisor_range.maxValue >= 0 then
incr(countDivisionChecks);
c_expr.expr &:= "divChk(";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":";
else
countDivisionOptimizations(c_expr);
end if;
end if;
c_expr.expr &:= integerLiteral(dividend);
c_expr.expr &:= "/";
c_expr.expr &:= divisor_name;
c_expr.expr &:= ")";
end if;
end if;
end func;
const proc: process (INT_MDIV, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var string: dividend_name is "";
var string: divisor_name is "";
var intRange: dividend_range is intRange.value;
var intRange: divisor_range is intRange.value;
begin
if getConstant(params[3], INTOBJECT, evaluatedParam) then
process_const_int_mdiv(params[1], getValue(evaluatedParam, integer), c_expr);
elsif getConstant(params[1], INTOBJECT, evaluatedParam) then
process_const_int_mdiv(getValue(evaluatedParam, integer), params[3], c_expr);
elsif evaluate_const_expr = 0 and check_int_div_zero_by_zero and
category(params[1]) = INTOBJECT and not isVar(params[1]) and
getValue(params[1], integer) = 0 then
incr(countDivisionChecks);
c_expr.expr &:= "(divChk((";
process_expr(params[3], c_expr);
c_expr.expr &:= ")==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":0)";
else
divisor_range := getIntRange(params[3]);
if params[1] = params[3] then
if integer_division_check then
if (divisor_range.minValue <= 0 and divisor_range.maxValue >= 0) or
divisor_range.mayRaiseException then
incr(countDivisionChecks);
c_expr.expr &:= "(divChk((";
process_expr(params[1], c_expr);
c_expr.expr &:= ")==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":1)";
else
countDivisionOptimizations(c_expr);
c_expr.expr &:= "1";
end if;
else
c_expr.expr &:= "1";
end if;
else
dividend_range := getIntRange(params[1]);
if (dividend_range.maxValue <= 0 and
((dividend_range.minValue > integer.first and divisor_range.maxValue < 0) or
divisor_range.maxValue < -1)) or
(dividend_range.minValue >= 0 and divisor_range.minValue > 0) then
c_expr.expr &:= "(";
process_expr(params[1], c_expr);
c_expr.expr &:= ")/(";
process_expr(params[3], c_expr);
c_expr.expr &:= ")";
elsif dividend_range.minValue > 0 and divisor_range.maxValue < 0 then
if check_int_division_overflow then
countOverflowOptimizations(c_expr);
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
end if;
if check_int_div_by_zero then
countDivisionOptimizations(c_expr);
end if;
c_expr.expr &:= "((";
process_expr(params[1], c_expr);
c_expr.expr &:= ")-1)/(";
process_expr(params[3], c_expr);
c_expr.expr &:= ")-1";
elsif dividend_range.maxValue < 0 and divisor_range.minValue > 0 then
if check_int_division_overflow then
countOverflowOptimizations(c_expr);
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
end if;
if check_int_div_by_zero then
countDivisionOptimizations(c_expr);
end if;
c_expr.expr &:= "((";
process_expr(params[1], c_expr);
c_expr.expr &:= ")+1)/(";
process_expr(params[3], c_expr);
c_expr.expr &:= ")-1";
else
c_expr.expr &:= "(";
dividend_name := getParameterAsVariable("intType", "dividend_", params[1], c_expr);
divisor_name := getParameterAsVariable("intType", "divisor_", params[3], c_expr);
if dividend_range.maxValue > 0 and divisor_range.minValue < 0 then
if dividend_range.minValue <= 0 then
c_expr.expr &:= dividend_name;
c_expr.expr &:= ">0";
if divisor_range.maxValue >= 0 then
c_expr.expr &:= "&&";
end if;
end if;
if divisor_range.maxValue >= 0 then
c_expr.expr &:= divisor_name;
c_expr.expr &:= "<0";
end if;
c_expr.expr &:= "?(";
c_expr.expr &:= dividend_name;
c_expr.expr &:= "-1)/";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "-1:";
end if;
if dividend_range.minValue < 0 and divisor_range.maxValue > 0 then
if dividend_range.maxValue >= 0 then
c_expr.expr &:= dividend_name;
c_expr.expr &:= "<0";
if divisor_range.minValue <= 0 then
c_expr.expr &:= "&&";
end if;
end if;
if divisor_range.minValue <= 0 then
c_expr.expr &:= divisor_name;
c_expr.expr &:= ">0";
end if;
c_expr.expr &:= "?(";
c_expr.expr &:= dividend_name;
c_expr.expr &:= "+1)/";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "-1:";
end if;
if check_int_div_by_zero then
if divisor_range.minValue <= 0 and divisor_range.maxValue >= 0 then
incr(countDivisionChecks);
c_expr.expr &:= "divChk(";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":";
else
countDivisionOptimizations(c_expr);
end if;
end if;
if check_int_division_overflow then
if dividend_range.minValue = integer.first and
divisor_range.minValue <= -1 and divisor_range.maxValue >= -1 then
incr(countOverflowChecks);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= dividend_name;
c_expr.expr &:= "==";
c_expr.expr &:= integerLiteral(integer.first);
c_expr.expr &:= "&&";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "==-1";
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
else
countOverflowOptimizations(c_expr);
end if;
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
end if;
c_expr.expr &:= dividend_name;
c_expr.expr &:= "/";
c_expr.expr &:= divisor_name;
c_expr.expr &:= ")";
end if;
end if;
end if;
end func;
const proc: optimize_mod_of_left_shifted_value (in reference: argument,
in integer: lshift, in integer: bitsToMask, inout expr_type: c_expr) is func
begin
if lshift < 0 or lshift >= ccConf.INTTYPE_SIZE then
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
elsif lshift >= bitsToMask then
c_expr.expr &:= "0";
else
c_expr.expr &:= "/*mod_of_lshift*/ ((";
process_expr(argument, c_expr);
c_expr.expr &:= ")&";
c_expr.expr &:= integerLiteral(pred(2 ** (bitsToMask - lshift)));
c_expr.expr &:= ")<<";
c_expr.expr &:= integerLiteral(lshift);
end if;
end func;
const proc: optimize_mod_of_left_shifted_value (in reference: argument,
in reference: lshift, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var integer: lshift_value is 0;
var string: lshift_name is "";
var intRange: lshift_range is intRange.value;
begin
if getConstant(lshift, INTOBJECT, evaluatedParam) then
lshift_value := getValue(evaluatedParam, integer);
if lshift_value < 0 or lshift_value >= ccConf.INTTYPE_SIZE then
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
else
c_expr.expr &:= "((uintType)(";
process_expr(argument, c_expr);
c_expr.expr &:= ") << ";
c_expr.expr &:= integerLiteral(lshift_value);
c_expr.expr &:= ")";
end if;
elsif check_int_shift_overflow then
lshift_range := getIntRange(lshift);
if lshift_range.maxValue < 0 or
lshift_range.minValue >= ccConf.INTTYPE_SIZE then
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
elsif lshift_range.minValue >= 0 and
lshift_range.maxValue < ccConf.INTTYPE_SIZE then
countOverflowOptimizations(c_expr);
c_expr.expr &:= "/*no_overflow_check_lshift*/";
c_expr.expr &:= "((uintType)(";
process_expr(argument, c_expr);
c_expr.expr &:= ") << (";
process_expr(lshift, c_expr);
c_expr.expr &:= "))";
else
incr(countOverflowChecks);
c_expr.expr &:= "(";
lshift_name := getParameterAsVariable("intType", "lshift_", lshift, c_expr);
c_expr.expr &:= "ovfChk(";
checkRangeFromZero(lshift_name,
integerLiteral(ccConf.INTTYPE_SIZE), c_expr);
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= "((uintType)(";
process_expr(argument, c_expr);
c_expr.expr &:= ") << ";
c_expr.expr &:= lshift_name;
c_expr.expr &:= "))";
end if;
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
c_expr.expr &:= "((uintType)(";
process_expr(argument, c_expr);
c_expr.expr &:= ") << (";
process_expr(lshift, c_expr);
c_expr.expr &:= "))";
end if;
end func;
const proc: optimize_mod_of_product (in reference: factor1,
in reference: factor2, inout expr_type: c_expr) is func
begin
c_expr.expr &:= "(uintType)(";
process_expr(factor1, c_expr);
c_expr.expr &:= ")*(uintType)(";
process_expr(factor2, c_expr);
c_expr.expr &:= ")";
end func;
const proc: optimize_mod_of_sum (in addSubIntListType: addSubParamList,
inout expr_type: c_expr) is func
local
var integer: index is 1;
var bigInteger: constSummand is 0_;
var reference: summand is NIL;
begin
for key index range addSubParamList do
if addSubParamList[index].summand = NIL then
if addSubParamList[index].doAdd then
constSummand +:= bigInteger(addSubParamList[index].constSummand);
else
constSummand -:= bigInteger(addSubParamList[index].constSummand);
end if;
end if;
end for;
c_expr.expr &:= "/*mod_of_sum*/ ((intType) (";
for key index range addSubParamList do
if addSubParamList[index].summand <> NIL then
if addSubParamList[index].doAdd then
c_expr.expr &:= "+";
else
c_expr.expr &:= "-";
end if;
summand := addSubParamList[index].summand;
if isActionExpression(summand, "INT_MULT") then
optimize_mod_of_product(getValue(summand, ref_list)[2],
getValue(summand, ref_list)[4], c_expr);
elsif isActionExpression(summand, "INT_LSHIFT") then
optimize_mod_of_left_shifted_value(getValue(summand, ref_list)[2],
getValue(summand, ref_list)[4], c_expr);
else
c_expr.expr &:= "(uintType)(";
process_expr(summand, c_expr);
c_expr.expr &:= ")";
end if;
end if;
end for;
if constSummand >= 0_ then
constSummand := constSummand mod (2_ ** 63);
if constSummand <> 0_ then
c_expr.expr &:= "+(uintType)(";
c_expr.expr &:= integerLiteral(ord(constSummand));
c_expr.expr &:= ")";
end if;
else
constSummand := -constSummand mod (2_ ** 63);
if constSummand <> 0_ then
c_expr.expr &:= "-(uintType)(";
c_expr.expr &:= integerLiteral(ord(constSummand));
c_expr.expr &:= ")";
end if;
end if;
c_expr.expr &:= "))";
end func;
const proc: optimize_mod_of_sum (in ref_list: params, in boolean: doAdd,
inout expr_type: c_expr) is func
local
var addSubIntListType: addSubParamList is 0 times addSubIntElementType.value;
begin
addSubParamList := getAddSubParamList(params, doAdd);
evaluateConstants(addSubParamList);
optimize_mod_of_sum(addSubParamList, c_expr);
end func;
const proc: optimize_mod_of_sum (in reference: summand1, in integer: summand2,
inout expr_type: c_expr) is func
local
var addSubIntListType: addSubParamList is 0 times addSubIntElementType.value;
begin
addSubParamList := getAddSubParamList(summand1, summand2);
evaluateConstants(addSubParamList);
optimize_mod_of_sum(addSubParamList, c_expr);
end func;
const proc: optimize_mod_dividend (in reference: dividend, inout expr_type: c_expr) is func
begin
if isActionExpression(dividend, "INT_MULT") then
c_expr.expr &:= "/*mod_of_product*/ ((intType) (";
optimize_mod_of_product(getValue(dividend, ref_list)[2],
getValue(dividend, ref_list)[4], c_expr);
c_expr.expr &:= "))";
elsif isActionExpression(dividend, "INT_LSHIFT") then
c_expr.expr &:= "/*mod_of_lshift*/ ((intType) (";
optimize_mod_of_left_shifted_value(getValue(dividend, ref_list)[2],
getValue(dividend, ref_list)[4], c_expr);
c_expr.expr &:= "))";
elsif isActionExpression(dividend, "INT_ADD") then
optimize_mod_of_sum(getValue(dividend, ref_list)[2 ..], TRUE, c_expr)
elsif isActionExpression(dividend, "INT_SBTR") then
optimize_mod_of_sum(getValue(dividend, ref_list)[2 ..], FALSE, c_expr)
elsif isActionExpression(dividend, "INT_SUCC") then
optimize_mod_of_sum(getValue(dividend, ref_list)[2], 1, c_expr);
elsif isActionExpression(dividend, "INT_PRED") then
optimize_mod_of_sum(getValue(dividend, ref_list)[2], -1, c_expr);
elsif isActionExpression(dividend, "INT_ICONV1") then
optimize_mod_dividend(getActionParameter(dividend, 1), c_expr);
elsif isActionExpression(dividend, "INT_ICONV3") then
optimize_mod_dividend(getActionParameter(dividend, 3), c_expr);
else
c_expr.expr &:= "(";
process_expr(dividend, c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: optimize_mod_by_power_of_two (in reference: dividend, in reference: lshift,
in boolean: powerOperator, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var integer: lshift_value is 0;
var string: lshift_name is "";
begin
incr(countOptimizations);
c_expr.expr &:= "/*mod_by_power_of_two*/ ";
if getConstant(lshift, INTOBJECT, evaluatedParam) then
lshift_value := getValue(evaluatedParam, integer);
if lshift_value < 0 then
if powerOperator then
warning(DOES_RAISE, "NUMERIC_ERROR", c_expr);
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
else
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
end if;
elsif lshift_value >= ccConf.INTTYPE_SIZE then
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
elsif lshift_value = 0 then
c_expr.expr &:= "0";
else
optimize_mod_dividend(dividend, c_expr);
c_expr.expr &:= "&";
c_expr.expr &:= integerLiteral(pred(1 << lshift_value));
end if;
elsif check_int_shift_overflow then
incr(countOverflowChecks);
c_expr.expr &:= "(";
lshift_name := getParameterAsVariable("intType", "lshift_", lshift, c_expr);
if powerOperator then
c_expr.expr &:= "numChk(";
c_expr.expr &:= lshift_name;
c_expr.expr &:= "<0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":ovfChk(";
c_expr.expr &:= lshift_name;
c_expr.expr &:= ">=";
c_expr.expr &:= integerLiteral(pred(ccConf.INTTYPE_SIZE));
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
else
c_expr.expr &:= "ovfChk(";
checkRangeFromZero(lshift_name, integerLiteral(pred(ccConf.INTTYPE_SIZE)), c_expr);
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
end if;
c_expr.expr &:= ":";
optimize_mod_dividend(dividend, c_expr);
c_expr.expr &:= "&((";
c_expr.expr &:= integerLiteral(1);
c_expr.expr &:= "<<(";
c_expr.expr &:= lshift_name;
c_expr.expr &:= "))-1))";
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
if powerOperator then
c_expr.expr &:= "(";
lshift_name := getParameterAsVariable("intType", "lshift_", lshift, c_expr);
c_expr.expr &:= "numChk(";
c_expr.expr &:= lshift_name;
c_expr.expr &:= "<0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":";
optimize_mod_dividend(dividend, c_expr);
c_expr.expr &:= "&((";
c_expr.expr &:= integerLiteral(1);
c_expr.expr &:= "<<(";
c_expr.expr &:= lshift_name;
c_expr.expr &:= "))-1))";
else
optimize_mod_dividend(dividend, c_expr);
c_expr.expr &:= "&((";
c_expr.expr &:= integerLiteral(1);
c_expr.expr &:= "<<(";
process_expr(lshift, c_expr);
c_expr.expr &:= "))-1)";
end if;
end if;
end func;
const proc: process_const_int_mod (in reference: dividend, in integer: divisor,
inout expr_type: c_expr) is func
local
var reference: evaluatedDividend is NIL;
var reference: evaluatedLshift is NIL;
var integer: dividend_value is 0;
var string: dividend_name is "";
var string: remainder_name is "";
begin
incr(countOptimizations);
if divisor = 0 then
warning(DOES_RAISE, "NUMERIC_ERROR", c_expr);
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
elsif divisor = 1 then
c_expr.expr &:= "0";
elsif getConstant(dividend, INTOBJECT, evaluatedDividend) then
dividend_value := getValue(evaluatedDividend, integer);
if divisor = -1 and dividend_value < -integer.last then
if reduceOverflowChecks then
countOverflowOptimizations(c_expr);
c_expr.expr &:= "/*no_overflow_check_mod*/ 0";
else
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
end if;
else
c_expr.expr &:= integerLiteral(dividend_value mod divisor);
end if;
elsif divisor = -1 then
if not check_int_division_overflow then
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
c_expr.expr &:= "0";
elsif reduceOverflowChecks then
countOverflowOptimizations(c_expr);
c_expr.expr &:= "/*no_overflow_check_mod*/ 0";
else
incr(countOverflowChecks);
c_expr.expr &:= "(";
dividend_name := getParameterAsVariable("intType", "dividend_", dividend, c_expr);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= dividend_name;
c_expr.expr &:= "==";
c_expr.expr &:= integerLiteral(integer.first);
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":0)";
end if;
elsif divisor > 0 and 2 ** log2(divisor) = divisor then
incr(countOptimizations);
if modDividendOptimization then
if isActionExpression(dividend, "INT_LSHIFT") and
getConstant(getActionParameter(dividend, 3), INTOBJECT, evaluatedLshift) then
optimize_mod_of_left_shifted_value(getActionParameter(dividend, 1),
getValue(evaluatedLshift, integer), log2(divisor), c_expr);
else
optimize_mod_dividend(dividend, c_expr);
c_expr.expr &:= "&";
c_expr.expr &:= integerLiteral(pred(divisor));
end if;
else
c_expr.expr &:= "(";
process_expr(dividend, c_expr);
c_expr.expr &:= ")";
c_expr.expr &:= "&";
c_expr.expr &:= integerLiteral(pred(divisor));
end if;
elsif divisor < 0 and bitLength(divisor) = lowestSetBit(divisor) then
c_expr.expr &:= "(intType)-(-(uintType)(";
process_expr(dividend, c_expr);
c_expr.expr &:= ")&";
c_expr.expr &:= integerLiteral(-succ(divisor));
c_expr.expr &:= ")";
else
c_expr.expr &:= "(";
dividend_name := getParameterAsVariable("intType", "dividend_", dividend, c_expr);
remainder_name := defineTempVariable("intType", "remainder_", c_expr);
c_expr.expr &:= remainder_name;
c_expr.expr &:= "=";
c_expr.expr &:= dividend_name;
c_expr.expr &:= "%";
c_expr.expr &:= integerLiteral(divisor);
c_expr.expr &:= ",";
c_expr.expr &:= dividend_name;
if divisor > 0 then
c_expr.expr &:= "<0";
else
c_expr.expr &:= ">0";
end if;
c_expr.expr &:= "&&";
c_expr.expr &:= remainder_name;
c_expr.expr &:= "!=0?";
c_expr.expr &:= remainder_name;
c_expr.expr &:= "+";
c_expr.expr &:= integerLiteral(divisor);
c_expr.expr &:= ":";
c_expr.expr &:= remainder_name;
c_expr.expr &:= ")";
end if;
end func;
const proc: process_const_int_mod (in integer: dividend, in reference: divisor,
inout expr_type: c_expr) is func
local
var string: divisor_name is "";
var intRange: divisor_range is intRange.value;
var string: remainder_name is "";
begin
incr(countOptimizations);
divisor_range := getIntRange(divisor);
if dividend = 0 then
if integer_division_check then
if (divisor_range.minValue <= 0 and divisor_range.maxValue >= 0) or
divisor_range.mayRaiseException then
incr(countDivisionChecks);
c_expr.expr &:= "(divChk((";
process_expr(divisor, c_expr);
c_expr.expr &:= ")==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":0)";
else
countDivisionOptimizations(c_expr);
c_expr.expr &:= "0";
end if;
else
c_expr.expr &:= "0";
end if;
elsif dividend = 1 then
c_expr.expr &:= "(";
divisor_name := getParameterAsVariable("intType", "divisor_", divisor, c_expr);
c_expr.expr &:= divisor_name;
c_expr.expr &:= "<=0?";
if integer_division_check then
if divisor_range.minValue <= 0 and divisor_range.maxValue >= 0 then
incr(countDivisionChecks);
c_expr.expr &:= "(divChk(";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "+1)";
else
countDivisionOptimizations(c_expr);
c_expr.expr &:= divisor_name;
c_expr.expr &:= "+1";
end if;
else
c_expr.expr &:= divisor_name;
c_expr.expr &:= "+1";
end if;
c_expr.expr &:= ":(";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "==1?0:1))";
elsif check_int_division_overflow and dividend = integer.first then
if divisor_range.maxValue < -1 then
countOverflowOptimizations(c_expr);
if check_int_rem_by_zero then
countDivisionOptimizations(c_expr);
end if;
c_expr.expr &:= integerLiteral(dividend);
c_expr.expr &:= " % (";
process_expr(divisor, c_expr);
c_expr.expr &:= ")";
else
c_expr.expr &:= "(";
divisor_name := getParameterAsVariable("intType", "divisor_", divisor, c_expr);
remainder_name := defineTempVariable("intType", "remainder_", c_expr);
if divisor_range.minValue <= -1 and divisor_range.maxValue >= -1 then
incr(countOverflowChecks);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "==-1)?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
else
countOverflowOptimizations(c_expr);
end if;
if check_int_rem_by_zero then
if divisor_range.minValue <= 0 and divisor_range.maxValue >= 0 then
incr(countDivisionChecks);
c_expr.expr &:= "divChk(";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":";
else
countDivisionOptimizations(c_expr);
end if;
end if;
c_expr.expr &:= "(";
c_expr.expr &:= remainder_name;
c_expr.expr &:= "=";
c_expr.expr &:= integerLiteral(dividend);
c_expr.expr &:= "%";
c_expr.expr &:= divisor_name;
c_expr.expr &:= ",";
if divisor_range.maxValue <= 0 then
c_expr.expr &:= remainder_name;
else
if divisor_range.minValue <= 0 then
c_expr.expr &:= divisor_name;
c_expr.expr &:= ">0";
c_expr.expr &:= "&&";
end if;
c_expr.expr &:= remainder_name;
c_expr.expr &:= "!=0?";
c_expr.expr &:= remainder_name;
c_expr.expr &:= "+";
c_expr.expr &:= divisor_name;
c_expr.expr &:= ":";
c_expr.expr &:= remainder_name;
end if;
c_expr.expr &:= "))";
end if;
else
if dividend = integer.first then
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
end if;
c_expr.expr &:= "(";
divisor_name := getParameterAsVariable("intType", "divisor_", divisor, c_expr);
if check_int_rem_by_zero then
if divisor_range.minValue <= 0 and divisor_range.maxValue >= 0 then
incr(countDivisionChecks);
c_expr.expr &:= "divChk(";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":";
else
countDivisionOptimizations(c_expr);
end if;
end if;
if (dividend >= 0 and divisor_range.minValue >= 0) or
(dividend <= 0 and divisor_range.maxValue <= 0) then
c_expr.expr &:= integerLiteral(dividend);
c_expr.expr &:= "%";
c_expr.expr &:= divisor_name;
else
c_expr.expr &:= "(";
remainder_name := defineTempVariable("intType", "remainder_", c_expr);
c_expr.expr &:= remainder_name;
c_expr.expr &:= "=";
c_expr.expr &:= integerLiteral(dividend);
c_expr.expr &:= "%";
c_expr.expr &:= divisor_name;
c_expr.expr &:= ",";
if (dividend < 0 or divisor_range.maxValue >= 0) and
(dividend > 0 or divisor_range.minValue <= 0) then
c_expr.expr &:= divisor_name;
if dividend > 0 then
c_expr.expr &:= "<0";
else
c_expr.expr &:= ">0";
end if;
c_expr.expr &:= "&&";
end if;
c_expr.expr &:= remainder_name;
c_expr.expr &:= "!=0?";
c_expr.expr &:= remainder_name;
c_expr.expr &:= "+";
c_expr.expr &:= divisor_name;
c_expr.expr &:= ":";
c_expr.expr &:= remainder_name;
c_expr.expr &:= ")";
end if;
c_expr.expr &:= ")";
end if;
end func;
const proc: process (INT_MOD, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var string: dividend_name is "";
var string: divisor_name is "";
var intRange: dividend_range is intRange.value;
var intRange: divisor_range is intRange.value;
var string: remainder_name is "";
begin
if modDividendOptimization and
isActionExpression(params[3], "INT_LSHIFT") and
category(getValue(params[3], ref_list)[2]) = INTOBJECT and
not isVar(getValue(params[3], ref_list)[2]) and
getValue(getValue(params[3], ref_list)[2], integer) = 1 then
optimize_mod_by_power_of_two(params[1], getValue(params[3], ref_list)[4],
FALSE, c_expr);
elsif modDividendOptimization and
isActionExpression(params[3], "INT_POW") and
category(getValue(params[3], ref_list)[2]) = INTOBJECT and
not isVar(getValue(params[3], ref_list)[2]) and
getValue(getValue(params[3], ref_list)[2], integer) = 2 then
optimize_mod_by_power_of_two(params[1], getValue(params[3], ref_list)[4],
TRUE, c_expr);
elsif getConstant(params[3], INTOBJECT, evaluatedParam) then
process_const_int_mod(params[1], getValue(evaluatedParam, integer), c_expr);
elsif getConstant(params[1], INTOBJECT, evaluatedParam) then
process_const_int_mod(getValue(evaluatedParam, integer), params[3], c_expr);
elsif evaluate_const_expr = 0 and check_int_rem_zero_by_zero and
category(params[1]) = INTOBJECT and not isVar(params[1]) and
getValue(params[1], integer) = 0 then
incr(countDivisionChecks);
c_expr.expr &:= "(divChk((";
process_expr(params[3], c_expr);
c_expr.expr &:= ")==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":0)";
else
divisor_range := getIntRange(params[3]);
if params[1] = params[3] then
if integer_division_check then
if (divisor_range.minValue <= 0 and divisor_range.maxValue >= 0) or
divisor_range.mayRaiseException then
incr(countDivisionChecks);
c_expr.expr &:= "(divChk((";
process_expr(params[1], c_expr);
c_expr.expr &:= ")==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":0)";
else
countDivisionOptimizations(c_expr);
c_expr.expr &:= "0";
end if;
else
c_expr.expr &:= "0";
end if;
else
dividend_range := getIntRange(params[1]);
if (dividend_range.maxValue <= 0 and
((dividend_range.minValue > integer.first and divisor_range.maxValue < 0) or
divisor_range.maxValue < -1)) or
(dividend_range.minValue >= 0 and divisor_range.minValue > 0) then
countOverflowOptimizations(c_expr);
if check_int_rem_by_zero then
countDivisionOptimizations(c_expr);
end if;
c_expr.expr &:= "(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") % (";
process_expr(params[3], c_expr);
c_expr.expr &:= ")";
else
c_expr.expr &:= "(";
dividend_name := getParameterAsVariable("intType", "dividend_", params[1], c_expr);
divisor_name := getParameterAsVariable("intType", "divisor_", params[3], c_expr);
if check_int_division_overflow then
if dividend_range.minValue = integer.first and
divisor_range.minValue <= -1 and divisor_range.maxValue >= -1 then
incr(countOverflowChecks);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= dividend_name;
c_expr.expr &:= "==";
c_expr.expr &:= integerLiteral(integer.first);
c_expr.expr &:= "&&";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "==-1";
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
else
countOverflowOptimizations(c_expr);
end if;
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
end if;
if check_int_rem_by_zero then
if divisor_range.minValue <= 0 and divisor_range.maxValue >= 0 then
incr(countDivisionChecks);
c_expr.expr &:= "divChk(";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":";
else
countDivisionOptimizations(c_expr);
end if;
end if;
if (dividend_range.minValue >= 0 and divisor_range.minValue >= 0) or
(dividend_range.maxValue <= 0 and divisor_range.maxValue <= 0) then
c_expr.expr &:= dividend_name;
c_expr.expr &:= "%";
c_expr.expr &:= divisor_name;
else
c_expr.expr &:= "(";
remainder_name := defineTempVariable("intType", "remainder_", c_expr);
c_expr.expr &:= remainder_name;
c_expr.expr &:= "=";
c_expr.expr &:= dividend_name;
c_expr.expr &:= "%";
c_expr.expr &:= divisor_name;
c_expr.expr &:= ",";
if (dividend_range.maxValue >= 0 or divisor_range.minValue < 0) and
(dividend_range.minValue < 0 or divisor_range.maxValue >= 0) then
if dividend_range.maxValue < 0 then
c_expr.expr &:= divisor_name;
c_expr.expr &:= ">0";
elsif dividend_range.minValue >= 0 then
c_expr.expr &:= divisor_name;
c_expr.expr &:= "<0";
elsif divisor_range.minValue >= 0 then
c_expr.expr &:= dividend_name;
c_expr.expr &:= "<0";
elsif divisor_range.maxValue < 0 then
c_expr.expr &:= dividend_name;
c_expr.expr &:= ">0";
else
c_expr.expr &:= dividend_name;
c_expr.expr &:= "<0^";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "<0";
end if;
c_expr.expr &:= "&&";
end if;
c_expr.expr &:= remainder_name;
c_expr.expr &:= "!=0?";
c_expr.expr &:= remainder_name;
c_expr.expr &:= "+";
c_expr.expr &:= divisor_name;
c_expr.expr &:= ":";
c_expr.expr &:= remainder_name;
c_expr.expr &:= ")";
end if;
c_expr.expr &:= ")";
end if;
end if;
end if;
end func;
const proc: process_const_int_mult (in reference: factor1, in integer: factor2,
inout expr_type: c_expr) is func
local
var integer: minAllowedFactor1 is 0;
var integer: maxAllowedFactor1 is 0;
var reference: evaluatedParam is NIL;
var integer: factor1_value is 0;
var intRange: factor1_range is intRange.value;
var string: factor1_name is "";
var string: product_name is "";
var boolean: fullOverflowCheck is FALSE;
begin
if factor2 < -1 then
minAllowedFactor1 := integer.last div factor2;
maxAllowedFactor1 := integer.first div factor2;
elsif factor2 = -1 then
minAllowedFactor1 := -integer.last;
maxAllowedFactor1 := integer.last;
elsif factor2 = 0 then
minAllowedFactor1 := integer.first;
maxAllowedFactor1 := integer.last;
elsif factor2 >= 1 then
minAllowedFactor1 := integer.first div factor2;
maxAllowedFactor1 := integer.last div factor2;
end if;
if getConstant(factor1, INTOBJECT, evaluatedParam) then
incr(countOptimizations);
factor1_value := getValue(evaluatedParam, integer);
if factor1_value < minAllowedFactor1 or
factor1_value > maxAllowedFactor1 then
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
else
c_expr.expr &:= integerLiteral(factor1_value * factor2);
end if;
elsif factor2 = 0 then
incr(countOptimizations);
c_expr.expr &:= "0";
elsif factor2 = 1 then
incr(countOptimizations);
process_expr(factor1, c_expr);
elsif factor2 = -1 then
incr(countOptimizations);
negate(factor1, c_expr);
elsif check_int_arithmetic_overflow then
incr(countOptimizations);
factor1_range := getIntRange(factor1);
if factor1_range <> intRange.value then
if factor1_range.minValue >= minAllowedFactor1 and
factor1_range.maxValue <= maxAllowedFactor1 then
countOverflowOptimizations(c_expr);
c_expr.expr &:= "/*no_overflow_check_mult*/(";
process_expr(factor1, c_expr);
c_expr.expr &:= ") * ";
c_expr.expr &:= integerLiteral(factor2);
elsif factor1_range.minValue >= minAllowedFactor1 or
factor1_range.maxValue <= maxAllowedFactor1 then
incr(countOverflowChecks);
c_expr.expr &:= "/*simplified_overflow_check_mult*/(";
factor1_name := getParameterAsVariable("intType", "factor1_", factor1, c_expr);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= factor1_name;
if factor1_range.minValue >= minAllowedFactor1 then
c_expr.expr &:= ">";
c_expr.expr &:= integerLiteral(maxAllowedFactor1);
else
c_expr.expr &:= "<";
c_expr.expr &:= integerLiteral(minAllowedFactor1);
end if;
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= factor1_name;
c_expr.expr &:= " * ";
c_expr.expr &:= integerLiteral(factor2);
c_expr.expr &:= ")";
else
fullOverflowCheck := TRUE;
end if;
else
fullOverflowCheck := TRUE;
end if;
if fullOverflowCheck then
incr(countOverflowChecks);
if ccConf.BUILTIN_MULT_OVERFLOW <> "" then
product_name := defineTempVariable("intType", "product_", c_expr);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= ccConf.BUILTIN_MULT_OVERFLOW;
c_expr.expr &:= "(";
process_expr(factor1, c_expr);
c_expr.expr &:= ", ";
c_expr.expr &:= integerLiteral(factor2);
c_expr.expr &:= ", &";
c_expr.expr &:= product_name;
c_expr.expr &:= "))?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= product_name;
else
c_expr.expr &:= "(";
factor1_name := getParameterAsVariable("intType", "factor1_", factor1, c_expr);
c_expr.expr &:= "ovfChk(";
checkIfOutsideRange(factor1_name, minAllowedFactor1,
maxAllowedFactor1, c_expr);
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= factor1_name;
c_expr.expr &:= " * ";
c_expr.expr &:= integerLiteral(factor2);
c_expr.expr &:= ")";
end if;
end if;
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
c_expr.expr &:= "(";
process_expr(factor1, c_expr);
c_expr.expr &:= ") * ";
c_expr.expr &:= integerLiteral(factor2);
end if;
end func;
const proc: process (INT_MULT, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var intRange: productRange is intRange.value;
var boolean: doOverflowCheck is FALSE;
begin
if getConstant(params[3], INTOBJECT, evaluatedParam) then
process_const_int_mult(params[1], getValue(evaluatedParam, integer), c_expr);
elsif getConstant(params[1], INTOBJECT, evaluatedParam) then
process_const_int_mult(params[3], getValue(evaluatedParam, integer), c_expr);
else
if check_int_arithmetic_overflow then
if reduceOverflowChecks then
productRange := getIntMultRange(getIntRange(params[1]),
getIntRange(params[3]));
if productRange.mayOverflow then
doOverflowCheck := TRUE;
else
countOverflowOptimizations(c_expr);
c_expr.expr &:= "/*no_overflow_check_mult*/";
end if;
else
doOverflowCheck := TRUE;
end if;
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
end if;
if doOverflowCheck then
incr(countOverflowChecks);
c_expr.expr &:= "(";
int_mult_with_overflow_check(params[1], params[3], c_expr);
c_expr.expr &:= ")";
else
c_expr.expr &:= "(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") * (";
process_expr(params[3], c_expr);
c_expr.expr &:= ")";
end if;
end if;
end func;
const proc: process_const_int_mult_assign (in reference: variable, in integer: factor,
inout expr_type: c_expr) is func
local
var string: variable_name is "";
var expr_type: statement is expr_type.value;
begin
if factor = 0 then
incr(countOptimizations);
process_expr(variable, statement);
statement.expr &:= "=";
statement.expr &:= integerLiteral(0);
statement.expr &:= ";\n";
doLocalDeclsOfStatement(statement, c_expr);
elsif factor = 1 then
incr(countOptimizations);
c_expr.expr &:= "/* ignore integer *:= 1; */\n";
elsif factor = -1 then
if check_int_arithmetic_overflow and ccConf.TWOS_COMPLEMENT_INTTYPE then
incr(countOverflowChecks);
variable_name := getParameterAsReference("intType", "variable_", variable, statement);
statement.expr &:= "if (ovfChk(";
statement.expr &:= variable_name;
statement.expr &:= "==";
statement.expr &:= integerLiteral(integer.first);
statement.expr &:= ")) {\n";
statement.expr &:= raiseError("OVERFLOW_ERROR");
statement.expr &:= "} else {\n";
statement.expr &:= variable_name;
statement.expr &:= "*= -1;\n";
statement.expr &:= "}\n";
else
if ccConf.TWOS_COMPLEMENT_INTTYPE then
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
end if;
process_expr(variable, statement);
statement.expr &:= "*= -1;\n";
end if;
doLocalDeclsOfStatement(statement, c_expr);
elsif check_int_arithmetic_overflow then
incr(countOptimizations);
incr(countOverflowChecks);
variable_name := getParameterAsReference("intType", "variable_", variable, statement);
statement.expr &:= "if (ovfChk(";
if factor < 0 then
checkIfOutsideRange(variable_name, integer.last div factor,
integer.first div factor, statement);
else
checkIfOutsideRange(variable_name, integer.first div factor,
integer.last div factor, statement);
end if;
statement.expr &:= ")) {\n";
statement.expr &:= raiseError("OVERFLOW_ERROR");
statement.expr &:= "} else {\n";
statement.expr &:= variable_name;
statement.expr &:= " *= ";
statement.expr &:= integerLiteral(factor);
statement.expr &:= ";\n";
statement.expr &:= "}\n";
doLocalDeclsOfStatement(statement, c_expr);
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
process_expr(variable, statement);
statement.expr &:= "*=";
statement.expr &:= integerLiteral(factor);
statement.expr &:= ";\n";
doLocalDeclsOfStatement(statement, c_expr);
end if;
end func;
const proc: process (INT_MULT_ASSIGN, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var string: variable_name is "";
var string: factor_name is "";
var string: product_name is "";
var expr_type: statement is expr_type.value;
begin
if getConstant(params[3], INTOBJECT, evaluatedParam) then
process_const_int_mult_assign(params[1], getValue(evaluatedParam, integer), c_expr);
elsif check_int_arithmetic_overflow then
incr(countOverflowChecks);
variable_name := getParameterAsReference("intType", "variable_", params[1], statement);
if ccConf.BUILTIN_MULT_OVERFLOW <> "" then
statement.expr &:= "ovfChk(";
statement.expr &:= ccConf.BUILTIN_MULT_OVERFLOW;
statement.expr &:= "(";
statement.expr &:= variable_name;
statement.expr &:= ", ";
process_expr(params[3], statement);
statement.expr &:= ", &(";
statement.expr &:= variable_name;
statement.expr &:= ")))?";
statement.expr &:= intRaiseError("OVERFLOW_ERROR");
statement.expr &:= ":0;";
elsif ccConf.INTTYPE_SIZE = 64 and ccConf.INT128TYPE <> "" or
ccConf.INTTYPE_SIZE = 32 then
product_name := defineTempVariable("doubleIntType", "product_", statement);
statement.expr &:= product_name;
statement.expr &:= "=(doubleIntType)(";
statement.expr &:= variable_name;
statement.expr &:= ") * (doubleIntType)(";
process_expr(params[3], statement);
statement.expr &:= "),ovfChk(!inIntTypeRange(";
statement.expr &:= product_name;
statement.expr &:= "))?";
statement.expr &:= intRaiseError("OVERFLOW_ERROR");
statement.expr &:= ":(";
statement.expr &:= variable_name;
statement.expr &:= "=(intType)";
statement.expr &:= product_name;
statement.expr &:= ");\n";
else
factor_name := getParameterAsVariable("intType", "factor_", params[3], statement);
statement.expr &:= variable_name;
statement.expr &:= "<0&&(";
statement.expr &:= factor_name;
statement.expr &:= "<0&&";
statement.expr &:= variable_name;
statement.expr &:= "<";
statement.expr &:= integerLiteral(integer.last);
statement.expr &:= "/";
statement.expr &:= factor_name;
statement.expr &:= "||";
statement.expr &:= factor_name;
statement.expr &:= ">0&&";
statement.expr &:= variable_name;
statement.expr &:= "<";
statement.expr &:= integerLiteral(integer.first);
statement.expr &:= "/";
statement.expr &:= factor_name;
statement.expr &:= ")||";
statement.expr &:= variable_name;
statement.expr &:= ">0&&(";
statement.expr &:= factor_name;
statement.expr &:= "<0&&";
statement.expr &:= factor_name;
statement.expr &:= "<";
statement.expr &:= integerLiteral(integer.first);
statement.expr &:= "/";
statement.expr &:= variable_name;
statement.expr &:= "||";
statement.expr &:= factor_name;
statement.expr &:= ">0&&";
statement.expr &:= factor_name;
statement.expr &:= ">";
statement.expr &:= integerLiteral(integer.last);
statement.expr &:= "/";
statement.expr &:= variable_name;
statement.expr &:= ")?";
statement.expr &:= intRaiseError("OVERFLOW_ERROR");
statement.expr &:= ":(";
statement.expr &:= variable_name;
statement.expr &:= " *= ";
statement.expr &:= factor_name;
statement.expr &:= ");\n";
end if;
doLocalDeclsOfStatement(statement, c_expr);
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
process_expr(params[1], statement);
statement.expr &:= "*=";
process_expr(params[3], statement);
statement.expr &:= ";\n";
doLocalDeclsOfStatement(statement, c_expr);
end if;
end func;
const proc: process (INT_NE, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var intRange: number1Range is intRange.value;
var intRange: number2Range is intRange.value;
var boolean: doCompare is TRUE;
begin
if optimizeComparisons then
number1Range := getIntRange(params[1]);
number2Range := getIntRange(params[3]);
if not number1Range.mayRaiseException and not number2Range.mayRaiseException then
if number1Range.maxValue < number2Range.minValue or
number1Range.minValue > number2Range.maxValue then
warning(COMPARISON_RESULT_CONSTANT, "<>", TRUE, c_expr);
incr(countOptimizations);
c_expr.expr &:= "1";
doCompare := FALSE;
elsif number1Range.minValue = number1Range.maxValue and
number2Range.minValue = number2Range.maxValue and
number1Range.minValue = number2Range.minValue then
warning(COMPARISON_RESULT_CONSTANT, "<>", FALSE, c_expr);
incr(countOptimizations);
c_expr.expr &:= "0";
doCompare := FALSE;
end if;
end if;
end if;
if doCompare then
c_expr.expr &:= "(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") != (";
process_expr(params[3], c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: process (INT_NEGATE, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var string: number_name is "";
var integer: number is 0;
begin
if getConstant(params[2], INTOBJECT, evaluatedParam) then
incr(countOptimizations);
number := getValue(evaluatedParam, integer);
if number = integer.first and ccConf.TWOS_COMPLEMENT_INTTYPE then
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
else
c_expr.expr &:= integerLiteral(-number);
end if;
else
negate(params[2], c_expr);
end if;
end func;
const proc: process (INT_N_BYTES_BE_SIGNED, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
prepare_stri_result(c_expr);
c_expr.result_expr := "intNBytesBeSigned(";
getStdParamToResultExpr(params[1], c_expr);
c_expr.result_expr &:= ", ";
getStdParamToResultExpr(params[4], c_expr);
c_expr.result_expr &:= ")";
end func;
const proc: process_const_int_n_bytes_be_unsigned (in reference: number,
in integer: length, inout expr_type: c_expr) is func
local
var reference: evaluatedNumber is NIL;
var integer: numberValue is 0;
var intRange: numberRange is intRange.value;
var boolean: rangeCheckDone is FALSE;
var string: buffer_name is "";
var string: number_name is "";
var integer: index is 0;
begin
if length <= 0 then
incr(countOptimizations);
warning(DOES_RAISE, "RANGE_ERROR", c_expr);
c_expr.expr &:= strRaiseError("RANGE_ERROR");
elsif getConstant(number, INTOBJECT, evaluatedNumber) then
incr(countOptimizations);
numberValue := getValue(evaluatedNumber, integer);
if numberValue < 0 or (length < 8 and numberValue >= 2 ** (8 * length)) then
warning(DOES_RAISE, "RANGE_ERROR", c_expr);
c_expr.expr &:= strRaiseError("RANGE_ERROR");
else
c_expr.expr &:= stringLiteral(bytes(numberValue, UNSIGNED, BE, length));
end if;
elsif ccConf.ALLOW_STRITYPE_SLICES and length <= 8 then
incr(countOptimizations);
incr(countInlinedFunctions);
incr(c_expr.temp_num);
buffer_name := "buffer_" & str(c_expr.temp_num);
c_expr.temp_decls &:= "union {\n";
c_expr.temp_decls &:= " struct striStruct striBuf;\n";
c_expr.temp_decls &:= " char charBuf[SIZ_STRI(";
c_expr.temp_decls &:= str(length);
c_expr.temp_decls &:= ")];\n";
c_expr.temp_decls &:= "} ";
c_expr.temp_decls &:= buffer_name;
c_expr.temp_decls &:= ";\n";
c_expr.expr &:= "(";
number_name := getParameterAsVariable("intType", "number_", number, c_expr);
if function_range_check then
numberRange := getIntRange(number);
if numberRange.minValue >= 0 and
(length >= 8 or numberRange.maxValue < 2 ** (8 * length)) then
countRangeOptimizations(c_expr);
else
incr(countRangeChecks);
c_expr.expr &:= "rngChk(";
if length >= 8 or numberRange.maxValue < 2 ** (8 * length) then
c_expr.expr &:= number_name;
c_expr.expr &:= "<0";
else
checkIfOutsideRange(number_name, 0, pred(2 ** (8 * length)), c_expr);
end if;
c_expr.expr &:= ")?";
c_expr.expr &:= strRaiseError("RANGE_ERROR");
c_expr.expr &:= ":(";
rangeCheckDone := TRUE;
end if;
else
incr(countNoRangeChecks);
end if;
c_expr.expr &:= buffer_name;
c_expr.expr &:= ".striBuf.size=";
c_expr.expr &:= str(length);
c_expr.expr &:= ",";
c_expr.expr &:= buffer_name;
c_expr.expr &:= ".striBuf.mem=";
c_expr.expr &:= buffer_name;
c_expr.expr &:= ".striBuf.mem1,";
for index range 1 to length do
c_expr.expr &:= buffer_name;
c_expr.expr &:= ".striBuf.mem1[";
c_expr.expr &:= str(pred(index));
c_expr.expr &:= "]=(strElemType)(";
if index <> length then
c_expr.expr &:= "(";
c_expr.expr &:= number_name;
c_expr.expr &:= ">>";
c_expr.expr &:= str(8 * (length - index));
c_expr.expr &:= ")";
else
c_expr.expr &:= number_name;
end if;
if index <> 1 then
c_expr.expr &:= "&255";
end if;
c_expr.expr &:= "),";
end for;
c_expr.expr &:= "&";
c_expr.expr &:= buffer_name;
c_expr.expr &:= ".striBuf";
if rangeCheckDone then
c_expr.expr &:= ")";
end if;
c_expr.expr &:= ")";
else
prepare_stri_result(c_expr);
c_expr.result_expr := "intNBytesBeUnsigned(";
getStdParamToResultExpr(number, c_expr);
c_expr.result_expr &:= ", ";
c_expr.result_expr &:= integerLiteral(length);
c_expr.result_expr &:= ")";
end if;
end func;
const proc: process (INT_N_BYTES_BE_UNSIGNED, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedLength is NIL;
begin
if inlineFunctions and
getConstant(params[4], INTOBJECT, evaluatedLength) then
process_const_int_n_bytes_be_unsigned(params[1],
getValue(evaluatedLength, integer), c_expr);
else
prepare_stri_result(c_expr);
c_expr.result_expr := "intNBytesBeUnsigned(";
getStdParamToResultExpr(params[1], c_expr);
c_expr.result_expr &:= ", ";
getStdParamToResultExpr(params[4], c_expr);
c_expr.result_expr &:= ")";
end if;
end func;
const proc: process (INT_N_BYTES_LE_SIGNED, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
prepare_stri_result(c_expr);
c_expr.result_expr := "intNBytesLeSigned(";
getStdParamToResultExpr(params[1], c_expr);
c_expr.result_expr &:= ", ";
getStdParamToResultExpr(params[4], c_expr);
c_expr.result_expr &:= ")";
end func;
const proc: process_const_int_n_bytes_le_unsigned (in reference: number,
in integer: length, inout expr_type: c_expr) is func
local
var reference: evaluatedNumber is NIL;
var integer: numberValue is 0;
var intRange: numberRange is intRange.value;
var boolean: rangeCheckDone is FALSE;
var string: buffer_name is "";
var string: number_name is "";
var integer: index is 0;
begin
if length <= 0 then
incr(countOptimizations);
warning(DOES_RAISE, "RANGE_ERROR", c_expr);
c_expr.expr &:= strRaiseError("RANGE_ERROR");
elsif getConstant(number, INTOBJECT, evaluatedNumber) then
incr(countOptimizations);
numberValue := getValue(evaluatedNumber, integer);
if numberValue < 0 or (length < 8 and numberValue >= 2 ** (8 * length)) then
warning(DOES_RAISE, "RANGE_ERROR", c_expr);
c_expr.expr &:= strRaiseError("RANGE_ERROR");
else
c_expr.expr &:= stringLiteral(bytes(numberValue, UNSIGNED, LE, length));
end if;
elsif ccConf.ALLOW_STRITYPE_SLICES and length <= 8 then
incr(countOptimizations);
incr(countInlinedFunctions);
incr(c_expr.temp_num);
buffer_name := "buffer_" & str(c_expr.temp_num);
c_expr.temp_decls &:= "union {\n";
c_expr.temp_decls &:= " struct striStruct striBuf;\n";
c_expr.temp_decls &:= " char charBuf[SIZ_STRI(";
c_expr.temp_decls &:= str(length);
c_expr.temp_decls &:= ")];\n";
c_expr.temp_decls &:= "} ";
c_expr.temp_decls &:= buffer_name;
c_expr.temp_decls &:= ";\n";
c_expr.expr &:= "(";
number_name := getParameterAsVariable("intType", "number_", number, c_expr);
if function_range_check then
numberRange := getIntRange(number);
if numberRange.minValue >= 0 and
(length >= 8 or numberRange.maxValue < 2 ** (8 * length)) then
countRangeOptimizations(c_expr);
else
incr(countRangeChecks);
c_expr.expr &:= "rngChk(";
if length >= 8 or numberRange.maxValue < 2 ** (8 * length) then
c_expr.expr &:= number_name;
c_expr.expr &:= "<0";
else
checkIfOutsideRange(number_name, 0, pred(2 ** (8 * length)), c_expr);
end if;
c_expr.expr &:= ")?";
c_expr.expr &:= strRaiseError("RANGE_ERROR");
c_expr.expr &:= ":(";
rangeCheckDone := TRUE;
end if;
else
incr(countNoRangeChecks);
end if;
c_expr.expr &:= buffer_name;
c_expr.expr &:= ".striBuf.size=";
c_expr.expr &:= str(length);
c_expr.expr &:= ",";
c_expr.expr &:= buffer_name;
c_expr.expr &:= ".striBuf.mem=";
c_expr.expr &:= buffer_name;
c_expr.expr &:= ".striBuf.mem1,";
for index range 1 to length do
c_expr.expr &:= buffer_name;
c_expr.expr &:= ".striBuf.mem1[";
c_expr.expr &:= str(pred(index));
c_expr.expr &:= "]=(strElemType)(";
if index <> 1 then
c_expr.expr &:= "(";
c_expr.expr &:= number_name;
c_expr.expr &:= ">>";
c_expr.expr &:= str(8 * pred(index));
c_expr.expr &:= ")";
else
c_expr.expr &:= number_name;
end if;
if index <> length then
c_expr.expr &:= "&255";
end if;
c_expr.expr &:= "),";
end for;
c_expr.expr &:= "&";
c_expr.expr &:= buffer_name;
c_expr.expr &:= ".striBuf";
if rangeCheckDone then
c_expr.expr &:= ")";
end if;
c_expr.expr &:= ")";
else
prepare_stri_result(c_expr);
c_expr.result_expr := "intNBytesLeUnsigned(";
getStdParamToResultExpr(number, c_expr);
c_expr.result_expr &:= ", ";
c_expr.result_expr &:= integerLiteral(length);
c_expr.result_expr &:= ")";
end if;
end func;
const proc: process (INT_N_BYTES_LE_UNSIGNED, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedLength is NIL;
begin
if inlineFunctions and
getConstant(params[4], INTOBJECT, evaluatedLength) then
process_const_int_n_bytes_le_unsigned(params[1],
getValue(evaluatedLength, integer), c_expr);
else
prepare_stri_result(c_expr);
c_expr.result_expr := "intNBytesLeUnsigned(";
getStdParamToResultExpr(params[1], c_expr);
c_expr.result_expr &:= ", ";
getStdParamToResultExpr(params[4], c_expr);
c_expr.result_expr &:= ")";
end if;
end func;
const proc: process (INT_ODD, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
c_expr.expr &:= "(";
process_expr(params[1], c_expr);
c_expr.expr &:= ")&1";
end func;
const proc: process (INT_PARSE1, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
c_expr.expr &:= "intParse(";
getAnyParamToExpr(params[1], c_expr);
c_expr.expr &:= ")";
end func;
const proc: process (INT_PLUS, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
process_expr(params[2], c_expr);
end func;
const func boolean: powerOverflows (in integer: base, in integer: exponent) is func
result
var boolean: powerOverflows is FALSE;
begin
if exponent < 0 then
powerOverflows := FALSE;
elsif exponent >= minIdx(minBaseOfExponent) then
if exponent <= maxIdx(minBaseOfExponent) then
if base < minBaseOfExponent[exponent] or
base > maxBaseOfExponent[exponent] then
powerOverflows := TRUE;
end if;
elsif base < minIdx(maxExponentOfBase) or
base > maxIdx(maxExponentOfBase) or
exponent > maxExponentOfBase[base] then
powerOverflows := TRUE;
end if;
end if;
end func;
const proc: process_const_int_pow (in reference: base, in integer: exponent,
inout expr_type: c_expr) is func
local
const array string: power is [2] (
"x*x", "x*x*x", "(a=x*x,a*a)", "(a=x*x,a*a*x)", "(a=x*x*x,a*a)",
"(a=x*x,a*a*a*x)", "(b=(a=x*x,a*a),b*b)", "(b=(a=x*x,a*a),b*b*x)",
"(b=(a=x*x,a*a*x),b*b)", "(b=(a=x*x,a*a*x),b*b*x)",
"(b=(a=x*x*x,a*a),b*b)", "(b=(a=x*x,a*a),b*b*b*x)",
"(b=(a=x*x,a*a*a*x),b*b)", "(b=(a=x*x*x,a*a),b*b*a)",
"(c=(b=(a=x*x,a*a),b*b),c*c)", "(c=(b=(a=x*x,a*a),b*b),c*c*x)",
"(c=(b=(a=x*x,a*a),b*b),c*c*a)", "(c=(b=(a=x*x,a*a*x),b*a),c*c*b)",
"(c=(b=(a=x*x,a*a*x),b*b),c*c)", "(c=(b=(a=x*x,a*a*x),b*b),c*c*x)",
"(c=(b=(a=x*x,a*a*x),b*b*x),c*c)");
const string: variables is "abc";
var reference: evaluatedBase is NIL;
var integer: baseValue is 0;
var string: powerTemplate is "";
var intRange: baseRange is intRange.value;
var string: baseName is "";
var string: variableName is "";
var char: ch is ' ';
var integer: minBase is 0;
var integer: maxBase is 0;
begin
if exponent < 0 then
incr(countOptimizations);
warning(DOES_RAISE, "NUMERIC_ERROR", c_expr);
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
elsif getConstant(base, INTOBJECT, evaluatedBase) then
incr(countOptimizations);
baseValue := getValue(evaluatedBase, integer);
if powerOverflows(baseValue, exponent) then
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
else
c_expr.expr &:= integerLiteral(baseValue ** exponent);
end if;
elsif exponent = 0 then
incr(countOptimizations);
c_expr.expr &:= integerLiteral(1);
elsif exponent = 1 then
incr(countOptimizations);
process_expr(base, c_expr);
elsif exponent in {2 .. maxIdx(power)} then
incr(countOptimizations);
powerTemplate := power[exponent];
c_expr.expr &:= "(";
baseName := getParameterAsVariable("intType", "base_", base, c_expr);
if check_int_arithmetic_overflow then
baseRange := getIntRange(base);
if baseRange.minValue < minBaseOfExponent[exponent] or
baseRange.maxValue > maxBaseOfExponent[exponent] then
incr(countOverflowChecks);
c_expr.expr &:= "ovfChk(";
checkIfOutsideRange(baseName, minBaseOfExponent[exponent],
maxBaseOfExponent[exponent], c_expr);
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
else
countOverflowOptimizations(c_expr);
end if;
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
end if;
for ch range variables do
if pos(powerTemplate, ch) <> 0 then
variableName := defineTempVariable("intType", str(ch) & "_", c_expr);
powerTemplate := replace(powerTemplate, str(ch), variableName);
end if;
end for;
c_expr.expr &:= replace(powerTemplate, "x", baseName);
c_expr.expr &:= ")";
elsif integer_overflow_check then
incr(countOptimizations);
baseRange := getIntRange(base);
minBase := minIdx(maxExponentOfBase);
while exponent > maxExponentOfBase[minBase] do
incr(minBase);
end while;
maxBase := maxIdx(maxExponentOfBase);
while exponent > maxExponentOfBase[maxBase] do
decr(maxBase);
end while;
c_expr.expr &:= "(";
baseName := getParameterAsVariable("intType", "base_", base, c_expr);
if baseRange.minValue < minBase or
baseRange.maxValue > maxBase then
incr(countOverflowChecks);
c_expr.expr &:= "ovfChk(";
checkIfOutsideRange(baseName, minBase, maxBase, c_expr);
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
else
countOverflowOptimizations(c_expr);
end if;
c_expr.expr &:= "intPow(";
c_expr.expr &:= baseName;
c_expr.expr &:= ", ";
c_expr.expr &:= integerLiteral(exponent);
c_expr.expr &:= "))";
else
c_expr.expr &:= "intPow(";
process_expr(base, c_expr);
c_expr.expr &:= ", ";
c_expr.expr &:= integerLiteral(exponent);
c_expr.expr &:= ")";
end if;
end func;
const proc: process_const_int_pow (in integer: base, in reference: exponent,
inout expr_type: c_expr) is func
local
var intRange: exponentRange is intRange.value;
var string: exponentName is "";
var integer: log2ofNegatedBase is 0;
var integer: maxExponent is 0;
begin
exponentRange := getIntRange(exponent);
if exponentRange.maxValue < 0 then
warning(DOES_RAISE, "NUMERIC_ERROR", c_expr);
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
elsif base = -1 then
incr(countOptimizations);
if integer_power_check and exponentRange.minValue < 0 then
c_expr.expr &:= "(";
exponentName := getParameterAsVariable("intType", "exponent_", exponent, c_expr);
c_expr.expr &:= "numChk(";
c_expr.expr &:= exponentName;
c_expr.expr &:= "<0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":1-((";
c_expr.expr &:= exponentName;
c_expr.expr &:= "&1)<<1))";
else
c_expr.expr &:= "1-(((";
process_expr(exponent, c_expr);
c_expr.expr &:= ")&1)<<1)";
end if;
elsif base = 0 then
incr(countOptimizations);
if integer_power_check and exponentRange.minValue < 0 then
c_expr.expr &:= "(";
exponentName := getParameterAsVariable("intType", "exponent_", exponent, c_expr);
c_expr.expr &:= "numChk(";
c_expr.expr &:= exponentName;
c_expr.expr &:= "<0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= exponentName;
c_expr.expr &:= "==0?";
c_expr.expr &:= integerLiteral(1);
c_expr.expr &:= ":";
c_expr.expr &:= integerLiteral(0);
c_expr.expr &:= ")";
else
c_expr.expr &:= "(";
process_expr(exponent, c_expr);
c_expr.expr &:= ")==0?";
c_expr.expr &:= integerLiteral(1);
c_expr.expr &:= ":";
c_expr.expr &:= integerLiteral(0);
end if;
elsif base = 1 then
incr(countOptimizations);
if integer_power_check and exponentRange.minValue < 0 then
c_expr.expr &:= "(numChk((";
process_expr(exponent, c_expr);
c_expr.expr &:= ")<0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= integerLiteral(1);
c_expr.expr &:= ")";
else
c_expr.expr &:= integerLiteral(1);
end if;
elsif base > 0 and 2 ** log2(base) = base then
incr(countOptimizations);
maxExponent := log2(integer.last) div log2(base);
if exponentRange.minValue > maxExponent then
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
elsif integer_power_check and exponentRange.minValue < 0 or
integer_overflow_check and exponentRange.maxValue > maxExponent then
c_expr.expr &:= "(";
exponentName := getParameterAsVariable("intType", "exponent_", exponent, c_expr);
if integer_power_check and exponentRange.minValue < 0 then
c_expr.expr &:= "numChk(";
c_expr.expr &:= exponentName;
c_expr.expr &:= "<0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":";
end if;
if integer_overflow_check then
if exponentRange.maxValue > maxExponent then
incr(countOverflowChecks);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= exponentName;
c_expr.expr &:= ">";
c_expr.expr &:= integerLiteral(maxExponent);
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
else
countOverflowOptimizations(c_expr);
end if;
end if;
c_expr.expr &:= integerLiteral(1);
c_expr.expr &:= "<<";
if base <> 2 then
c_expr.expr &:= integerLiteral(log2(base));
c_expr.expr &:= "*";
end if;
c_expr.expr &:= exponentName;
c_expr.expr &:= ")";
else
if integer_overflow_check then
countOverflowOptimizations(c_expr);
end if;
c_expr.expr &:= integerLiteral(1);
c_expr.expr &:= "<<";
if base <> 2 then
c_expr.expr &:= integerLiteral(log2(base));
c_expr.expr &:= "*";
end if;
c_expr.expr &:= "(";
process_expr(exponent, c_expr);
c_expr.expr &:= ")";
end if;
elsif base < 0 and bitLength(base) = lowestSetBit(base) then
incr(countOptimizations);
log2ofNegatedBase := ord(log2(-bigInteger(base)));
maxExponent := ord(log2(-bigInteger(integer.first))) div log2ofNegatedBase;
if not odd(maxExponent) then
maxExponent := log2(integer.last) div log2ofNegatedBase;
end if;
if exponentRange.minValue > maxExponent then
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
else
c_expr.expr &:= "(";
exponentName := getParameterAsVariable("intType", "exponent_", exponent, c_expr);
if integer_power_check and exponentRange.minValue < 0 then
c_expr.expr &:= "numChk(";
c_expr.expr &:= exponentName;
c_expr.expr &:= "<0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":";
end if;
if integer_overflow_check then
if exponentRange.maxValue > maxExponent then
incr(countOverflowChecks);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= exponentName;
c_expr.expr &:= ">";
c_expr.expr &:= integerLiteral(maxExponent);
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
else
countOverflowOptimizations(c_expr);
end if;
end if;
c_expr.expr &:= exponentName;
c_expr.expr &:= "&1?";
c_expr.expr &:= integerLiteral(-1);
c_expr.expr &:= "<<";
if base <> -2 then
c_expr.expr &:= integerLiteral(log2ofNegatedBase);
c_expr.expr &:= "*";
end if;
c_expr.expr &:= exponentName;
c_expr.expr &:= ":";
c_expr.expr &:= integerLiteral(1);
c_expr.expr &:= "<<";
if base <> -2 then
c_expr.expr &:= integerLiteral(log2ofNegatedBase);
c_expr.expr &:= "*";
end if;
c_expr.expr &:= exponentName;
c_expr.expr &:= ")";
end if;
elsif integer_overflow_check then
incr(countOptimizations);
if base >= minIdx(maxExponentOfBase) and base <= maxIdx(maxExponentOfBase) then
maxExponent := maxExponentOfBase[base];
elsif base > 0 then
maxExponent := 2;
while base <= maxBaseOfExponent[maxExponent] do
incr(maxExponent);
end while;
decr(maxExponent);
else
maxExponent := 2;
while base >= minBaseOfExponent[maxExponent] do
incr(maxExponent);
end while;
decr(maxExponent);
end if;
if exponentRange.minValue > maxExponent then
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
else
c_expr.expr &:= "(";
exponentName := getParameterAsVariable("intType", "exponent_", exponent, c_expr);
if exponentRange.maxValue > maxExponent then
incr(countOverflowChecks);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= exponentName;
c_expr.expr &:= ">";
c_expr.expr &:= integerLiteral(maxExponent);
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
else
countOverflowOptimizations(c_expr);
end if;
c_expr.expr &:= "intPow(";
c_expr.expr &:= integerLiteral(base);
c_expr.expr &:= ", ";
c_expr.expr &:= exponentName;
c_expr.expr &:= "))";
end if;
else
c_expr.expr &:= "intPow(";
c_expr.expr &:= integerLiteral(base);
c_expr.expr &:= ", ";
process_expr(exponent, c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: process (INT_POW, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var intRange: baseRange is intRange.value;
var intRange: exponentRange is intRange.value;
begin
if getConstant(params[3], INTOBJECT, evaluatedParam) then
process_const_int_pow(params[1], getValue(evaluatedParam, integer), c_expr);
elsif getConstant(params[1], INTOBJECT, evaluatedParam) then
process_const_int_pow(getValue(evaluatedParam, integer), params[3], c_expr);
else
baseRange := getIntRange(params[1]);
exponentRange := getIntRange(params[3]);
if exponentRange.maxValue < 0 then
warning(DOES_RAISE, "NUMERIC_ERROR", c_expr);
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
else
if integer_overflow_check then
if exponentRange.maxValue < minIdx(minBaseOfExponent) or
exponentRange.maxValue > maxIdx(minBaseOfExponent) or
baseRange.minValue < minBaseOfExponent[exponentRange.maxValue] or
baseRange.maxValue > maxBaseOfExponent[exponentRange.maxValue] then
incr(countOverflowChecks);
c_expr.expr &:= "intPowOvfChk(";
else
countOverflowOptimizations(c_expr);
c_expr.expr &:= "intPow(";
end if;
else
c_expr.expr &:= "intPow(";
end if;
process_expr(params[1], c_expr);
c_expr.expr &:= ", ";
process_expr(params[3], c_expr);
c_expr.expr &:= ")";
end if;
end if;
end func;
const proc: process (INT_PRED, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var string: number_name is "";
var integer: number is 0;
begin
if callOptimizeIntAdd then
optimize_int_add(params[1], -1, c_expr);
elsif getConstant(params[1], INTOBJECT, evaluatedParam) then
incr(countOptimizations);
number := getValue(evaluatedParam, integer);
if number = integer.first then
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
else
c_expr.expr &:= integerLiteral(pred(number));
end if;
elsif check_int_arithmetic_overflow then
incr(countOverflowChecks);
c_expr.expr &:= "(";
number_name := getParameterAsVariable("intType", "number_", params[1], c_expr);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= number_name;
c_expr.expr &:= "==";
c_expr.expr &:= integerLiteral(integer.first);
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= number_name;
c_expr.expr &:= "-1)";
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
c_expr.expr &:= "(";
process_expr(params[1], c_expr);
c_expr.expr &:= ")-1";
end if;
end func;
const proc: process_const_int_radix (in reference: param1, in integer: base,
in boolean: upperCase, inout expr_type: c_expr) is func
begin
if base < 2 or base > 36 then
incr(countOptimizations);
warning(DOES_RAISE, "RANGE_ERROR", c_expr);
c_expr.expr &:= strRaiseError("RANGE_ERROR");
elsif base = 10 then
incr(countOptimizations);
process_int_str(param1, c_expr);
elsif 2 ** log2(base) = base then
incr(countOptimizations);
prepare_stri_result(c_expr);
c_expr.result_expr := "intRadixPow2(";
getStdParamToResultExpr(param1, c_expr);
c_expr.result_expr &:= ",";
c_expr.result_expr &:= integerLiteral(log2(base));
c_expr.result_expr &:= ",";
c_expr.result_expr &:= integerLiteral(pred(base));
c_expr.result_expr &:= ",";
c_expr.result_expr &:= str(ord(upperCase));
c_expr.result_expr &:= ")";
else
prepare_stri_result(c_expr);
c_expr.result_expr := "intRadix(";
getStdParamToResultExpr(param1, c_expr);
c_expr.result_expr &:= ", ";
c_expr.result_expr &:= integerLiteral(base);
c_expr.result_expr &:= ",";
c_expr.result_expr &:= str(ord(upperCase));
c_expr.result_expr &:= ")";
end if;
end func;
const proc: process_int_radix (in ref_list: params, in boolean: upperCase,
inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
begin
if getConstant(params[3], INTOBJECT, evaluatedParam) then
process_const_int_radix(params[1], getValue(evaluatedParam, integer),
upperCase, c_expr);
else
prepare_stri_result(c_expr);
c_expr.result_expr := "intRadix(";
getStdParamToResultExpr(params[1], c_expr);
c_expr.result_expr &:= ", ";
getStdParamToResultExpr(params[3], c_expr);
c_expr.result_expr &:= ",";
c_expr.result_expr &:= str(ord(upperCase));
c_expr.result_expr &:= ")";
end if;
end func;
const proc: process (INT_radix, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
process_int_radix(params, FALSE, c_expr);
end func;
const proc: process (INT_RADIX, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
process_int_radix(params, TRUE, c_expr);
end func;
const proc: process_const_int_rand (in integer: lowerBound, in integer: upperBound,
inout expr_type: c_expr) is func
local
const bigInteger: UINTTYPE_MAX is 18446744073709551615_;
var bigInteger: beyond is 0_;
var bigInteger: rand_max is 0_;
begin
incr(countOptimizations);
if lowerBound >= upperBound then
if lowerBound = upperBound then
c_expr.expr &:= integerLiteral(lowerBound);
else
warning(DOES_RAISE, "RANGE_ERROR", c_expr);
c_expr.expr &:= intRaiseError("RANGE_ERROR");
end if;
else
beyond := bigInteger(upperBound) - bigInteger(lowerBound) + 1_;
if beyond = succ(UINTTYPE_MAX) then
c_expr.expr &:= "(intType) uintRand()";
elsif 2_ ** ord(log2(beyond)) = beyond then
c_expr.expr &:= "(intType) (";
if lowerBound <> 0 then
c_expr.expr &:= "(uintType) ";
c_expr.expr &:= integerLiteral(lowerBound);
c_expr.expr &:= " + (";
end if;
c_expr.expr &:= "uintRand() & ";
c_expr.expr &:= str(pred(beyond));
c_expr.expr &:= "U";
c_expr.expr &:= ccConf.INTTYPE_LITERAL_SUFFIX;
if lowerBound <> 0 then
c_expr.expr &:= ")";
end if;
c_expr.expr &:= ")";
else
c_expr.expr &:= "(intType) (";
if lowerBound <> 0 then
c_expr.expr &:= "(uintType) ";
c_expr.expr &:= integerLiteral(lowerBound);
c_expr.expr &:= " + ";
end if;
rand_max := UINTTYPE_MAX - (succ(UINTTYPE_MAX) rem beyond);
c_expr.expr &:= "uintRandLimited(";
c_expr.expr &:= str(rand_max);
c_expr.expr &:= "U";
c_expr.expr &:= ccConf.INTTYPE_LITERAL_SUFFIX;
c_expr.expr &:= ") % ";
c_expr.expr &:= str(beyond);
c_expr.expr &:= "U";
c_expr.expr &:= ccConf.INTTYPE_LITERAL_SUFFIX;
c_expr.expr &:= ")";
end if;
end if;
end func;
const proc: process (INT_RAND, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedLowerBound is NIL;
var reference: evaluatedUpperBound is NIL;
begin
if getConstant(params[1], INTOBJECT, evaluatedLowerBound) and
getConstant(params[2], INTOBJECT, evaluatedUpperBound) then
process_const_int_rand(getValue(evaluatedLowerBound, integer),
getValue(evaluatedUpperBound, integer), c_expr);
else
c_expr.expr &:= "intRand(";
process_expr(params[1], c_expr);
c_expr.expr &:= ", ";
process_expr(params[2], c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: process_const_int_rem (in reference: dividend, in integer: divisor,
inout expr_type: c_expr) is func
local
var reference: evaluatedDividend is NIL;
var integer: dividend_value is 0;
var string: dividend_name is "";
var intRange: dividend_range is intRange.value;
begin
if divisor = 0 then
incr(countOptimizations);
warning(DOES_RAISE, "NUMERIC_ERROR", c_expr);
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
elsif divisor = 1 then
incr(countOptimizations);
c_expr.expr &:= "0";
elsif getConstant(dividend, INTOBJECT, evaluatedDividend) then
incr(countOptimizations);
dividend_value := getValue(evaluatedDividend, integer);
if divisor = -1 and dividend_value < -integer.last then
if reduceOverflowChecks then
countOverflowOptimizations(c_expr);
c_expr.expr &:= "/*no_overflow_check_rem*/ 0";
else
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
end if;
else
c_expr.expr &:= integerLiteral(dividend_value rem divisor);
end if;
elsif divisor = -1 then
incr(countOptimizations);
if not check_int_division_overflow then
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
c_expr.expr &:= "0";
elsif reduceOverflowChecks then
countOverflowOptimizations(c_expr);
c_expr.expr &:= "/*no_overflow_check_rem*/ 0";
else
incr(countOverflowChecks);
c_expr.expr &:= "(";
dividend_name := getParameterAsVariable("intType", "dividend_", dividend, c_expr);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= dividend_name;
c_expr.expr &:= "==";
c_expr.expr &:= integerLiteral(integer.first);
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":0)";
end if;
elsif divisor > 0 and 2 ** log2(divisor) = divisor then
dividend_range := getIntRange(dividend);
if dividend_range.minValue >= 0 then
incr(countOptimizations);
c_expr.expr &:= "(";
process_expr(dividend, c_expr);
c_expr.expr &:= ")";
c_expr.expr &:= "&";
c_expr.expr &:= integerLiteral(pred(divisor));
else
c_expr.expr &:= "(";
process_expr(dividend, c_expr);
c_expr.expr &:= ") % ";
c_expr.expr &:= integerLiteral(divisor);
end if;
else
c_expr.expr &:= "(";
process_expr(dividend, c_expr);
c_expr.expr &:= ") % ";
c_expr.expr &:= integerLiteral(divisor);
end if;
end func;
const proc: process_const_int_rem (in integer: dividend, in reference: divisor,
inout expr_type: c_expr) is func
local
var string: divisor_name is "";
var intRange: divisor_range is intRange.value;
begin
divisor_range := getIntRange(divisor);
if dividend = 0 then
incr(countOptimizations);
if integer_division_check then
if (divisor_range.minValue <= 0 and divisor_range.maxValue >= 0) or
divisor_range.mayRaiseException then
incr(countDivisionChecks);
c_expr.expr &:= "(divChk((";
process_expr(divisor, c_expr);
c_expr.expr &:= ")==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":0)";
else
countDivisionOptimizations(c_expr);
c_expr.expr &:= "0";
end if;
else
c_expr.expr &:= "0";
end if;
elsif check_int_division_overflow and dividend = integer.first then
c_expr.expr &:= "(";
divisor_name := getParameterAsVariable("intType", "divisor_", divisor, c_expr);
if divisor_range.minValue <= -1 and divisor_range.maxValue >= -1 then
incr(countOverflowChecks);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "==-1)?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
else
countOverflowOptimizations(c_expr);
end if;
if check_int_rem_by_zero then
if divisor_range.minValue <= 0 and divisor_range.maxValue >= 0 then
incr(countDivisionChecks);
c_expr.expr &:= "divChk(";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":";
else
countDivisionOptimizations(c_expr);
end if;
end if;
c_expr.expr &:= integerLiteral(dividend);
c_expr.expr &:= " % ";
c_expr.expr &:= divisor_name;
c_expr.expr &:= ")";
else
if dividend = integer.first then
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
end if;
if check_int_rem_by_zero then
if divisor_range.minValue <= 0 and divisor_range.maxValue >= 0 then
incr(countDivisionChecks);
c_expr.expr &:= "(";
divisor_name := getParameterAsVariable("intType", "divisor_", divisor, c_expr);
c_expr.expr &:= "divChk(";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= integerLiteral(dividend);
c_expr.expr &:= " % ";
c_expr.expr &:= divisor_name;
c_expr.expr &:= ")";
else
countDivisionOptimizations(c_expr);
c_expr.expr &:= integerLiteral(dividend);
c_expr.expr &:= " % (";
process_expr(divisor, c_expr);
c_expr.expr &:= ")";
end if;
else
c_expr.expr &:= integerLiteral(dividend);
c_expr.expr &:= " % (";
process_expr(divisor, c_expr);
c_expr.expr &:= ")";
end if;
end if;
end func;
const proc: process (INT_REM, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var string: dividend_name is "";
var string: divisor_name is "";
var intRange: dividend_range is intRange.value;
var intRange: divisor_range is intRange.value;
begin
if getConstant(params[3], INTOBJECT, evaluatedParam) then
process_const_int_rem(params[1], getValue(evaluatedParam, integer), c_expr);
elsif constValueIsEqual(params[3], -1) then
process_const_int_rem(params[1], -1, c_expr);
elsif getConstant(params[1], INTOBJECT, evaluatedParam) then
process_const_int_rem(getValue(evaluatedParam, integer), params[3], c_expr);
elsif evaluate_const_expr = 0 and check_int_rem_zero_by_zero and
category(params[1]) = INTOBJECT and not isVar(params[1]) and
getValue(params[1], integer) = 0 then
incr(countDivisionChecks);
c_expr.expr &:= "(divChk((";
process_expr(params[3], c_expr);
c_expr.expr &:= ")==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":0)";
else
divisor_range := getIntRange(params[3]);
if params[1] = params[3] then
if integer_division_check then
if (divisor_range.minValue <= 0 and divisor_range.maxValue >= 0) or
divisor_range.mayRaiseException then
incr(countDivisionChecks);
c_expr.expr &:= "(divChk((";
process_expr(params[1], c_expr);
c_expr.expr &:= ")==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":0)";
else
countDivisionOptimizations(c_expr);
c_expr.expr &:= "0";
end if;
else
c_expr.expr &:= "0";
end if;
elsif check_int_division_overflow then
dividend_range := getIntRange(params[1]);
c_expr.expr &:= "(";
dividend_name := getParameterAsVariable("intType", "dividend_", params[1], c_expr);
divisor_name := getParameterAsVariable("intType", "divisor_", params[3], c_expr);
if dividend_range.minValue = integer.first and
divisor_range.minValue <= -1 and divisor_range.maxValue >= -1 then
incr(countOverflowChecks);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= dividend_name;
c_expr.expr &:= "==";
c_expr.expr &:= integerLiteral(integer.first);
c_expr.expr &:= "&&";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "==-1";
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
else
countOverflowOptimizations(c_expr);
end if;
if check_int_rem_by_zero then
if divisor_range.minValue <= 0 and divisor_range.maxValue >= 0 then
incr(countDivisionChecks);
c_expr.expr &:= "divChk(";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":";
else
countDivisionOptimizations(c_expr);
end if;
end if;
c_expr.expr &:= dividend_name;
c_expr.expr &:= " % ";
c_expr.expr &:= divisor_name;
c_expr.expr &:= ")";
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
if check_int_rem_by_zero then
if divisor_range.minValue <= 0 and divisor_range.maxValue >= 0 then
incr(countDivisionChecks);
c_expr.expr &:= "(";
divisor_name := getParameterAsVariable("intType", "divisor_", params[3], c_expr);
c_expr.expr &:= "divChk(";
c_expr.expr &:= divisor_name;
c_expr.expr &:= "==0)?";
c_expr.expr &:= intRaiseError("NUMERIC_ERROR");
c_expr.expr &:= ":(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") % ";
c_expr.expr &:= divisor_name;
c_expr.expr &:= ")";
else
countDivisionOptimizations(c_expr);
c_expr.expr &:= "(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") % (";
process_expr(params[3], c_expr);
c_expr.expr &:= ")";
end if;
else
c_expr.expr &:= "(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") % (";
process_expr(params[3], c_expr);
c_expr.expr &:= ")";
end if;
end if;
end if;
end func;
const proc: process_const_int_rshift (in reference: number, in integer: rshift,
inout expr_type: c_expr) is func
local
var reference: evaluatedNumber is NIL;
var string: number_name is "";
begin
if rshift < 0 or rshift >= ccConf.INTTYPE_SIZE then
incr(countOptimizations);
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
elsif getConstant(number, INTOBJECT, evaluatedNumber) then
incr(countOptimizations);
c_expr.expr &:= integerLiteral(getValue(evaluatedNumber, integer) >> rshift);
elsif rshift = 0 then
incr(countOptimizations);
process_expr(number, c_expr);
else
if ccConf.RSHIFT_DOES_SIGN_EXTEND then
c_expr.expr &:= "(";
process_expr(number, c_expr);
c_expr.expr &:= ") >> ";
c_expr.expr &:= integerLiteral(rshift);
else
c_expr.expr &:= "(";
number_name := getParameterAsVariable("intType", "number_", number, c_expr);
doRshift(number_name, integerLiteral(rshift), c_expr);
c_expr.expr &:= ")";
end if;
end if;
end func;
const proc: process (INT_RSHIFT, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var string: number_name is "";
var string: rshift_name is "";
var intRange: rshift_range is intRange.value;
var boolean: doOverflowCheck is FALSE;
begin
if getConstant(params[3], INTOBJECT, evaluatedParam) then
process_const_int_rshift(params[1], getValue(evaluatedParam, integer), c_expr);
elsif ccConf.RSHIFT_DOES_SIGN_EXTEND then
if check_int_shift_overflow then
rshift_range := getIntRange(params[3]);
if rshift_range.minValue < 0 or
rshift_range.maxValue >= ccConf.INTTYPE_SIZE then
incr(countOverflowChecks);
doOverflowCheck := TRUE;
else
countOverflowOptimizations(c_expr);
c_expr.expr &:= "/*no_overflow_check_rshift*/";
end if;
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
end if;
if doOverflowCheck then
c_expr.expr &:= "(";
rshift_name := getParameterAsVariable("intType", "rshift_", params[3], c_expr);
c_expr.expr &:= "ovfChk(";
checkRangeFromZero(rshift_name, integerLiteral(ccConf.INTTYPE_SIZE), c_expr);
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") >> ";
c_expr.expr &:= rshift_name;
c_expr.expr &:= ")";
else
c_expr.expr &:= "(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") >> (";
process_expr(params[3], c_expr);
c_expr.expr &:= ")";
end if;
else
if check_int_shift_overflow then
rshift_range := getIntRange(params[3]);
if rshift_range.minValue < 0 or
rshift_range.maxValue >= ccConf.INTTYPE_SIZE then
incr(countOverflowChecks);
doOverflowCheck := TRUE;
else
countOverflowOptimizations(c_expr);
c_expr.expr &:= "/*no_overflow_check_rshift*/";
end if;
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
end if;
if doOverflowCheck then
incr(countOverflowChecks);
c_expr.expr &:= "(";
number_name := getParameterAsVariable("intType", "number_", params[1], c_expr);
rshift_name := getParameterAsVariable("intType", "rshift_", params[3], c_expr);
c_expr.expr &:= "ovfChk(";
checkRangeFromZero(rshift_name, integerLiteral(ccConf.INTTYPE_SIZE), c_expr);
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
doRshift(number_name, rshift_name, c_expr);
c_expr.expr &:= ")";
else
c_expr.expr &:= "(";
number_name := getParameterAsVariable("intType", "number_", params[1], c_expr);
c_expr.expr &:= number_name;
c_expr.expr &:= "<0?~(~";
c_expr.expr &:= number_name;
c_expr.expr &:= " >> (";
process_expr(params[3], c_expr);
c_expr.expr &:= ")):";
c_expr.expr &:= number_name;
c_expr.expr &:= " >> (";
process_expr(params[3], c_expr);
c_expr.expr &:= "))";
end if;
end if;
end func;
const proc: process_const_int_rshift_assign (in reference: variable, in integer: rshift,
inout expr_type: c_expr) is func
local
var string: variable_name is "";
var expr_type: statement is expr_type.value;
begin
if rshift < 0 or rshift >= ccConf.INTTYPE_SIZE then
incr(countOptimizations);
setDiagnosticLine(c_expr);
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= raiseError("OVERFLOW_ERROR");
elsif rshift = 0 then
incr(countOptimizations);
c_expr.expr &:= "/* ignore integer >>:= 0; */\n";
elsif ccConf.RSHIFT_DOES_SIGN_EXTEND then
process_expr(variable, statement);
statement.expr &:= ">>=";
statement.expr &:= integerLiteral(rshift);
statement.expr &:= ";\n";
doLocalDeclsOfStatement(statement, c_expr);
else
variable_name := getParameterAsReference("intType", "variable_", variable, statement);
statement.expr &:= variable_name;
statement.expr &:= "<0?";
statement.expr &:= variable_name;
statement.expr &:= "= ~(~";
statement.expr &:= variable_name;
statement.expr &:= " >> ";
statement.expr &:= integerLiteral(rshift);
statement.expr &:= "):(";
statement.expr &:= variable_name;
statement.expr &:= " >>= ";
statement.expr &:= integerLiteral(rshift);
statement.expr &:= ");\n";
doLocalDeclsOfStatement(statement, c_expr);
end if;
end func;
const proc: process (INT_RSHIFT_ASSIGN, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var expr_type: statement is expr_type.value;
var string: variable_name is "";
var string: rshift_name is "";
begin
if getConstant(params[3], INTOBJECT, evaluatedParam) then
process_const_int_rshift_assign(params[1], getValue(evaluatedParam, integer), c_expr);
elsif ccConf.RSHIFT_DOES_SIGN_EXTEND then
if check_int_shift_overflow then
incr(countOverflowChecks);
rshift_name := getParameterAsVariable("intType", "rshift_", params[3], statement);
statement.expr &:= "ovfChk(";
checkRangeFromZero(rshift_name, integerLiteral(ccConf.INTTYPE_SIZE), statement);
statement.expr &:= ")?";
statement.expr &:= intRaiseError("OVERFLOW_ERROR");
statement.expr &:= ":(";
process_expr(params[1], statement);
statement.expr &:= ">>=";
statement.expr &:= rshift_name;
statement.expr &:= ");\n";
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
process_expr(params[1], statement);
statement.expr &:= ">>=";
process_expr(params[3], statement);
statement.expr &:= ";\n";
end if;
doLocalDeclsOfStatement(statement, c_expr);
else
variable_name := getParameterAsReference("intType", "variable_", params[1], statement);
rshift_name := getParameterAsVariable("intType", "rshift_", params[3], statement);
if check_int_shift_overflow then
incr(countOverflowChecks);
statement.expr &:= "ovfChk(";
checkRangeFromZero(rshift_name, integerLiteral(ccConf.INTTYPE_SIZE), statement);
statement.expr &:= ")?";
statement.expr &:= intRaiseError("OVERFLOW_ERROR");
statement.expr &:= ":";
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
end if;
statement.expr &:= variable_name;
statement.expr &:= "<0? ";
statement.expr &:= variable_name;
statement.expr &:= "= ~(~";
statement.expr &:= variable_name;
statement.expr &:= " >> ";
statement.expr &:= rshift_name;
statement.expr &:= "):(";
statement.expr &:= variable_name;
statement.expr &:= " >>= ";
statement.expr &:= rshift_name;
statement.expr &:= ");\n";
doLocalDeclsOfStatement(statement, c_expr);
end if;
end func;
const proc: process (INT_SBTR, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var string: minuend_name is "";
var string: subtrahend_name is "";
begin
if callOptimizeIntAdd then
optimize_int_add(params, FALSE, c_expr);
elsif getConstant(params[3], INTOBJECT, evaluatedParam) then
process_const_int_sbtr(params[1], getValue(evaluatedParam, integer), c_expr);
elsif getConstant(params[1], INTOBJECT, evaluatedParam) then
process_const_int_sbtr(getValue(evaluatedParam, integer), params[3], c_expr);
else
process_int_sbtr(params[1], params[3], c_expr);
end if;
end func;
const proc: process_const_int_sbtr_assign (in reference: variable, in integer: delta,
inout expr_type: c_expr) is func
local
var string: variable_name is "";
var expr_type: statement is expr_type.value;
begin
if delta = 0 then
incr(countOptimizations);
c_expr.expr &:= "/* ignore integer -:= 0; */\n";
elsif check_int_arithmetic_overflow then
incr(countOptimizations);
incr(countOverflowChecks);
variable_name := getParameterAsReference("intType", "variable_", variable, statement);
statement.expr &:= "if (ovfChk(";
statement.expr &:= variable_name;
if delta = -1 then
statement.expr &:= "==";
statement.expr &:= integerLiteral(integer.last);
elsif delta = 1 then
statement.expr &:= "==";
statement.expr &:= integerLiteral(integer.first);
elsif delta < 0 then
statement.expr &:= ">";
statement.expr &:= integerLiteral(integer.last + delta);
else
statement.expr &:= "<";
statement.expr &:= integerLiteral(integer.first + delta);
end if;
statement.expr &:= ")) {\n";
statement.expr &:= raiseError("OVERFLOW_ERROR");
statement.expr &:= "} else {\n";
statement.expr &:= variable_name;
statement.expr &:= "-=";
statement.expr &:= integerLiteral(delta);
statement.expr &:= ";\n";
statement.expr &:= "}\n";
doLocalDeclsOfStatement(statement, c_expr);
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
process_expr(variable, statement);
statement.expr &:= "-=";
statement.expr &:= integerLiteral(delta);
statement.expr &:= ";\n";
doLocalDeclsOfStatement(statement, c_expr);
end if;
end func;
const proc: process (INT_SBTR_ASSIGN, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var string: variable_name is "";
var string: delta_name is "";
var intRange: deltaRange is intRange.value;
var expr_type: statement is expr_type.value;
begin
if getConstant(params[3], INTOBJECT, evaluatedParam) then
process_const_int_sbtr_assign(params[1], getValue(evaluatedParam, integer), c_expr);
elsif check_int_arithmetic_overflow then
incr(countOverflowChecks);
deltaRange := getIntRange(params[3]);
if deltaRange.minValue = 0 and deltaRange.maxValue = 0 then
c_expr.expr &:= "/* ignore integer -:= 0; */\n";
else
variable_name := getParameterAsReference("intType", "variable_", params[1], statement);
if ccConf.BUILTIN_SUB_OVERFLOW <> "" then
statement.expr &:= "ovfChk(";
statement.expr &:= ccConf.BUILTIN_SUB_OVERFLOW;
statement.expr &:= "(";
statement.expr &:= variable_name;
statement.expr &:= ", ";
process_expr(params[3], statement);
statement.expr &:= ", &(";
statement.expr &:= variable_name;
statement.expr &:= ")))?";
statement.expr &:= intRaiseError("OVERFLOW_ERROR");
statement.expr &:= ":0;\n";
else
delta_name := getParameterAsVariable("intType", "delta_", params[3], statement);
if deltaRange.minValue < 0 or deltaRange.maxValue > 0 then
statement.expr &:= "ovfChk(";
if deltaRange.minValue < 0 and deltaRange.maxValue > 0 then
statement.expr &:= delta_name;
statement.expr &:= "<0&&";
statement.expr &:= variable_name;
statement.expr &:= ">";
statement.expr &:= integerLiteral(integer.last);
statement.expr &:= "+";
statement.expr &:= delta_name;
statement.expr &:= " || ";
statement.expr &:= delta_name;
statement.expr &:= ">=0&&";
statement.expr &:= variable_name;
statement.expr &:= "<";
statement.expr &:= integerLiteral(integer.first);
statement.expr &:= "+";
statement.expr &:= delta_name;
elsif deltaRange.minValue < 0 then
statement.expr &:= variable_name;
statement.expr &:= ">";
statement.expr &:= integerLiteral(integer.last);
statement.expr &:= "+";
statement.expr &:= delta_name;
else
statement.expr &:= variable_name;
statement.expr &:= "<";
statement.expr &:= integerLiteral(integer.first);
statement.expr &:= "+";
statement.expr &:= delta_name;
end if;
statement.expr &:= ")?";
statement.expr &:= intRaiseError("OVERFLOW_ERROR");
statement.expr &:= ":";
end if;
statement.expr &:= "(";
statement.expr &:= variable_name;
statement.expr &:= "-=";
statement.expr &:= delta_name;
statement.expr &:= ");\n";
end if;
doLocalDeclsOfStatement(statement, c_expr);
end if;
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
process_expr(params[1], statement);
statement.expr &:= "-=";
process_expr(params[3], statement);
statement.expr &:= ";\n";
doLocalDeclsOfStatement(statement, c_expr);
end if;
end func;
const proc: process (INT_SQRT, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
c_expr.expr &:= "intSqrt(";
process_expr(params[1], c_expr);
c_expr.expr &:= ")";
end func;
const proc: process (INT_STR, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
process_int_str(params[1], c_expr);
end func;
const proc: process (INT_SUCC, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var string: number_name is "";
var integer: number is 0;
begin
if callOptimizeIntAdd then
optimize_int_add(params[1], 1, c_expr);
elsif getConstant(params[1], INTOBJECT, evaluatedParam) then
incr(countOptimizations);
number := getValue(evaluatedParam, integer);
if number = integer.last then
warning(DOES_RAISE, "OVERFLOW_ERROR", c_expr);
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
else
c_expr.expr &:= integerLiteral(succ(number));
end if;
elsif check_int_arithmetic_overflow then
incr(countOverflowChecks);
c_expr.expr &:= "(";
number_name := getParameterAsVariable("intType", "number_", params[1], c_expr);
c_expr.expr &:= "ovfChk(";
c_expr.expr &:= number_name;
c_expr.expr &:= "==";
c_expr.expr &:= integerLiteral(integer.last);
c_expr.expr &:= ")?";
c_expr.expr &:= intRaiseError("OVERFLOW_ERROR");
c_expr.expr &:= ":";
c_expr.expr &:= number_name;
c_expr.expr &:= "+1)";
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
c_expr.expr &:= "(";
process_expr(params[1], c_expr);
c_expr.expr &:= ")+1";
end if;
end func;
const proc: process (INT_VALUE, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
c_expr.expr &:= "intValue(";
process_expr(params[1], c_expr);
c_expr.expr &:= ")";
end func;