如何告诉clang我的LLVM目标应该使用16位';int';?

如何告诉clang我的LLVM目标应该使用16位';int';?,clang,llvm,pic,llvm-clang,Clang,Llvm,Pic,Llvm Clang,对于我的PIC后端,我希望'int'为16位。我/我的目标如何告诉clang“int”的大小?仅定义16位寄存器似乎不够 当前“铿锵-O2-发射llvm-目标pic”转换为 对于此IR代码,使用32位整数: ; ModuleID = '../test/sum.c' source_filename = "../test/sum.c" target datalayout = "e-m:e-p:16:16-i16:16-a:0:16-n16-S16" target triple = "pic" ;

对于我的PIC后端,我希望'int'为16位。我/我的目标如何告诉clang“int”的大小?仅定义16位寄存器似乎不够

当前“铿锵-O2-发射llvm-目标pic”转换为

对于此IR代码,使用32位整数:

; ModuleID = '../test/sum.c'
source_filename = "../test/sum.c"
target datalayout = "e-m:e-p:16:16-i16:16-a:0:16-n16-S16"
target triple = "pic"

; Function Attrs: norecurse nounwind readnone
define i32 @foo(i32 %a, i32 %b) local_unnamed_addr #0 {
entry:
  %add = add nsw i32 %b, %a
  ret i32 %add
}

attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.ident = !{!0}

!0 = !{!"clang version 4.0.0 (http://llvm.org/git/clang.git 92920e1616528c259756dd8190d4a47058fae127) (http://llvm.org/git/llvm.git 7ca31361200d6bc8a75fa06f112083a8be544287)"}

这可能是也可能不是我在中描述的“返回操作数#1具有未处理的i16类型”消息的原因。但是,在处理其他问题之前,我可能应该先更正clang输出中使用的类型。

我强烈建议养成使用ISO/IEC 9899 include文件
的习惯。在您的情况下,您可以声明

int16_t foo(int16_t a, int16_t b) { return a + b; }
并且可以保证变量和返回值是16位有符号整数,与目标处理器无关。查看文件内容或ISO文档附录B.17(搜索ISO/IEC 9899,您将很容易找到pdf文档),以查看所有类型选项


这些文件(加上变量名上的前缀,如u16foo和i32bar,以向我澄清标识符的大小和签名性)保存了我的皮肤太多次,无法计数。

已解决:clang从它自己的目标(在clang/lib/Basics/Targets.cpp中定义)获取int(和其他类型)的大小。本机大小设置“-n16”不足以覆盖(默认?)i32设置。相反:

IntWidth = 32;
IntAlign = 32;
在我的目标中,构造函数实现了这个技巧


这也解决了奇怪的“未处理的返回类型i16”问题。不知道为什么。

当然,如果程序员打算使用特定的大小,最好明确说明大小。然而,这并不能解决我的问题,原因有两个:a)int的意思是“一个合理的、通常是本机字长的整数”,在我的例子中是16位。b) 当我使用short(int16_t实际上只是一个typedef)时,我会得到16位的参数和返回类型-但是一旦我删除“-O2”,LLVM就会将它们转换到i32,尝试添加并再次转换回它-所有这些都失败了,因为我没有32个算术或寄存器。听起来好像clang认为你的目标是32位。我不使用它,所以我不能评论配置或优化。关于使用stdint typedefs,这是一个偏好/风格的问题。就我个人而言,我从未观察到编译器会覆盖显式大小,无论优化级别如何。我相信我的答案完美地解决了您的问题。您的开场白是“对于我的PIC后端,我希望'int'为16位。”这是'stdint.h'的目的,也是它的表兄弟。
int16\u t
是一个typedef并不重要,重要的是对于给定的编译器和目标,
int16\u t
保证为您提供16位。你证明了我的观点,说你的构建在使用
short
时有效,这是16位目标上的
int16\t
的等效类型。如果你想要一个通解(即“一个合理字数的整数”),我的答案不起作用,但这不是你想要的。这不是重点。根据定义,C在进行算术运算时将大部分内容转换为int。添加两个int16_t将创建一个int值,该值在赋值时转换回int16_t,除非:1。编译器知道uP使用16位字和2。可以证明结果是一样的。因此后端需要知道本地单词的大小,后端的作者必须告诉它。
IntWidth = 32;
IntAlign = 32;