Как выполнить проверку типов с помощью LLVM C ++ API? - PullRequest
0 голосов
/ 02 июля 2019

Я только начал изучать LLVM C ++ API, и меня немного смущает вопрос о том, как выполнять проверку типов. Вот пример, который мой инструктор предоставил мне для хранения переменной в памяти стека следующим образом:

llvm::AllocaInst *Alloca;
Alloca = llvm::Builder.CreateAlloca(llvm::IntegerType::get(getGlobalContext(), 32), nullptr, "variable_name");

Я понимаю это, но в следующей части речь пойдет о проверке типа перед присвоением значения переменной. To assign a value in a Decaf statement of the type lvalue = rvalue you should get the location of lvalue from the symbol table. You can check the type of rvalue using the following API call:

const llvm::PointerType *ptrTy = rvalue->getType()->getPointerTo();
ptrTy == Alloca->getType()

Я совершенно не понимаю, почему это нужно делать для проверки типов. Я прочитал документацию и getPointerTo возвращает объект PointerType. Итак, мой первый вопрос: объект Type объекта Alloca - IntegerType, так почему же мы создаем объект PointerType? Мне кажется, это совершенно за пределами левого поля.

Второй вопрос, который у меня есть, почему мы тогда сравниваем этот объект PointerType с объектом Alloca Type, который является объектом IntegerType? Есть ли какая-то перегрузка оператора ==? Потому что я искал документацию и не смог ее найти.

1 Ответ

2 голосов
/ 02 июля 2019

Вы, похоже, следуете этому учебнику .В вашем вопросе отсутствует какой-то ценный контекст, который я воспроизвожу ниже:

Например, следующий код использует API LLVM для создания инструкции alloca для хранения целых чисел (тип LLVM i32) в стеке.Это пространство хранения используется для хранения значений и для загрузки значений из областей памяти в стеке.

llvm::AllocaInst *Alloca; 
// unlike CreateEntryBlockAlloca the following will 
// create the alloca instr at the current insertion point
// rather than at the start of the block
Alloca = llvm::Builder.CreateAlloca(llvm::IntegerType::get(getGlobalContext(), 32), nullptr, "variable_name");

Затем следует сохранить этот указатель в таблице символов для идентификатора NAME.Вы можете получить доступ к указателю на тип TYPE, используя Alloca->getType(), когда хотите присвоить значение этому местоположению.

Так что Alloca->getType() предоставляет вам объект PointerType, представляющий "указатель на i32, "в частности указатель на место в стеке, которое было выделено для i32.Но rvalue - это i32, а не указатель на i32.Тем не менее, мы все равно можем использовать Alloca->getType() для сравнения типа lvalue (i32) с чем-то, а именно с типом rvalue:

Чтобы присвоить значение вОператор без кофеина типа lvalue = rvalue, вы должны получить местоположение lvalue из таблицы символов.Вы можете проверить тип rvalue, используя следующий вызов API:

const llvm::PointerType *ptrTy = rvalue->getType()->getPointerTo();

Сначала мы получим тип rvalue.Мы не можем сравнивать его напрямую с типом lvalue, потому что у нас есть только тип «указатель на тип lvalue».Поэтому нам нужно преобразовать объект типа, полученный из rvalue, в «указатель на тип rvalue», то есть преобразовать его из i32 в *i32.

InДругими словами, как мы можем проверить, что rvalue имеет тип i32, если все, с чем мы должны сравнивать его, это тип *i32?Ответ таков: мы просто переводим тип rvalue в тип указателя, то есть берем его i32 и делаем его указателем *i32.

В этот момент ptrTy содержит указатель типа "указатель"для типа rvalue ", в то время как мы также знаем, что Alloca->getType() дает нам тип" указатель на тип lvalue. "Чтобы назначить rvalue для lvalue, мы проверяем, что эти два типа совпадают:

И проверяем, что тип расположения Alloca для lvalue имеет тот же тип:

ptrTy == Alloca->getType()

Вышеприведенное выражение является условным;это верно, если типы одинаковы, и ложь в противном случае.Предполагая, что это правда, вы присваиваете значения следующим образом:

llvm::Value *val = Builder.CreateStore(rvalue, Alloca)
...