кстати, передача неоктрытых массивов без `IN` делает копии тоже по месту вызова, причём делается это уже силами кодогена, выделяя место на стеке через `ADD ESP, -size`. конечно, почистить это потом все забыли. ну ёлы-палы, ну… вот засунуть такое в длиииинный цикл — и офигеть от того, что внезапно, на пустом месте, закончится стек. какого чёрта это не делается в вызываемой процедуре?
отсюда запомните правило хорошего тона: никогда не вызывайте в цикле процедуру, которая принимает неоткрытый массив без `IN`.
короче, иллюстрация:
Код:
   TYPE S10 = ARRAY 10 OF CHAR;
   PROCEDURE Str2Proc (a: S10);
   PROCEDURE TestStr12;
   VAR b: S10;
   BEGIN
      Str2Proc(b); (* тут мы делаем копию b на стеке через ADD ESP *)
      Str2Proc(b); (* а тут ещё раз, забыв убрать старую копию, снова через ADD ESP *)
   END TestStr12;
делается две копии `b`. будет цикл — будет овердофига копий, место на стеке выделяется каждый раз. по-моему, это тупо баг, ребята забыли подкорректировать ESP в финале.
но.
Код:
   PROCEDURE Str0Proc (a: ARRAY OF CHAR);
   PROCEDURE TestStr13;
   VAR b: S10;
   BEGIN
      Str0Proc(b);
      Str0Proc(b);
   END TestStr13;
копии `b` делаются внутри `Str0Proc`, так что такой вызов из цикла безопасен.
Код:
   PROCEDURE Str1Proc (IN a: S10);
   PROCEDURE TestStr13;
   VAR b: S10;
   BEGIN
      Str1Proc(b);
      Str1Proc(b);
   END TestStr13;
никаких копий.
Код:
   PROCEDURE Str1Proc (IN a: S10);
   PROCEDURE TestStr14;
   VAR b: S10;
   BEGIN
      Str1Proc(b$);
      Str1Proc(b$);
   END TestStr14;
а вот тут всё происходит уровнем выше: заводятся две скрытые локальные перменные (по количеству вызовов). такая ерунда в цикле безопасна. то есть, место на стеке выделяется один раз, по визуальному счёту вызовов. собственно, реальный AST:
Код:
   PROCEDURE TestStr14
      VAR @str0: ARRAY 10 OF CHAR
      VAR @str1: ARRAY 10 OF CHAR
      VAR b: S10
   BEGIN
      COMPOUND
         @str0 := b$;
         CALL Str1Proc(@str0$);
      END COMPOUND;
      COMPOUND
         @str1 := b$;
         CALL Str1Proc(@str1$);
      END COMPOUND;
   END TestStr14