当前位置:  开发笔记 > 前端 > 正文

为Ada Array of Records循环生成了什么代码?

如何解决《为AdaArrayofRecords循环生成了什么代码?》经验,为你挑选了2个好方法。

例如:

type PERSONCV is
   record
      name: String ( 1..4 );
      age: Integer;
      cvtext: String ( 1..2000 );
   end record;

N: constant := 40000;
persons : array ( 1..N ) of PERSONCV;

function jobcandidate return Boolean is
   iscandidate: Boolean := False;
begin
   for p of persons loop   -- what code is generated for this?
      if p.age >= 18 then
         iscandidate := true;
         exit;
      end if;
   end loop;
   return iscandidate;
end;

在C/C++中,循环部分通常是:

PERSONCV * p; // address pointer
int k = 0;
while ( k < N )
   {
   p = &persons [ k ]; // pointer to k'th record
   if ( p->age >= 18 )...  
   ...
   k++ ;
   }

我读过Ada对记录使用Value语义.上面的Ada循环是否将第k个记录复制到循环变量p?例如,这是在C/C++中:

PERSONCV p; // object/variable
int k = 0;
while ( k < N )
   {
   memcpy ( &p, &persons [ k ], sizeof ( PERSONCV ) ); // copies k'th elem 
   if ( p.age >= 18 )...  
   ...
   k++ ;
   }

Simon Wright.. 13

假设您使用的是GNAT,则有两种调查途径.

交换机-gnatG将重新生成类似Ada的表示,表示编译器的前端将传递到后端(在任何优化之前).在这种情况下,我明白了

   function resander__jobcandidate return boolean is
      iscandidate : boolean := false;
      L_1 : label
   begin
      L_1 : for C8b in 1 .. 40000 loop
         p : resander__personcv renames resander__persons (C8b);
         if p.age >= 18 then
            iscandidate := true;
            exit;
         end if;
      end loop L_1;
      return iscandidate;
   end resander__jobcandidate;

所以问题是,如何renames翻译?鉴于记录大小是2008字节,编译器生成副本的几率几乎为零.

第二种调查方法是保留编译器通常发送给汇编器的汇编代码,然后使用该开关删除-S.这证实生成的代码就像您的第一个C++版本(对于macOS).

作为一个有趣的侧面,Ada 2012允许替代实施jobcandidate:

   function jobcandidate2 return Boolean is
     (for some p of persons => p.age >= 18);

它生成相同的代码.



1> Simon Wright..:

假设您使用的是GNAT,则有两种调查途径.

交换机-gnatG将重新生成类似Ada的表示,表示编译器的前端将传递到后端(在任何优化之前).在这种情况下,我明白了

   function resander__jobcandidate return boolean is
      iscandidate : boolean := false;
      L_1 : label
   begin
      L_1 : for C8b in 1 .. 40000 loop
         p : resander__personcv renames resander__persons (C8b);
         if p.age >= 18 then
            iscandidate := true;
            exit;
         end if;
      end loop L_1;
      return iscandidate;
   end resander__jobcandidate;

所以问题是,如何renames翻译?鉴于记录大小是2008字节,编译器生成副本的几率几乎为零.

第二种调查方法是保留编译器通常发送给汇编器的汇编代码,然后使用该开关删除-S.这证实生成的代码就像您的第一个C++版本(对于macOS).

作为一个有趣的侧面,Ada 2012允许替代实施jobcandidate:

   function jobcandidate2 return Boolean is
     (for some p of persons => p.age >= 18);

它生成相同的代码.


我喜欢替代实现!
另见[*Ada 2012的基本原理,§3.4量化表达式*](http://www.ada-auth.org/standards/12rat/html/Rat12-3-4.html).

2> Brian Drummo..:

我怀疑你读到的有关Ada的内容是错误的,而且可能更糟糕的是,鼓励你以错误的方式思考Ada.

Ada的目的是鼓励在问题领域进行思考,即指定应该发生什么,而不是在解决方案领域进行思考,即实现精确的细节.

所以这里的目的是遍历所有人,在第一次超过18时退出返回True,否则返回False.

就是这样.

一般来说,只要这些语义得到满足,Ada就不会详细说明它是如何完成的.

然后,意图是,你只希望编译器做正确的事情.

现在,单个编译器可以选择一个实现而不是另一个 - 或者可以根据优化启发式在实现之间切换,考虑它正在编译的CPU,以及对象的大小(它们是否适合寄存器?)等.

您可以想象一个具有许多寄存器的CPU,其中单个高速缓存行读取使得复制实现比在适当位置操作更快(特别是如果没有修改以回写到P的内容),或者反向为真的其他目标CPU.为什么要阻止编译器选择更好的实现?

这方面的一个很好的例子是艾达对参数传递到子程序的做法-名称,值或引用传递真的不适用-相反,您指定的参数传递模式- in,outin out描述信息流(或)子程序.直观,提供可以更严格检查的语义,并使编译器可以自由选择正确遵循这些语义的最佳(最快,最小,取决于您的目标)实现.

现在,特定的Ada编译器可能会做出糟糕的选择,而30年前,当计算机根本不足以运行Ada编译器时,您可能会发现在编译器的早期版本中,为了简单起见,性能受到了损害.

但是我们现在有三十多年的编译器开发,在更强大的计算机上运行.所以,今天,我希望编译器能够正常地做出最佳选择.如果您发现某个特定编译器错过了性能优化,请提交增强请求.Ada编译器并不完美,就像任何其他编译器一样.

在这个具体的例子中,我通常希望P成为数组的游标,并且操作就地发生,即引用语义.或者可能是表单之间的混合,其中一个存储器提取到寄存器中用于多个操作,如部分形式的值语义.

如果您的兴趣是学术性的,您可以轻松查看您正在使用的任何编译器的汇编输出并找出答案.或者写上面的所有三个版本并对它们进

推荐阅读
小白也坚强_177
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有