как правильно передавать структуры данных между пользовательскими проходами llvm - PullRequest
0 голосов
/ 26 августа 2018

У меня есть проход Function, называемый firstPass, который выполняет некоторый анализ и заполняет:

A a;

, где

typedef std::map< std::string, B* > A;
class firstPass : public FunctionPass {  
   A a;
}

typedef std::vector< C* > D;
class B {
   D d;
}

class C {
   // some class packing information about basic blocks;
}

Следовательно, у меня есть карта векторов, пройденных std::string. Я написал связанные деструкторы для этих классов. Этот проход успешно работает самостоятельно.

У меня есть еще один проход Function, называемый secondPass, для которого необходима структура типа A для некоторых преобразований. Я использовал

bool secondPass::doInitialization(Module &M) {
  errs() << "now running secondPass\n";
  a = getAnalysis<firstPass>().getA();
  return false;
}

void secondPass::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.addRequired<firstPass>();
  AU.setPreservesAll();
}

Весь код компилируется нормально, но я получаю ошибку сегментации при печати этой структуры в конце моего первого прохода , только если я вызываю свой второй проход (так как B* равен нулю) .

Чтобы быть ясным:

opt -load ./libCustomLLVMPasses.so -passA < someCode.bc

печатает в doFinalization() и успешно завершает работу

opt -load ./libCustomLLVMPasses.so -passA -passB < someCode.bc

дает ошибку сегментации.

Как мне обернуть эту структуру данных и передать ее на второй проход без проблем? Я попробовал std::unique_ptr вместо сырых, но не смог заставить его работать. Я не уверен, что это правильный подход, так что любая помощь будет оценена.

EDIT: Я решил проблему сег. неисправность. В основном это я вызывал getAnalysis в doInitialization (). Я написал ModulePass для объединения моего firstPass и secondPass, чей runOnModule показан ниже.

bool MPass::runOnModule(Module &M) {
  for(Function& F : M) {
    errs() << "F: " << F.getName() << "\n";
    if(!F.getName().equals("main") && !F.isDeclaration())
      getAnalysis<firstPass>(F);
  }

  StringRef main = StringRef("main");
  A& a = getAnalysis<firstPass>(*(M.getFunction(main))).getA();

  return false;
 }

Это также дало мне возможность контролировать порядок обработки функций. Теперь я могу получить результат прохода, но не могу использовать его как вход для другого прохода. Я думаю, что это показывает, что проходы в llvm автономны.

1 Ответ

0 голосов
/ 30 августа 2018

Я не собираюсь комментировать качество структур данных, основанных на их достоинствах C ++ (это трудно комментировать только этим минимальным примером).

Более того, я бы не стал использоватьdoInitialization метод, если фактическая инициализация настолько проста, но это также побочный комментарий.( doc не упоминает ничего явно об этом, но если он запускается один раз за Module, в то время как метод runOn запускается на каждом Function этого модуля, это может быть проблемой).

Я подозреваю, что основная проблема, похоже, связана с тем фактом, что A a в вашем firstPass связан с временем жизни объекта pass, которое заканчивается после завершения pass.Простейшим изменением будет выделение этого объекта в куче (например, new) и возврат указателя на него при вызове getAnalysis<firstPass>().getA();.

Обратите внимание, что использование этого подхода может потребовать ручной очистки, если вы решитеиспользуйте необработанный указатель.

...