2013-09-10 3 views
3

Я скомпилировал библиотеку MUSL C, используя Clang 3.3, и сбрасывал сгенерированные файлы LLVM IR. Я обнаружил, что FILE STRUCTПочему поле указателя функций в структуре 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 } 

в некоторых ИК-файлов, но был составлен по

%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. В некоторых единицах компиляции весь тип определен, а в других, где ему не нужен доступ к определенному типу, единственное, что известно, это то, что оно является указателем.

Исправление легко, а не вперед, объявляя, что тип включает заголовочный файл с определением полного типа. НЕ ДЕЛАЙТЕ ЭТО. Вы увеличиваете время компиляции, делая это и, вероятно, хуже увеличивая раздувание окончательного исполняемого файла. Именно то, что музл написано, чтобы избежать. Если блок компиляции не заботится о полном типе, то он не будет знать о полном типе. Но все будет работать правильно.

+0

Благодарим за отзыв. Я думаю, что проблема более специфична для LLVM, потому что даже включая полное определение типа, некоторые структурные поля по-прежнему отсутствуют (заменены на {} *). – user2744932

+1

Я не следую последнему абзацу. Но я также не убежден, что этот ответ имеет смысл. Почему бы просто повлиять на * one * указателей на функцию, а не на всех других, использующих 'FILE *'? –

+0

Не могли бы вы объяснить, что вы имели в виду в последнем абзаце? Я не понимаю, говоришь ли ты, что каждый файл * должен * включать полное определение или * не должен *. –

2

Это a known bug in Clang.

Я не имею ни малейшего понятия, как обходить его, кроме того, что вы строите Clang самостоятельно и применяете the patch discussed at that bug (но имейте в виду, что патч не был зафиксирован по какой-либо причине).

Смежные вопросы