Передача массива во внешнюю функцию

Я новичок в LLVM и учусь использовать LLVM для профилирования. Мне нужно передать массив внешнему методу и вставить в код инструкцию вызова метода. В настоящее время я использую следующий код, который при выполнении дает ошибку сегментации.

std::vector<Value*> Args(1);

//Vector with array values
SmallVector<Constant*, 2> counts;

counts.push_back(ConstantInt::get(Type::getInt32Ty(BB->getContext()),32, false));
                        counts.push_back(ConstantInt::get(Type::getInt32Ty(BB->getContext()),12, false));

//Array with 2 integers
Args[0]= ConstantArray::get(llvm::ArrayType::get(llvm::Type::getInt32Ty(BI->getContext()),2), counts);

Здесь внешняя функция «крюк» определяется как M.getOrInsertFunction("hook", Type::getVoidTy(M.getContext()), llvm::ArrayType::get(llvm::Type::getInt32Ty(BI->getContext()),2) (Type*)0);

Прочитав несколько исходных файлов, я попытался использовать GetElementPtrInst для передачи массива

std::vector<Value*> ids(1);
ids.push_back(ConstantInt::get(Type::getInt32Ty(BB->getContext()),0));
Constant* array = ConstantArray::get(llvm::ArrayType::get(llvm::Type::getInt32Ty(BI->getContext()),2), counts);
Args[0] = ConstantExpr::getGetElementPtr(&(*array), ids, false);

но это не с

7  opt 0x00000000006c59f5 bool llvm::isa<llvm::Constant, llvm::Value*>(llvm::Value* const&) + 24

8  opt 0x00000000006c5a0f llvm::cast_retty<llvm::Constant, llvm::Value*>::ret_type llvm::cast<llvm::Constant, llvm::Value*>(llvm::Value* const&) + 24

9  opt 0x0000000000b2b22f

10 opt 0x0000000000b2a4fe llvm::ConstantFoldGetElementPtr(llvm::Constant*, bool, llvm::ArrayRef<llvm::Value*>) + 55

11 opt 0x0000000000b33df2 llvm::ConstantExpr::getGetElementPtr(llvm::Constant*, llvm::ArrayRef<llvm::Value*>, bool) + 82

Кроме того, в этом случае «крючок» определяется как M.getOrInsertFunction("hook", Type::getVoidTy(M.getContext()), PointerType::get(Type::getInt32PtrTy(M.getContext()),0), //when using GEP (Type*)0);

Может ли кто-нибудь оставить мне несколько указателей на передачу массивов во внешнюю функцию (скажем, с подписью void hook(int abc[]) ). Я, вероятно, ошибаюсь на всем пути, и был бы очень признателен за помощь.


person SArora    schedule 29.01.2013    source источник


Ответы (2)


Хорошее место для начала с вопросов «как мне сделать это в стиле c в LLVM IR» — сначала написать, что вы хотите сделать в C, а затем скомпилируйте его в LLVM IR через Clang и посмотрите на результат.

В вашем конкретном случае файл:

void f(int a[2]);

void g() {
    int x[2];
    x[0] = 1;
    x[1] = 3;
    f(x);
}

Будет компилироваться в:

define void @g() nounwind {
  %x = alloca [2 x i32], align 4
  %1 = getelementptr inbounds [2 x i32]* %x, i32 0, i32 0
  store i32 1, i32* %1, align 4
  %2 = getelementptr inbounds [2 x i32]* %x, i32 0, i32 1
  store i32 3, i32* %2, align 4
  %3 = getelementptr inbounds [2 x i32]* %x, i32 0, i32 0
  call void @f(i32* %3)
  ret void
}

declare void @f(i32*)

Итак, мы видим, что clang скомпилировал g для получения i32*, а не массива. Это означает, что вам нужен способ получить адрес первого элемента массива из самого массива и getelementptr — простой способ сделать это.

Однако обратите внимание, что вы хотите сгенерировать GEP (инструкцию getelementptr), например, через GetElementPtrInst::create. постоянное выражение, которое вы пытаетесь сгенерировать здесь, это что-то другое, и будет работать только с константами времени компиляции.

person Oak    schedule 29.01.2013

Вы должны использовать Clang для его компиляции. Затем проверьте границы массива и все ли элементы определены.

person Community    schedule 29.01.2013