zoukankan      html  css  js  c++  java
  • LLVM新建全局变量

    在LLVM中,有原生的AST Clone,却没有一个比较好的Stmt copy功能,基于Scout在LLVM上进行的修改,我们实现了自己的Stmt Clone功能。

    要进行Stmt Clone,肯定需要新建新的AST节点,首先用一个立即介绍如何进行AST节点的构建,以新建一个全局的variable为例。

    首先分析下需求,新建variable,自然的有几个问题:

    1.变量如何新建

    2.新建的变量应该处于程序的哪个部分

    以如下的代码为例子:

    int main()
    {
      return 0;
    }

    我们有两个地方可以插入新建的variable,一个是将其作为全局变量进行插入,一个是作为main函数的局部变量进行插入,这里选择作为全局变量进行插入。那么插入后,示例代码会变成:

    int main()
    {
      return 0;
    }
    int a;

    (想要有个比较系统的了解的,建议看下tools/clang/lib/StaticAnalyzer,StaticAnalyzer是一个良好的例子)

    std::string keyName = "a";
    int value = 0;
    
    IdentifierTable& idTable = Context->Idents;
    IdentifierInfo&  idInfo =idTable.get(keyName);
    const SourceLocation nopos;
        VarDecl *tmpVar = VarDecl::Create(*Context, Context->getTranslationUnitDecl(), nopos, nopos, &idInfo, Context->IntTy, Context->CreateTypeSourceInfo(Context->IntTy), SC_None);
    Context->getTranslationUnitDecl()->addDeclInternal (tmpVar);
    IntegerLiteral *init = IntegerLiteral::Create(*Context,llvm::APInt(Context->getIntWidth(Context->IntTy),value,true),
            Context->IntTy,nopos);
     if (init != 0)
     {
        tmpVar->setInit(init);
     }

    如果想新建一个int *a;这种的,稍微比较麻烦,因为需要自己新建类型。在context中只提供了基础类型的:

      // Builtin Types.
      CanQualType VoidTy;
      CanQualType BoolTy;
      CanQualType CharTy;
      CanQualType WCharTy;  // [C++ 3.9.1p5].
      CanQualType WideCharTy; // Same as WCharTy in C++, integer type in C99.
      CanQualType WIntTy;   // [C99 7.24.1], integer type unchanged by default promotions.
      CanQualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99.
      CanQualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99.
      CanQualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty;
      CanQualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy;
      CanQualType UnsignedLongLongTy, UnsignedInt128Ty;
      CanQualType FloatTy, DoubleTy, LongDoubleTy, Float128Ty;
      CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON
      CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
      CanQualType Float128ComplexTy;
      CanQualType VoidPtrTy, NullPtrTy;
      CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy;
      CanQualType BuiltinFnTy;
      CanQualType PseudoObjectTy, ARCUnbridgedCastTy;
      CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy;
      CanQualType ObjCBuiltinBoolTy;
    #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) 
      CanQualType SingletonId;
    #include "clang/Basic/OpenCLImageTypes.def"
      CanQualType OCLSamplerTy, OCLEventTy, OCLClkEventTy;
      CanQualType OCLQueueTy, OCLNDRangeTy, OCLReserveIDTy;
      CanQualType OMPArraySectionTy;
    
      // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand.
      mutable QualType AutoDeductTy;     // Deduction against 'auto'.
      mutable QualType AutoRRefDeductTy; // Deduction against 'auto &&'.
    
      // Decl used to help define __builtin_va_list for some targets.
      // The decl is built when constructing 'BuiltinVaListDecl'.
      mutable Decl *VaListTagDecl;

    新建int *a;第一步自然是在源码中手动插入这样的代码,使用clang -fsyntax-only -Xclang -ast-dump test.cpp来查看这个新建的AST节点是如何表达的,再寻找对应的新建方式。

    VarDecl 0xccec418 <test.cpp:2:1, col:6> col:6 a 'int *'

    经过查找,我们发现,假如我们在遍历AST树根节点的子节点的时候,添加如下的处理代码:

    else if(isa<VarDecl>(*D))
        {
            VarDecl *var = dyn_cast<VarDecl>(*D);
            var->dump();
            QualType varTp = var->getType();
            
            while (true) {
                varTp.dump();
                const PointerType *pointTp = varTp->getAs<PointerType>();
                if(pointTp==NULL)
                {
                    const Type* ET = varTp->getArrayElementTypeNoTypeQual();
                    ET->dump();
                    break;
                }
                varTp = pointTp ->getPointeeType();
                
            }
            std::cout <<"********"<<std::endl;
        }

    输出的代码如下:

    VarDecl 0xde9dcf0 <test.cpp:2:1, col:6> col:6 a 'int *'
    PointerType 0xd732d00 'int *'
    `-BuiltinType 0xd6a8140 'int' 
    BuiltinType 0xd6a8140 'int' 
    <<<NULL>>>
    ********

    这里就比较明显了,这个VarDecl的QUALType是 PointerType,而PointerType对应的Pointee是int。

    这样模仿上边的代码,如果新建一个int **aaaa;的节点,可以使用:

    std::string keyName = "aaaa";
    IdentifierTable& idTable = Context->Idents;
    IdentifierInfo&  idInfo =idTable.get(keyName);
    const SourceLocation nopos;
    QualType PointerTy_1 = Context->getPointerType(Context->getIntTypeForBitwidth(32, 1));
    QualType PointerTy_2 = Context->getPointerType(PointerTy_1);
    VarDecl *tmpVar = VarDecl::Create(*Context, Context->getTranslationUnitDecl(), nopos, nopos, &idInfo, PointerTy_2, Context->CreateTypeSourceInfo(PointerTy_2), SC_None);
    Context->getTranslationUnitDecl()->addDecl (tmpVar);

    本来想写Stmt Clone的,太多了,不好讲,先鸽。

  • 相关阅读:
    Python--面向对象编程(2)
    Python--面向对象编程(1)
    Python--常用模块
    Python--函数
    Hadoop综合大作业
    hive基本操作与应用
    MapReduce作业
    熟悉HBase基本操作
    熟悉常用的HDFS操作
    爬虫大作业(对电影的爬取)
  • 原文地址:https://www.cnblogs.com/jourluohua/p/10813824.html
Copyright © 2011-2022 走看看