为什么c输出对齐特定的东西

Dar*_*bik 5 c c++ alignment llvm clang

假设我在c中有一个基本程序,并且用clang编译它,如下所示:

#include "stdio.h"
int x = 0x7FFFFFFF;
int main(void)
{

    printf("%d\n",x);
}
Run Code Online (Sandbox Code Playgroud)

将其编译clang -emit-llvm temp.c -fno-rtti -O3 -S产生以下位码:

; ModuleID = 'temp.c'
target datalayout = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128"
target triple = "i686-pc-linux-gnu"

@x = global i32 2147483647, align 4
@.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1

; Function Attrs: nounwind
define i32 @main() #0 {
entry:
  %0 = load i32, i32* @x, align 4, !tbaa !1
  %call = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %0) #1
  ret i32 0
}

; Function Attrs: nounwind
declare i32 @printf(i8* nocapture readonly, ...) #0

attributes #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { nounwind }

!llvm.ident = !{!0}

!0 = !{!"clang version 3.7.1 "}
!1 = !{!2, !2, i64 0}
!2 = !{!"int", !3, i64 0}
!3 = !{!"omnipotent char", !4, i64 0}
!4 = !{!"Simple C/C++ TBAA"}
Run Code Online (Sandbox Code Playgroud)

现在我真正的问题是关于引用变量的行x。如果您注意到,似乎已将x其声明为对齐的变量(对齐为4)。

lang如何知道ints应该对齐?我的主张是,clang没有任何变量对齐的任何线索,因为这取决于您使用的后端。例如,我可以将后端用于8位计算机,则根本不需要对齐。

所以我的问题是:为什么clang认为对齐是不可能的呢?

LPs*_*LPs 1

看看LLVM MAN

\n
\n

模块可以指定目标特定数据布局字符串,该字符串指定数据如何在存储器中布局。数据布局的语法很简单:

\n
target datalayout = "layout specification"\n
Run Code Online (Sandbox Code Playgroud)\n

布局规范由由减号字符 (\xe2\x80\x98-\xe2\x80\x98) 分隔的规范列表组成。每个规范都以字母开头,并且可能在字母后面包含其他信息以定义数据布局的某些方面。接受的规格如下:

\n
\n

[...]

\n
\n

n < 尺寸 1 > : < 尺寸 2 > : < 尺寸 3 >...

\n

这指定了目标 CPU 的一组本机整数宽度(以位为单位)。例如,对于 32 位 PowerPC,它可能包含 n32,对于 PowerPC 64,它可能包含 n32:64,对于 X86-64,它可能包含 n8:16:32:64。该集合的元素被认为可以有效地支持大多数通用算术运算。

\n
\n

强调我的

\n

\n
\n

当 LLVM 确定给定类型的对齐方式时,它使用以下规则:

\n

如果所寻求的类型与其中一项规范完全匹配,则使用该规范。

\n
    \n
  1. 如果未找到匹配项,并且所查找的类型是整数类型,则使用大于所查找类型的位宽的最小整数类型。
  2. \n
  3. 如果没有任何规格大于位宽,则使用最大的整数类型。例如,给定上面的默认规范,i7 类型将使用 i8(下一个最大)的对齐方式,而 i65 和 i256 都将使用 i64(指定的最大)对齐方式。
  4. \n
  5. 如果未找到匹配项,并且所查找的类型是向量类型,则\n小于所查找的向量类型的最大向量类型将被用作后备。发生这种情况是因为 <128 x double> 可以\n用 64 <2 x double> 来实现。
  6. \n
\n
\n

\n
\n

++全局变量**

\n

[...]

\n

可以为全局指定显式对齐,该对齐必须是 2 的幂。如果不存在,或者对齐设置为零,则全局对齐由目标设置为任何它认为方便的值。如果指定了显式对齐方式,则全局将强制具有完全相同的对齐方式。

\n
\n

强调我的

\n