这与 How to force const propagation through an inline function? 有关Clang 有一个集成的汇编程序;而且它不使用系统的汇编程序(通常是 GNU AS (GAS))。非 Clang 早期执行了数学运算,一切都“正常工作”。
我说“早”是因为@n.m。反对将其描述为“预处理器执行的数学运算”。但是这个想法是这个值在编译时是已知的,应该尽早评估它,就像预处理器评估 #if (X % 32 == 0) 时一样。 .
下面,Clang 3.6 提示违反了约束。似乎常量没有在整个过程中传播:
$ export CXX=/usr/local/bin/clang++
$ $CXX --version
clang version 3.6.0 (tags/RELEASE_360/final)
Target: x86_64-apple-darwin12.6.0
...
$ make
/usr/local/bin/clang++ -DNDEBUG -g2 -O3 -Wall -fPIC -arch i386 -arch x86_64 -pipe -Wno-tautological-compare -c integer.cpp
In file included from integer.cpp:8:
In file included from ./integer.h:7:
In file included from ./secblock.h:7:
./misc.h:941:44: error: constraint 'I' expects an integer constant expression
__asm__ ("rolb %1, %0" : "+mq" (x) : "I" ((unsigned char)(y%8)));
^~~~~~~~~~~~~~~~~~~~
./misc.h:951:44: error: constraint 'I' expects an integer constant expression
...
上面的函数是内联模板特化:
template<> inline byte rotrFixed<byte>(byte x, unsigned int y)
{
// The I constraint ensures we use the immediate-8 variant of the
// shift amount y. However, y must be in [0, 31] inclusive. We
// rely on the preprocessor to propoagte the constant and perform
// the modular reduction so the assembler generates the instruction.
__asm__ ("rorb %1, %0" : "+mq" (x) : "I" ((unsigned char)(y%8)));
return x;
}
它们是用常量值调用的,因此循环量在编译时是已知的。典型的来电者可能看起来像:
unsigned int x1 = rotrFixed<byte>(1, 4);
unsigned int x2 = rotrFixed<byte>(1, 32);
如果GCC,则不需要这些[有问题的]技巧或 Clang提供了一个内在函数来执行 rotate in near constant time .我什至满足于“执行轮换”,因为他们甚至没有。
让 Clang 恢复执行 const 值的预处理需要什么技巧?
精明的读者会认出 rotrFixed<byte>(1, 32)如果使用传统的 C/C++ 循环,则可能是未定义的行为。所以我们开始使用汇编来避免 C/C++ 的限制并享受 1 条指令的加速。
好奇的读者可能想知道我们为什么要这样做。密码学家提出规范,有时这些规范与底层硬件或标准机构并不一致。我们没有更改密码学家的规范,而是尝试逐字提供它以简化审核。
针对此问题打开了一个错误:LLVM Bug 24226 - Constant not propagated into inline assembly, results in "constraint 'I' expects an integer constant expression" .
我不知道 Clang 做了什么保证,但我知道编译器和集成汇编器声称与 GCC 和 GNU 的汇编器兼容。而GCC和GAS提供了常数值的传播。
最佳答案
由于设计决策而强制进行持续评估似乎并不走运,ror r/m8, cl 形式可能是一个很好的折衷方案:
__asm__ ("rorb %b1, %b0" : "+q,m" (x) : "c,c" (y) : "cc");
由于 clang 问题,多个替代约束语法是为了“促进”寄存器使用而不是内存使用,涵盖 here .不知道以后的版本有没有解决这个问题。 gcc 往往更擅长约束匹配和避免溢出。
这确实需要将 (y) 加载到 rcx/ecx/cl 寄存器中,但编译器可能会将其隐藏在另一个延迟之后。此外,(y) 不存在范围问题。 rorb 有效地使用了 (%cl % 8)。 "cc" clobber 不是必需的。
如果表达式是常量,gcc 和clang 都可以使用__builtin_constant_p :
if (__builtin_constant_p(y))
__asm__("rorb %1, %b0" : "+q,m" (x) : "N,N" ((unsigned char) y) : "cc");
else
... non-constant (y) ...
或如邮件列表中所述:
if (__builtin_constant_p(y))
{
if ((y &= 0x7) != 0)
x = (x >> y) | (x << (8 - y)); /* gcc generates rotate. */
}
关于c++ - 在常数值上强制 Clang 为 "perform math early",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31577608/
我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test
我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que
我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file
当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub
我在新的Debian6VirtualBoxVM上安装RVM时遇到问题。我已经安装了所有需要的包并使用下载了安装脚本(curl-shttps://rvm.beginrescueend.com/install/rvm)>rvm,但以单个用户身份运行时bashrvm我收到以下错误消息:ERROR:Unabletocheckoutbranch.安装在这里停止,并且(据我所知)没有安装RVM的任何文件。如果我以root身份运行脚本(对于多用户安装),我会收到另一条消息:Successfullycheckedoutbranch''安装程序继续并指示成功,但未添加.rvm目录,甚至在修改我的.bas