如何使用LLVM API找出函数之间的共享变量?

时间:2012-12-12 08:42:42

标签: llvm

最近我使用LLVM API来测试C ++程序。现在我想找出不同函数之间的共享变量,有没有办法做到这一点?似乎AliasAnalysis不起作用!

我写了一个函数通行证如下:

bool EscapeAnalysis::runOnFunction(Function& F) {
    EscapePoints.clear();

    TargetData& TD = getAnalysis<TargetData>();
    AliasAnalysis& AA = getAnalysis<AliasAnalysis>();
    Module* M = F.getParent();
 // errs() << *M << "\n";
 // Walk through all instructions in the function, identifying those that
 // may allow their inputs to escape.
    for(inst_iterator II = inst_begin(F), IE = inst_end(F); II != IE; ++II) {
        Instruction* I = &*II;

     // The most obvious case is stores.  Any store that may write to global
     // memory or to a function argument potentially allows its input to escape.
        if (StoreInst* S = dyn_cast<StoreInst>(I)) {
             Type* StoreType = S->getOperand(0)->getType();
             unsigned StoreSize = TD.getTypeStoreSize(StoreType);
             Value* Pointer = S->getPointerOperand();

             bool inserted = false;
             for (Function::arg_iterator AI = F.arg_begin(), AE = F.arg_end(); 
                  AI != AE; ++AI) {
                 if (!isa<PointerType>(AI->getType())) continue;
                 AliasAnalysis::AliasResult R = AA.alias(Pointer, StoreSize, AI, ~0UL);
                 if (R != AliasAnalysis::NoAlias) {
                     EscapePoints.insert(S);
                     inserted = true;
                     break;
                 }
            }

            if (inserted)
                continue;

            for (Module::global_iterator GI = M->global_begin(), GE = M->global_end();
                 GI != GE; ++GI) {
                errs() << *GI << "\n";
                AliasAnalysis::AliasResult R = AA.alias(Pointer, StoreSize, GI, ~0UL);
                errs() << "R: " << R << " , NoAlias: " << AliasAnalysis::NoAlias << "\n";

                if (R != AliasAnalysis::NoAlias) {
                    EscapePoints.insert(S);
                    break;
                }
            }

      // Calls and invokes potentially allow their parameters to escape.
      // FIXME: This can and should be refined.  Intrinsics have known escape
      // behavior, and alias analysis may be able to tell us more about callees.
        } else if (isa<CallInst>(I) || isa<InvokeInst>(I)) {
            EscapePoints.insert(I);

            // Returns allow the return value to escape.  This is mostly important
            // for malloc to alloca promotion.
        } else if (isa<ReturnInst>(I)) {
            EscapePoints.insert(I);

            // Branching on the value of a pointer may allow the value to escape through
            // methods not discoverable via def-use chaining.
        } else if(isa<BranchInst>(I) || isa<SwitchInst>(I)) {
            EscapePoints.insert(I);
        }

     // FIXME: Are there any other possible escape points?
    }

     return false;
}

测试main.cpp如下:     #include

using namespace std;

int X = 0;

int foo() {
X = 1;
int b = 1;
return 0;
}

int bar(int param) {
int y = X;
int z = 9;
int a = z;

++a;
return 0;
}

int main(int argc, char *argv[])
{
    cout << "Hello world!" << endl;
    return 0;
}

全局变量X是函数栏和函数foo之间的共享变量。 但是,当我使用以下命令运行传递时:

opt -load ./EscapeAnalysis.so -escape-analysis main.o | llc > main.ss

我得到了结果:

R: 1 , NoAlias: 0

所有结果都是一样的。 我在escapePoint中打印出变量,发现函数栏中的变量a,z,y在escapePoint中。这不对!

注意:我写了一个选择传递给测试程序。

1 个答案:

答案 0 :(得分:2)

如果要确定两个不同变量何时指向同一个内存,则需要进行别名分析。如果您只想检查哪些变量与同一模块中的其他函数共享,您可以:

  1. 对所有说明进行迭代,并对每个说明进行迭代:
  2. 迭代所有操作数,并为每个操作数:
  3. 检查它是否为GlobalVariable(例如,通过isa),如果是,请执行以下操作:
  4. 迭代所有全球用途(通过use_beginuse_end),并为每个用途:
  5. 检查是否是Instruction,如果是,请
  6. 检索封闭函数(通过getParent()->getParent()),对于该函数:
  7. 检查它是否是当前处理的功能。如果不是,则表示您找到了当前函数与另一个函数之间共享的变量。
  8. 还有其他检查方法,例如遍历当前模块中的所有全局变量。