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的,太多了,不好講,先鴿。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM