Определить тип массива в IR - PullRequest
3 голосов
/ 13 марта 2012

Я пытался идентифицировать доступ к массиву в IR, используя следующий код:

  for (BasicBlock::iterator ii = BB->begin(), ii2; ii != BB->end(); ii++) {
     Instruction *I=ii;             
    if(GetElementPtrInst *getElePntr = dyn_cast<GetElementPtrInst>(&*I))
    {                   

        Value *valAlloc = (getElePntr->getOperand(0));

        if(getElePntr->getOperand(0)->getType()->isArrayTy())
            {
                errs()<<"\tarray found";
            }
    }  
 }  

Этот код идентифицирует инструкцию getElementPtr, но не определяет, является ли ее первый операнд типом массива или нет. Пожалуйста, дайте мне знать, в чем проблема с моим кодом.

1 Ответ

5 голосов
/ 13 марта 2012

Первый операнд GEP (getelementptr инструкция) является указателем, а не массивом. Этот указатель может указывать на массив или нет (см. Ниже). Поэтому вам нужно посмотреть, на что указывает этот указатель.

Вот образец BasicBlockPass посетитель:

virtual bool runOnBasicBlock(BasicBlock &BB) {
    for (BasicBlock::iterator ii = BB.begin(), ii_e = BB.end(); ii != ii_e; ++ii) {
        if (GetElementPtrInst *gep = dyn_cast<GetElementPtrInst>(&*ii)) {
            // Dump the GEP instruction
            gep->dump();
            Value* firstOperand = gep->getOperand(0);
            Type* type = firstOperand->getType();

            // Figure out whether the first operand points to an array
            if (PointerType *pointerType = dyn_cast<PointerType>(type)) {
                Type* elementType = pointerType->getElementType();
                errs() << "The element type is: " << *elementType << "\n";

                if (elementType->isArrayTy()) {
                    errs() << "  .. points to an array!\n";
                }
            }
        }
    }

    return false;
}

Обратите внимание, однако, что многие "массивы" в C / C ++ на самом деле являются указателями, поэтому вы можете не получить тип массива там, где вы ожидаете.

Например, если вы скомпилируете этот код:

int main(int argc, char **argv) {
  return (int)argv[1][8];
}

Вы получаете ИК:

define i32 @main(i32 %argc, i8** %argv) nounwind uwtable {
  %1 = alloca i32, align 4
  %2 = alloca i32, align 4
  %3 = alloca i8**, align 8
  store i32 0, i32* %1
  store i32 %argc, i32* %2, align 4
  store i8** %argv, i8*** %3, align 8
  %4 = load i8*** %3, align 8
  %5 = getelementptr inbounds i8** %4, i64 1
  %6 = load i8** %5
  %7 = getelementptr inbounds i8* %6, i64 8
  %8 = load i8* %7
  %9 = sext i8 %8 to i32
  ret i32 %9
}

Хотя argv обрабатывается как массив, компилятор считает его указателем, поэтому тип массива в поле зрения отсутствует. Проход, который я вставил выше, не распознает массив здесь, потому что первый операнд GEP - это указатель на указатель .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...