const ACTION: BIN_AND is action "BIN_AND";
const ACTION: BIN_AND_ASSIGN is action "BIN_AND_ASSIGN";
const ACTION: BIN_BIG is action "BIN_BIG";
const ACTION: BIN_BINARY is action "BIN_BINARY";
const ACTION: BIN_BIT_LENGTH is action "BIN_BIT_LENGTH";
const ACTION: BIN_BYTES_BE_2_UINT is action "BIN_BYTES_BE_2_UINT";
const ACTION: BIN_BYTES_LE_2_UINT is action "BIN_BYTES_LE_2_UINT";
const ACTION: BIN_CARD is action "BIN_CARD";
const ACTION: BIN_CMP is action "BIN_CMP";
const ACTION: BIN_GET_BINARY_FROM_SET is action "BIN_GET_BINARY_FROM_SET";
const ACTION: BIN_LOWEST_SET_BIT is action "BIN_LOWEST_SET_BIT";
const ACTION: BIN_LSHIFT is action "BIN_LSHIFT";
const ACTION: BIN_LSHIFT_ASSIGN is action "BIN_LSHIFT_ASSIGN";
const ACTION: BIN_N_BYTES_BE is action "BIN_N_BYTES_BE";
const ACTION: BIN_N_BYTES_LE is action "BIN_N_BYTES_LE";
const ACTION: BIN_OR is action "BIN_OR";
const ACTION: BIN_OR_ASSIGN is action "BIN_OR_ASSIGN";
const ACTION: BIN_radix is action "BIN_radix";
const ACTION: BIN_RADIX is action "BIN_RADIX";
const ACTION: BIN_RSHIFT is action "BIN_RSHIFT";
const ACTION: BIN_RSHIFT_ASSIGN is action "BIN_RSHIFT_ASSIGN";
const ACTION: BIN_STR is action "BIN_STR";
const ACTION: BIN_XOR is action "BIN_XOR";
const ACTION: BIN_XOR_ASSIGN is action "BIN_XOR_ASSIGN";
const proc: bin_prototypes (inout file: c_prog) is func
begin
declareExtern(c_prog, "uintType setToUInt (const const_setType, const intType);");
declareExtern(c_prog, "uintType uintBytesBe2UInt (const const_striType);");
declareExtern(c_prog, "uintType uintBytesLe2UInt (const const_striType);");
declareExtern(c_prog, "intType uintCard (uintType);");
declareExtern(c_prog, "intType uintCmp (uintType, uintType);");
declareExtern(c_prog, "intType uintCmpGeneric (const genericType, const genericType);");
declareExtern(c_prog, "striType uintNBytesBe (uintType, intType);");
declareExtern(c_prog, "striType uintNBytesLe (uintType, intType);");
declareExtern(c_prog, "striType uintRadix (uintType, intType, boolType);");
declareExtern(c_prog, "striType uintRadixPow2 (uintType, int, int, boolType);");
declareExtern(c_prog, "striType uintStr (uintType);");
declareExtern(c_prog, "int uint64LeastSignificantBit (uintType);");
declareExtern(c_prog, "int uint64MostSignificantBit (uintType);");
end func;
const proc: process_str_substr_slice (in reference: stri,
in reference: start, in reference: length, in string: slice_name,
inout expr_type: c_expr) is forward;
const proc: process_str_substr_fixlen_slice (in reference: stri,
in reference: start, in reference: length, in string: slice_name,
inout expr_type: c_expr) is forward;
const proc: optimize_mod_dividend (in reference: dividend, inout expr_type: c_expr) is forward;
const proc: process_const_bin_and (in reference: bits1, in integer: bits2,
inout expr_type: c_expr) is func
begin
if bits2 = 0 then
incr(countOptimizations);
c_expr.expr &:= "/*a & 0*/";
c_expr.expr &:= integerLiteral(bits2);
elsif modDividendOptimization then
incr(countOptimizations);
c_expr.expr &:= "(";
if isActionExpression(bits1, "BIN_BINARY") then
if bits2 > 0 and (bits2 = integer.last or
2 ** log2(succ(bits2)) = succ(bits2)) then
optimize_big_mod_dividend(getActionParameter(bits1, 1),
succ(bigInteger(bits2)), c_expr);
else
optimize_big_mod_dividend(getActionParameter(bits1, 1),
succ(bigInteger(bin64(-1))), c_expr);
end if;
else
optimize_mod_dividend(bits1, c_expr);
end if;
c_expr.expr &:= ")";
if bits2 <> ord(~bin64(0)) then
c_expr.expr &:= " & ";
c_expr.expr &:= integerLiteral(bits2);
end if;
else
c_expr.expr &:= "(";
process_expr(bits1, c_expr);
c_expr.expr &:= ") & ";
c_expr.expr &:= integerLiteral(bits2);
end if;
end func;
const proc: process (BIN_AND, 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_bin_and(params[3], getValue(evaluatedParam, integer), c_expr);
elsif getConstant(params[3], INTOBJECT, evaluatedParam) then
process_const_bin_and(params[1], getValue(evaluatedParam, integer), c_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 func;
const proc: process (BIN_AND_ASSIGN, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var expr_type: statement is expr_type.value;
begin
process_expr(params[1], statement);
statement.expr &:= "&=";
process_expr(params[3], statement);
statement.expr &:= ";\n";
doLocalDeclsOfStatement(statement, c_expr);
end func;
const proc: process (BIN_BIG, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
prepare_bigint_result(c_expr);
c_expr.result_expr := "bigFromUInt64(";
getAnyParamToResultExpr(params[1], c_expr);
c_expr.result_expr &:= ")";
end func;
const proc: optimize_bin_binary_of_big_mod (in reference: param1,
in reference: dividend, in bigInteger: divisor,
inout expr_type: c_expr) is func
begin
if divisor > 0_ and log2(divisor) <= 64_ and
2_ ** ord(log2(divisor)) = divisor then
optimize_big_mod_dividend(dividend, divisor, c_expr);
if log2(divisor) < 64_ then
c_expr.expr &:= "&";
c_expr.expr &:= integerLiteral(ord(pred(divisor)));
end if;
else
c_expr.expr &:= "bigToUInt64(";
getAnyParamToExpr(param1, c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: process (BIN_BINARY, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
begin
if evaluate_const_expr >= 1 and
isActionExpression(params[1], "BIG_MOD") and
getConstant(getActionParameter(params[1], 3),
BIGINTOBJECT, evaluatedParam) then
optimize_bin_binary_of_big_mod(params[1],
getActionParameter(params[1], 1),
getValue(evaluatedParam, bigInteger), c_expr);
else
c_expr.expr &:= "bigToUInt64(";
getAnyParamToExpr(params[1], c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: process (BIN_BIT_LENGTH, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
c_expr.expr &:= "(intType) uint64MostSignificantBit(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") + 1";
end func;
const proc: optimize_bin_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_bin_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 &:= "(uintType)";
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_bin_bytes_be_2_uint (in string: slice_name, in integer: length,
in string: or_name, in string: result_name, inout expr_type: c_expr) is func
local
var integer: index is 0;
begin
for index range 1 to length do
if function_range_check then
incr(countRangeChecks);
c_expr.expr &:= or_name;
if index <> 1 then
c_expr.expr &:= "|";
end if;
c_expr.expr &:= "=(uintType)";
c_expr.expr &:= slice_name;
c_expr.expr &:= ".mem[";
c_expr.expr &:= integerLiteral(pred(index));
c_expr.expr &:= "],";
else
incr(countNoRangeChecks);
end if;
c_expr.expr &:= result_name;
if index <> 1 then
c_expr.expr &:= "|";
end if;
c_expr.expr &:= "=(uintType)";
c_expr.expr &:= slice_name;
c_expr.expr &:= ".mem[";
c_expr.expr &:= integerLiteral(pred(index));
c_expr.expr &:= "]";
if index < length then
c_expr.expr &:= "<<";
c_expr.expr &:= integerLiteral((length - index) * 8);
end if;
c_expr.expr &:= ",";
end for;
if function_range_check then
c_expr.expr &:= "rngChk(";
c_expr.expr &:= or_name;
c_expr.expr &:= ">255)?";
c_expr.expr &:= intRaiseError("RANGE_ERROR");
c_expr.expr &:= ":";
end if;
c_expr.expr &:= result_name;
end func;
const proc: optimize_bin_bytes_be_2_uint (in reference: stri,
in reference: start, in reference: lengthRef, in integer: length,
in boolean: fixedLengthSubstring, inout expr_type: c_expr) is func
local
var string: or_name is "";
var string: result_name is "";
var string: slice_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_bin_bytes_2_uint_length_0(getActionParameter(stri, 1),
start, fixedLengthSubstring, c_expr);
elsif length = 1 then
optimize_bin_bytes_2_uint_length_1(getActionParameter(stri, 1),
start, fixedLengthSubstring, c_expr);
elsif ccConf.ALLOW_STRITYPE_SLICES and length >= 2 and length <= 8 then
incr(countOptimizations);
incr(countInlinedFunctions);
c_expr.expr &:= "(";
if function_range_check then
or_name := defineTempVariable("uintType", "or_", c_expr);
end if;
result_name := defineTempVariable("uintType", "result_", c_expr);
incr(c_expr.temp_num);
slice_name := "slice_" & str(c_expr.temp_num);
if fixedLengthSubstring then
process_str_substr_fixlen_slice(getActionParameter(stri, 1), start,
lengthRef, slice_name, c_expr);
c_expr.expr &:= ", ";
optimize_bin_bytes_be_2_uint(slice_name, length, or_name, result_name, c_expr);
else
process_str_substr_slice(getActionParameter(stri, 1), start,
lengthRef, slice_name, c_expr);
c_expr.expr &:= ", ";
c_expr.expr &:= slice_name;
c_expr.expr &:= ".size==";
c_expr.expr &:= integerLiteral(length);
c_expr.expr &:= "?(";
optimize_bin_bytes_be_2_uint(slice_name, length, or_name, result_name, c_expr);
c_expr.expr &:= "):uintBytesBe2UInt(&";
c_expr.expr &:= slice_name;
c_expr.expr &:= ")";
end if;
c_expr.expr &:= ")";
else
c_expr.expr &:= "uintBytesBe2UInt(";
getAnyParamToExpr(stri, c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: process (BIN_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_bin_bytes_be_2_uint(params[1], getActionParameter(params[1], 3),
getActionParameter(params[1], 5), 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_bin_bytes_be_2_uint(params[1], getActionParameter(params[1], 3),
getActionParameter(params[1], 5), getValue(evaluatedParam, integer), TRUE, c_expr);
else
c_expr.expr &:= "uintBytesBe2UInt(";
getAnyParamToExpr(params[1], c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: optimize_bin_bytes_le_2_uint (in string: slice_name, in integer: length,
in string: or_name, in string: result_name, inout expr_type: c_expr) is func
local
var integer: index is 0;
begin
for index range 1 to length do
if function_range_check then
incr(countRangeChecks);
c_expr.expr &:= or_name;
if index <> 1 then
c_expr.expr &:= "|";
end if;
c_expr.expr &:= "=(uintType)";
c_expr.expr &:= slice_name;
c_expr.expr &:= ".mem[";
c_expr.expr &:= integerLiteral(pred(index));
c_expr.expr &:= "],";
else
incr(countNoRangeChecks);
end if;
c_expr.expr &:= result_name;
if index <> 1 then
c_expr.expr &:= "|";
end if;
c_expr.expr &:= "=(uintType)";
c_expr.expr &:= slice_name;
c_expr.expr &:= ".mem[";
c_expr.expr &:= integerLiteral(pred(index));
c_expr.expr &:= "]";
if index <> 1 then
c_expr.expr &:= "<<";
c_expr.expr &:= integerLiteral(pred(index) * 8);
end if;
c_expr.expr &:= ",";
end for;
if function_range_check then
c_expr.expr &:= "rngChk(";
c_expr.expr &:= or_name;
c_expr.expr &:= ">255)?";
c_expr.expr &:= intRaiseError("RANGE_ERROR");
c_expr.expr &:= ":";
end if;
c_expr.expr &:= result_name;
end func;
const proc: optimize_bin_bytes_le_2_uint (in reference: stri,
in reference: start, in reference: lengthRef, in integer: length,
in boolean: fixedLengthSubstring, inout expr_type: c_expr) is func
local
var string: or_name is "";
var string: result_name is "";
var string: slice_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_bin_bytes_2_uint_length_0(getActionParameter(stri, 1),
start, fixedLengthSubstring, c_expr);
elsif length = 1 then
optimize_bin_bytes_2_uint_length_1(getActionParameter(stri, 1),
start, fixedLengthSubstring, c_expr);
elsif ccConf.ALLOW_STRITYPE_SLICES and length >= 2 and length <= 8 then
incr(countOptimizations);
incr(countInlinedFunctions);
c_expr.expr &:= "(";
if function_range_check then
or_name := defineTempVariable("uintType", "or_", c_expr);
end if;
result_name := defineTempVariable("uintType", "result_", c_expr);
incr(c_expr.temp_num);
slice_name := "slice_" & str(c_expr.temp_num);
if fixedLengthSubstring then
process_str_substr_fixlen_slice(getActionParameter(stri, 1), start,
lengthRef, slice_name, c_expr);
c_expr.expr &:= ", ";
optimize_bin_bytes_le_2_uint(slice_name, length, or_name, result_name, c_expr);
else
process_str_substr_slice(getActionParameter(stri, 1), start,
lengthRef, slice_name, c_expr);
c_expr.expr &:= ", ";
c_expr.expr &:= slice_name;
c_expr.expr &:= ".size==";
c_expr.expr &:= integerLiteral(length);
c_expr.expr &:= "?(";
optimize_bin_bytes_le_2_uint(slice_name, length, or_name, result_name, c_expr);
c_expr.expr &:= "):uintBytesLe2UInt(&";
c_expr.expr &:= slice_name;
c_expr.expr &:= ")";
end if;
c_expr.expr &:= ")";
else
c_expr.expr &:= "uintBytesLe2UInt(";
getAnyParamToExpr(stri, c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: process (BIN_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_bin_bytes_le_2_uint(params[1], getActionParameter(params[1], 3),
getActionParameter(params[1], 5), 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_bin_bytes_le_2_uint(params[1], getActionParameter(params[1], 3),
getActionParameter(params[1], 5), getValue(evaluatedParam, integer), TRUE, c_expr);
else
c_expr.expr &:= "uintBytesLe2UInt(";
getAnyParamToExpr(params[1], c_expr);
c_expr.expr &:= ")";
end if;
end func;
const proc: process (BIN_CARD, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
c_expr.expr &:= "uintCard(";
process_expr(params[1], c_expr);
c_expr.expr &:= ")";
end func;
const proc: process (BIN_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("uintType", "num1_", params[1], c_expr);
number2_name := getParameterAsVariable("uintType", "num2_", 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 &:= "uintCmp(";
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 (BIN_GET_BINARY_FROM_SET, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
c_expr.expr &:= "setToUInt(";
getAnyParamToExpr(params[1], c_expr);
c_expr.expr &:= ", ";
process_expr(params[2], c_expr);
c_expr.expr &:= ")";
end func;
const proc: process (BIN_LOWEST_SET_BIT, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var string: numberName is "";
begin
c_expr.expr &:= "(intType)(";
numberName := getParameterAsVariable("uintType", "num1_", params[1], c_expr);
c_expr.expr &:= numberName;
c_expr.expr &:= " == 0 ? -1 : uint64LeastSignificantBit(";
c_expr.expr &:= numberName;
c_expr.expr &:= "))";
end func;
const proc: process_const_bin_lshift (in reference: number, in integer: lshift,
inout expr_type: c_expr) is func
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");
else
c_expr.expr &:= "(intType)((uintType)(";
process_expr(number, c_expr);
c_expr.expr &:= ") << ";
c_expr.expr &:= integerLiteral(lshift);
c_expr.expr &:= ")";
end if;
end func;
const proc: process (BIN_LSHIFT, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var string: lshift_name is "";
var intRange: lshift_range is intRange.value;
begin
if getConstant(params[3], INTOBJECT, evaluatedParam) then
process_const_bin_lshift(params[1], getValue(evaluatedParam, integer), c_expr);
elsif check_int_shift_overflow then
lshift_range := getIntRange(params[3]);
if lshift_range.minValue < 0 or
lshift_range.maxValue >= ccConf.INTTYPE_SIZE then
incr(countOverflowChecks);
c_expr.expr &:= "(";
lshift_name := getParameterAsVariable("intType", "lshift_", params[3], 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 &:= ":(intType)((uintType)(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") << ";
c_expr.expr &:= lshift_name;
c_expr.expr &:= "))";
else
countOverflowOptimizations(c_expr);
c_expr.expr &:= "/*no_overflow_check_lshift*/";
c_expr.expr &:= "(intType)((uintType)(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") << (";
process_expr(params[3], c_expr);
c_expr.expr &:= "))";
end if;
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
c_expr.expr &:= "(intType)((uintType)(";
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_bin_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");
else
variable_name := getParameterAsReference("intType", "tmp_", variable, statement);
statement.expr &:= variable_name;
statement.expr &:= "=(intType)((uintType)(";
statement.expr &:= variable_name;
statement.expr &:= ") << ";
statement.expr &:= integerLiteral(lshift);
statement.expr &:= ");\n";
doLocalDeclsOfStatement(statement, c_expr);
end if;
end func;
const proc: process (BIN_LSHIFT_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: lshift_name is "";
begin
if getConstant(params[3], INTOBJECT, evaluatedParam) then
process_const_bin_lshift_assign(params[1], getValue(evaluatedParam, integer), c_expr);
elsif check_int_shift_overflow then
incr(countOverflowChecks);
variable_name := getParameterAsReference("intType", "tmp_", params[1], statement);
lshift_name := getParameterAsVariable("intType", "tmp_", params[3], statement);
statement.expr &:= "ovfChk(";
checkRangeFromZero(lshift_name, integerLiteral(ccConf.INTTYPE_SIZE), statement);
statement.expr &:= ")?";
statement.expr &:= intRaiseError("OVERFLOW_ERROR");
statement.expr &:= ":(";
statement.expr &:= variable_name;
statement.expr &:= "=(intType)((uintType)(";
statement.expr &:= variable_name;
statement.expr &:= ") << ";
statement.expr &:= lshift_name;
statement.expr &:= "));\n";
doLocalDeclsOfStatement(statement, c_expr);
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
variable_name := getParameterAsReference("intType", "tmp_", params[1], statement);
statement.expr &:= variable_name;
statement.expr &:= "=(intType)((uintType)(";
statement.expr &:= variable_name;
statement.expr &:= ") << (";
process_expr(params[3], statement);
statement.expr &:= "));\n";
doLocalDeclsOfStatement(statement, c_expr);
end if;
end func;
const proc: process_const_bin_n_bytes_be (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 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 length < 8 and (numberValue >= 2 ** (8 * length) or numberValue < 0) then
warning(DOES_RAISE, "RANGE_ERROR", c_expr);
c_expr.expr &:= strRaiseError("RANGE_ERROR");
else
c_expr.expr &:= stringLiteral(bytes(bin64(numberValue), 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", "tmp_", number, c_expr);
if function_range_check and length < 8 then
incr(countRangeChecks);
c_expr.expr &:= "rngChk(";
c_expr.expr &:= "(uintType)";
c_expr.expr &:= number_name;
c_expr.expr &:= ">(uintType)";
c_expr.expr &:= integerLiteral(pred(2 ** (8 * length)));
c_expr.expr &:= ")?";
c_expr.expr &:= strRaiseError("RANGE_ERROR");
c_expr.expr &:= ":(";
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 &:= "((uintType)(";
c_expr.expr &:= number_name;
c_expr.expr &:= ")>>";
c_expr.expr &:= str(8 * (length - index));
else
c_expr.expr &:= "(uintType)(";
c_expr.expr &:= number_name;
end if;
c_expr.expr &:= ")";
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 function_range_check and length < 8 then
c_expr.expr &:= ")";
end if;
c_expr.expr &:= ")";
else
prepare_stri_result(c_expr);
c_expr.result_expr := "uintNBytesBe(";
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 (BIN_N_BYTES_BE, 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[3], INTOBJECT, evaluatedLength) then
process_const_bin_n_bytes_be(params[1],
getValue(evaluatedLength, integer), c_expr);
else
prepare_stri_result(c_expr);
c_expr.result_expr := "uintNBytesBe(";
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_bin_n_bytes_le (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 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 length < 8 and (numberValue >= 2 ** (8 * length) or numberValue < 0) then
warning(DOES_RAISE, "RANGE_ERROR", c_expr);
c_expr.expr &:= strRaiseError("RANGE_ERROR");
else
c_expr.expr &:= stringLiteral(bytes(bin64(numberValue), 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", "tmp_", number, c_expr);
if function_range_check and length < 8 then
incr(countRangeChecks);
c_expr.expr &:= "rngChk(";
c_expr.expr &:= "(uintType)";
c_expr.expr &:= number_name;
c_expr.expr &:= ">(uintType)";
c_expr.expr &:= integerLiteral(pred(2 ** (8 * length)));
c_expr.expr &:= ")?";
c_expr.expr &:= strRaiseError("RANGE_ERROR");
c_expr.expr &:= ":(";
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 &:= "((uintType)(";
c_expr.expr &:= number_name;
c_expr.expr &:= ")>>";
c_expr.expr &:= str(8 * pred(index));
else
c_expr.expr &:= "(uintType)(";
c_expr.expr &:= number_name;
end if;
c_expr.expr &:= ")";
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 function_range_check and length < 8 then
c_expr.expr &:= ")";
end if;
c_expr.expr &:= ")";
else
prepare_stri_result(c_expr);
c_expr.result_expr := "uintNBytesLe(";
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 (BIN_N_BYTES_LE, 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[3], INTOBJECT, evaluatedLength) then
process_const_bin_n_bytes_le(params[1],
getValue(evaluatedLength, integer), c_expr);
else
prepare_stri_result(c_expr);
c_expr.result_expr := "uintNBytesLe(";
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 (BIN_OR, 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 &:= ") | (";
process_expr(params[3], c_expr);
c_expr.expr &:= ")";
end func;
const proc: process (BIN_OR_ASSIGN, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var expr_type: statement is expr_type.value;
begin
process_expr(params[1], statement);
statement.expr &:= "|=";
process_expr(params[3], statement);
statement.expr &:= ";\n";
doLocalDeclsOfStatement(statement, c_expr);
end func;
const proc: process_bin_str (in reference: param1, inout expr_type: c_expr) is func
begin
prepare_stri_result(c_expr);
c_expr.result_expr := "uintStr(";
getStdParamToResultExpr(param1, c_expr);
c_expr.result_expr &:= ")";
end func;
const proc: process_const_bin_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_bin_str(param1, c_expr);
elsif 2 ** log2(base) = base then
incr(countOptimizations);
prepare_stri_result(c_expr);
c_expr.result_expr := "uintRadixPow2(";
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 := "uintRadix(";
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_bin_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_bin_radix(params[1], getValue(evaluatedParam, integer),
upperCase, c_expr);
else
prepare_stri_result(c_expr);
c_expr.result_expr := "uintRadix(";
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 (BIN_radix, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
process_bin_radix(params, FALSE, c_expr);
end func;
const proc: process (BIN_RADIX, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
process_bin_radix(params, TRUE, c_expr);
end func;
const proc: process_const_bin_rshift (in reference: number, in integer: rshift,
inout expr_type: c_expr) is func
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");
else
c_expr.expr &:= "(intType)((uintType)(";
process_expr(number, c_expr);
c_expr.expr &:= ") >> ";
c_expr.expr &:= integerLiteral(rshift);
c_expr.expr &:= ")";
end if;
end func;
const proc: process (BIN_RSHIFT, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var reference: evaluatedParam is NIL;
var string: rshift_name is "";
var intRange: rshift_range is intRange.value;
begin
if getConstant(params[3], INTOBJECT, evaluatedParam) then
process_const_bin_rshift(params[1], getValue(evaluatedParam, integer), c_expr);
elsif 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);
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 &:= ":(intType)((uintType)(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") >> ";
c_expr.expr &:= rshift_name;
c_expr.expr &:= "))";
else
countOverflowOptimizations(c_expr);
c_expr.expr &:= "/*no_overflow_check_rshift*/";
c_expr.expr &:= "(intType)((uintType)(";
process_expr(params[1], c_expr);
c_expr.expr &:= ") >> (";
process_expr(params[3], c_expr);
c_expr.expr &:= "))";
end if;
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
c_expr.expr &:= "(intType)((uintType)(";
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_bin_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");
else
variable_name := getParameterAsReference("intType", "tmp_", variable, statement);
statement.expr &:= variable_name;
statement.expr &:= "=(intType)((uintType)(";
statement.expr &:= variable_name;
statement.expr &:= ") >> ";
statement.expr &:= integerLiteral(rshift);
statement.expr &:= ");\n";
doLocalDeclsOfStatement(statement, c_expr);
end if;
end func;
const proc: process (BIN_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_bin_rshift_assign(params[1], getValue(evaluatedParam, integer), c_expr);
elsif check_int_shift_overflow then
incr(countOverflowChecks);
variable_name := getParameterAsReference("intType", "tmp_", params[1], statement);
rshift_name := getParameterAsVariable("intType", "tmp_", params[3], statement);
statement.expr &:= "ovfChk(";
checkRangeFromZero(rshift_name, integerLiteral(ccConf.INTTYPE_SIZE), statement);
statement.expr &:= ")?";
statement.expr &:= intRaiseError("OVERFLOW_ERROR");
statement.expr &:= ":(";
statement.expr &:= variable_name;
statement.expr &:= "=(intType)((uintType)(";
statement.expr &:= variable_name;
statement.expr &:= ") >> ";
statement.expr &:= rshift_name;
statement.expr &:= "));\n";
doLocalDeclsOfStatement(statement, c_expr);
else
countSuppressedOverflowChecks +:= ord(not integer_overflow_check);
variable_name := getParameterAsReference("intType", "tmp_", params[1], statement);
statement.expr &:= variable_name;
statement.expr &:= "=(intType)((uintType)(";
statement.expr &:= variable_name;
statement.expr &:= ") >> (";
process_expr(params[3], statement);
statement.expr &:= "));\n";
doLocalDeclsOfStatement(statement, c_expr);
end if;
end func;
const proc: process (BIN_STR, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
begin
process_bin_str(params[1], c_expr);
end func;
const proc: process (BIN_XOR, 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 &:= ") ^ (";
process_expr(params[3], c_expr);
c_expr.expr &:= ")";
end func;
const proc: process (BIN_XOR_ASSIGN, in reference: function,
in ref_list: params, inout expr_type: c_expr) is func
local
var expr_type: statement is expr_type.value;
begin
process_expr(params[1], statement);
statement.expr &:= "^=";
process_expr(params[3], statement);
statement.expr &:= ";\n";
doLocalDeclsOfStatement(statement, c_expr);
end func;