LLVM-выравнивание вложенных структур/массивов

Я хочу получить точное байтовое представление вложенных типов данных структуры/массива. Например, следующая структура C:

typedef struct zTy {
    int x;
    char c[2];
    struct  { char d; } v;
} z;

Он преобразуется в следующий LLVM IR:

%struct.zTy = type { i32, [2 x i8], %struct.anon }
%struct.anon = type { i8 }

%a = alloca %struct.zTy, align 4

Из инструкции alloca можно увидеть выравнивание (4 байта). Но я не знаю, куда вставляется это выравнивание или как рассчитывается выравнивание для вложенных структур. Я получаю общий размер структуры для моей целевой тройки, используя getTypeAllocSize():

AllocaInst* AI;
Module &M;
Type* T = AI->getAllocatedType();
int size = M.getDataLayout()->getTypeAllocSize(T) // 8 Byte

Есть ли способ определить точную компоновку произвольных вложенных типов данных для моей целевой архитектуры из прохода LLVM?


person user2600312    schedule 23.10.2016    source источник


Ответы (1)


Это специфично для ABI, поэтому зависит от цели. Clang будет вычислять его в целом для C/C++ как максимальное выравнивание отдельных членов. Здесь целое число является самым большим полем и имеет ограничение выравнивания по умолчанию, равное 4, что вы и получаете.

В Clang есть опция -fdump-record-layouts as cc1, помогающая определить макет структуры/класса, например здесь:

$ echo "struct zTy {
    int x;
    char c[2];
    struct  { char d; } v;
} z;" | clang -x c  -w - -Xclang -fdump-record-layouts  -c

*** Dumping AST Record Layout
         0 | struct zTy::(anonymous at <stdin>:4:5)
         0 |   char d
           | [sizeof=1, align=1]

*** Dumping AST Record Layout
         0 | struct zTy
         0 |   int x
         4 |   char [2] c
         6 |   struct zTy::(anonymous at <stdin>:4:5) v
         6 |     char d
           | [sizeof=8, align=4]

Внутри LLVM вы теряете типы «C», но если вы хотите проверить структуру, вам нужно использовать:

const StructLayout *getStructLayout(StructType *Ty) const;

И затем, используя возвращенный StructLayout, вы можете получить смещение каждого элемента, используя:

uint64_t StructLayout::getElementOffsetInBits(unsigned Idx) const
person Joky    schedule 26.10.2016
comment
Вы знаете, как я мог получить эту информацию внутри моего пропуска? - person user2600312; 28.10.2016
comment
Обновил ответ с помощью API LLVM. - person Joky; 29.10.2016