[疑难] [dmd bug]大家帮忙看一下if表达式内赋值为何失败
lifc
2009-08-07
这几天同事移植了一段代码到D,这一段反复调试都断言失败,各位帮忙看一下什么原因。
class ByteBuffer { uint idx, limit; } void main () { ByteBuffer bb = new ByteBuffer; uint offset; with (bb) { limit = idx; idx = 0; if (idx <= limit && (idx + (offset = 18) <= 100)) assert(offset == 18); } } 这是精简后的代码,里面加了一些无关语句为的是重现问题。若去掉一些语句或者调换顺序断言通过,所以怀疑又是编译器bug,因为只有用dmd -O编译才出现断言失败。 |
|
lifc
2009-08-07
看了反编译代码,确认是编译器问题,试过近几年的D1/D2各种版本只要加-O优化编译就统统有这个bug。ldc和gdc没问题,上面的简单程序因它们太聪明,直接优化省略掉了全部代码。
cmp EBX,0Ch[ESI] ja L45 push EBX mov EBX,012h mov ECX,EBX pop EBX ; <-------- 这里提前pop出ebx,覆盖了if里面赋值的18 lea EDX,[ECX][EBX] cmp EDX,064h ja L45 cmp EBX,012h je L45 mov EAX,0Ch call near ptr _D12assign_in_if8__assertFiZv@PC32 L45: pop ESI 最近遇到此类bug太多懒得上报了。刚刚在部门内部通报,不要把赋值语句写在if/while里面。大家以后写代码时自己小心吧! |
|
lifc
2009-08-07
上面反编译代码也可以看出,dmd优化编译效率和它的胞兄dmc一样需要大大提高。我这里有些稍微复杂一点的函数逻辑用dmd -O编译2~3KB,而ldc/gdc -O2才6~7百字节。
|
|
tomqyp
2009-08-07
要说目标文件体积的话,出错的这段代码我感觉实在是没法再压缩了,可以说要结果正确话还非加两行不可了。
呵呵,再说你这表达式也太长了。我估计编译到你出错的地方编译器肯定想:“糟了,寄存器不够了!怎么办,用内存寻址?现在可是加了-O命令的啊,太折WB老人家的面子了吧,干脆给这小子省两行代码得了!” 其实我也就用D1写过几个自己用的小工具也经常遇到许多问题,不知道经常用D的高人们怎么看,我是觉得不能让WB无休止的把精力都放到新特性上去了。 再说我们遇到bug不能懒得上报,上报了是不知道什么时候会修补,不上报可能就没机会被修补了,特别是这么严重的bug。 |
|
lifc
2009-08-07
上面的代码只是一个最小化重现代码,但已经有几处无谓的寄存器迁移和stack访问了。比如说这几行汇编:
push EBX mov EBX,012h mov ECX,EBX pop EBX ; 为何先push ebx再用ebx做中间寄存器向ecx传递,然后弹出ebx呢?虽没有仔细看过dmd、dmc的寄存器分配代码,但过去搞过集中单片机、dsp和假想机的编译器和JIT仿真器,感觉dmd和dmc缺少类似gcc必要的中间代码生成能力,致使它难以对操作码进行宏观优化。 对于gcc、lvm这样的高级编译器来说,上述代码完全可以优化成一句assert(true),如果编译器中加入了对assert的built in描述(例如gcc)甚至可以生成空输出。 |
|
lifc
2009-08-07
tomqyp 写道 再说我们遇到bug不能懒得上报,上报了是不知道什么时候会修补,不上报可能就没机会被修补了,特别是这么严重的bug。 从gdc还活跃的年代(06、07)年代就开始积极提交gdc和dmd的bug,这两个月我们组又报过4、5个。但是每次看到那几条3年前提交bug现躺还在bugzilla里面睡觉,就感觉提不起劲来... |
|
tomqyp
2009-08-07
仔细看了一下,从编译器(WB)的思路来看pop ebx是有用的,之前ebx是初始化为0的,这时idx刚好也等于0,如果idx不等于0肯定也不会生成这样的代码,所以pop ebx不算提前也不能放到后面。
不过这时唯一能用的寄存器edx却没有善加利用,这段代码还是有优化的潜力的。 |
|
lifc
2009-08-07
有点好奇Walter难道没有基本的编译器测试套件吗?像寄存器分配、表达式评估顺序、参数传递这类测试对编译器开发者来说是最基本的助手,我这样的菜鸟当年都下载了一批gcc的套件来测试自己的编译器,是不是成了大牛的人就可以脱俗?前两天看到这里朋友发帖问最希望D做什么,对于这个问题我目前最直接的答案就是稳定,进一步说应该调整之前的开发策略,不要反复在类似问题上吃亏。
|
|
tomqyp
2009-08-07
lifc 写道 感觉dmd和dmc缺少类似gcc必要的中间代码生成能力,致使它难以对操作码进行宏观优化。
对于gcc、lvm这样的高级编译器来说,上述代码完全可以优化成一句assert(true),如果编译器中加入了对assert的built in描述(例如gcc)甚至可以生成空输出。 对,我只希望LDC快发布windows版了 |
|
lifc
2009-08-07
tomqyp 写道 对,我只希望LDC快发布windows版了 windows下的ldc至今缺少seh异常掌握,只能说明群众(特别是高手)对d的信心不足。至于内联汇编,和linux下应该没有什么区别,似乎只是缺少x64的inline汇编。 但愿ldc能成为一股使d腾飞的东风,不过最终结果还要看老大对ldc的态度和重视程度。 |
相关讨论
相关资源推荐
- Borland JBuilder Enterprise 2005
- Windows2000 server下的Apache2.0.47与Tomcat4.1.27的整合配置方法
- Jbuilder2005破解补丁使用方法和下载地址
- import com.borland.jbcl.layout.*; 错误 需要的jbcl.jar包
- 通过JBuilder来制作exe文件来启动Java文件
- JBuilder 6 :Borland方式的Java集成开发环境
- JBuilder集成开发环境介绍
- 常见的十四种Java开发工具的特点
- 全面掌握JBuilder开发技术指南
- Jboss3.0.7在Jbuilder7中的配置