2013-09-10 41 views
3

我使用Clang 3.3编译MUSL C库,并转储生成的LLVM IR文件。我发现,该文件结构为什么LLVM IR结构中的函数指针字段被{} *替换?

struct __FILE_s { 
    unsigned flags; 
    unsigned char *rpos, *rend; 
    int (*close)(FILE *); 
    unsigned char *wend, *wpos; 
    unsigned char *mustbezero_1; 
    unsigned char *wbase; 
    size_t (*read)(FILE *, unsigned char *, size_t); 
    size_t (*write)(FILE *, const unsigned char *, size_t); 
    off_t (*seek)(FILE *, off_t, int); 
    unsigned char *buf; 
    size_t buf_size; 
    FILE *prev, *next; 
    int fd; 
    int pipe_pid; 
    long lockcount; 
    short dummy3; 
    signed char mode; 
    signed char lbf; 
    int lock; 
    int waiters; 
    void *cookie; 
    off_t off; 
    char *getln_buf; 
    void *mustbezero_2; 
    unsigned char *shend; 
    off_t shlim, shcnt; 
}; 

被编译为

%struct.__FILE_s = type { i32, i8*, i8*, 
i32 (%struct.__FILE_s*)*, i8*, i8*, i8*, i8*, 
i64 (%struct.__FILE_s*, i8*, i64)*, 
i64 (%struct.__FILE_s*, i8*, i64)*, 
i64 (%struct.__FILE_s*, i64, i32)*, 
i8*, i64, %struct.__FILE_s*, %struct.__FILE_s*, 
i32, i32, i64, i16, i8, i8, i32, i32, i8*, 
i64, i8*, i8*, i8*, i64, i64 } 
在一些IR文件

,但在其他的源文件编译为

%struct.__FILE_s = type { i32, i8*, i8*, 
i32 (%struct.__FILE_s*)*, i8*, i8*, i8*, i8*, 
i64 (%struct.__FILE_s*, i8*, i64)*, 
{}*, 
i64 (%struct.__FILE_s*, i64, i32)*, 
i8*, i64, %struct.__FILE_s*, %struct.__FILE_s*, 
i32, i32, i64, i16, i8, i8, i32, i32, i8*, 
i64, i8*, i8*, i8*, i64, i64 } 

。这两个IR结构之间的唯一区别是第一个表单中的函数指针类型字段被替换为{} *而不是其完整类型。谁能告诉我为什么会发生这种情况,以及如何禁用{} *替换?

回答

0

对于所发生的事情在这里我可以做下面的一个简单的例子:

struct thing; 
int do_work(struct thing *to_this); 

,编译器不知道的事情的类型,但可以在头文件,因为所有它关心的就是使用这个操作数的大小(它是一个指针,所以无论它指向什么都将是指针长度字节)。

同样的事情似乎发生在musl c库中。在一些编译单元中定义了整个类型,而在其他不需要访问特定类型的编译单元中,唯一已知的是它是一个指针。

该修复很容易,而不是正向声明类型包含带有完整类型定义的头文件。不要这样做。这样做会增加编译时间,可能会增加最终可执行文件的膨胀。确切地说,musl是为了避免而写的。如果编译单元不关心完整类型,那么它将不知道完整类型。但是,一切仍然会正常工作。

+0

谢谢你的回应。我认为这个问题更多的是LLVM的具体实现,因为即使包含完整的类型定义,一些结构字段仍然缺失(由*替换)。 – user2744932

+1

我不遵循最后一段。但我也不相信这个答案是有道理的。为什么只有一个函数指针会被影响,而不是所有其他使用'FILE *'的文件都会受到影响? –

+0

你能解释一下你最后一段的意思吗?我不清楚你是否说每个文件*都应该包含完整的定义,或者*不应该*。 –