Le premier opérande d'un GEP (instruction getelementptr
) est un pointeur, pas un tableau. Ce pointeur peut pointer vers un tableau, ou il ne peut pas (voir ci-dessous). Vous devez donc regarder à quoi pointe ce pointeur.
Voici un exemple BasicBlockPass
visiteur:
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;
}
Notez, cependant, que beaucoup de « tableaux » en C/C++ sont des pointeurs en fait, vous pouvez donc pas obtenir le type de tableau où vous vous attendez.
Par exemple, si vous compilez ce code:
int main(int argc, char **argv) {
return (int)argv[1][8];
}
Vous obtenez le IR:
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
}
Bien que argv
est traité comme un tableau, le compilateur pense comme un pointeur , donc il n'y a pas de type de tableau en vue. La passe que j'ai collée ci-dessus ne reconnaîtra pas un tableau ici, car le premier opérande du GEP est un pointeur vers un pointeur.