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

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

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

1.变量如何新建

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

以如下的代码为例子:

  1. int main()
  2. {
  3. return ;
  4. }

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

  1. int main()
  2. {
  3. return ;
  4. }
  1. int a;

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

  1. std::string keyName = "a";
  2. int value = ;
  3.  
  4. IdentifierTable& idTable = Context->Idents;
  5. IdentifierInfo& idInfo =idTable.get(keyName);
  6. const SourceLocation nopos;
  7. VarDecl *tmpVar = VarDecl::Create(*Context, Context->getTranslationUnitDecl(), nopos, nopos, &idInfo, Context->IntTy, Context->CreateTypeSourceInfo(Context->IntTy), SC_None);
  8. Context->getTranslationUnitDecl()->addDeclInternal (tmpVar);
  9. IntegerLiteral *init = IntegerLiteral::Create(*Context,llvm::APInt(Context->getIntWidth(Context->IntTy),value,true),
  10. Context->IntTy,nopos);
  11. if (init != )
  12. {
  13. tmpVar->setInit(init);
  14. }

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

  1. // Builtin Types.
  2. CanQualType VoidTy;
  3. CanQualType BoolTy;
  4. CanQualType CharTy;
  5. CanQualType WCharTy; // [C++ 3.9.1p5].
  6. CanQualType WideCharTy; // Same as WCharTy in C++, integer type in C99.
  7. CanQualType WIntTy; // [C99 7.24.1], integer type unchanged by default promotions.
  8. CanQualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99.
  9. CanQualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99.
  10. CanQualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty;
  11. CanQualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy;
  12. CanQualType UnsignedLongLongTy, UnsignedInt128Ty;
  13. CanQualType FloatTy, DoubleTy, LongDoubleTy, Float128Ty;
  14. CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON
  15. CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
  16. CanQualType Float128ComplexTy;
  17. CanQualType VoidPtrTy, NullPtrTy;
  18. CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy;
  19. CanQualType BuiltinFnTy;
  20. CanQualType PseudoObjectTy, ARCUnbridgedCastTy;
  21. CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy;
  22. CanQualType ObjCBuiltinBoolTy;
  23. #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
  24. CanQualType SingletonId;
  25. #include "clang/Basic/OpenCLImageTypes.def"
  26. CanQualType OCLSamplerTy, OCLEventTy, OCLClkEventTy;
  27. CanQualType OCLQueueTy, OCLNDRangeTy, OCLReserveIDTy;
  28. CanQualType OMPArraySectionTy;
  29.  
  30. // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand.
  31. mutable QualType AutoDeductTy; // Deduction against 'auto'.
  32. mutable QualType AutoRRefDeductTy; // Deduction against 'auto &&'.
  33.  
  34. // Decl used to help define __builtin_va_list for some targets.
  35. // The decl is built when constructing 'BuiltinVaListDecl'.
  36. 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树根节点的子节点的时候,添加如下的处理代码:

  1. else if(isa<VarDecl>(*D))
  2. {
  3. VarDecl *var = dyn_cast<VarDecl>(*D);
  4. var->dump();
  5. QualType varTp = var->getType();
  6.  
  7. while (true) {
  8. varTp.dump();
  9. const PointerType *pointTp = varTp->getAs<PointerType>();
  10. if(pointTp==NULL)
  11. {
  12. const Type* ET = varTp->getArrayElementTypeNoTypeQual();
  13. ET->dump();
  14. break;
  15. }
  16. varTp = pointTp ->getPointeeType();
  17.  
  18. }
  19. std::cout <<"********"<<std::endl;
  20. }

输出的代码如下:

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

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

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

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

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

LLVM新建全局变量的更多相关文章

  1. Android+Sqlite 实现古诗阅读应用(三)

    往期传送门: Android+Sqlite 实现古诗阅读应用(一) Android+Sqlite 实现古诗阅读应用(二) 加入截图分享的功能. 很多应用都有分享的功能,我也想在我的古诗App里加入这个 ...

  2. Axure一点

    自己的感受:非常的考脑,上课要集中120分精神. Axure(快速制作网页原型) 1:全局变量:a:在菜单栏中可以新建全局变量. b:控制全部网页. c:取到输入框的值,设置User的值等于输入框的值 ...

  3. nxlog4go 简介 - 基于log4go的下一代go语言日志系统

    nxlog4go的项目网址: https://github.com/ccpaging/nxlog4go 项目历史 ccpaging's log4go forked from https://githu ...

  4. Android NDK开发三:java和C\C++交互

    转自:http://www.cnblogs.com/shangdahao/archive/2013/05/02/3053971.html 1.定义native方法并加载动态链接库: public cl ...

  5. robotframework·RIDE基础

    date:2018520 day09 一.学习环境 1.安装python27 2.安装robotframework(cmd→[pip install robotframework]) 3.安装WxPy ...

  6. 10 - 函数嵌套-作用域-闭包-LEGB-函数销毁

    目录 1 函数嵌套 2 作用域 2.1 global关键字 3 闭包 3.1 nonlocal关键字 4 默认值的作用域 5 变量名解析原则LEGB 6 函数的销毁 1 函数嵌套         一个 ...

  7. vue多套样式切换

    最近根据设计要求app需要根据不同环境切换不同样式,网上找了很多方法都不理想,后面自己脑洞大开这么完成的,请大佬多指教! 一.新建全局变量js文件和公用样式文件,在main.js中引入 import  ...

  8. ifix 在切换菜单按钮弹出”已打开该画面“bug修复

    在ifix项目中,实际上会用到点击按钮弹出按钮菜单,点击另一按钮弹出另一按钮菜单的情况.一般在使用过程中切换菜单可有如下两种普遍做法: 1.使用ClosePicture "Middle&qu ...

  9. Atitit s2018.2 s2 doc list on home ntpc.docx  \Atiitt uke制度体系 法律 法规 规章 条例 国王诏书.docx \Atiitt 手写文字识别 讯飞科大 语音云.docx \Atitit 代码托管与虚拟主机.docx \Atitit 企业文化 每日心灵 鸡汤 值班 发布.docx \Atitit 几大研发体系对比 Stage-Gat

    Atitit s2018.2 s2 doc list on home ntpc.docx \Atiitt uke制度体系  法律 法规 规章 条例 国王诏书.docx \Atiitt 手写文字识别   ...

随机推荐

  1. C++ STL swap_range

    #include <iostream>#include <vector>#include <deque>#include <algorithm> usi ...

  2. Tomcat下配置javaWeb访问路径-Linux

    首先找到你的Tomcat的server.xml文件 笔者直接编辑 sudo vi /app/prod/conf/server.xml 访问只需要您的IP地址就可以访问项目了 第二个配置则是访问 ip+ ...

  3. 用SSMS连接Azure Sql Database 与连接本地库的一些操作区别

    背景 我们知道Azure Sql Database 可以降低运维成本.是一种Pass模式,有资源弹性设置,可以自由调整资源自动对应不同业务高峰(当然也可以降低费用成本),也方便项目后期的资源扩展,以及 ...

  4. [Python]Excel编程示例教程(openpyxl)

    1 前言(Preface) 博文背景:论文实验中有一大堆数据集需要观测其数据特征,通过人体肉眼,难以直观感受,故而准备通过生成Excel,可视化其评测数据. We know: Excel便于可视化分析 ...

  5. 陷门函数Trapdoor Function

    陷门函数:正向计算是很容易的,但若要有效的执行反向计算则必须要知道一些secret/knowledge/trapdoor(知识?),也称为伪随机置换,可用于构造公钥密码系统. 若 f 为陷门函数,则 ...

  6. Linux生成ssh密钥免密登录,允许/禁止密码登录,允许/禁止root远程登录,更改ssh端口

    进入想要使用密钥登录的用户家目录 cd 或 cd ~ 执行密钥创建命令,不行可能需要下载openssh-server与openssh-client ssh-keygen -t rsa -P " ...

  7. 【miscellaneous】语音识别工具箱综述和产品介绍

    原文:http://www.thinkface.cn/thread-893-1-1.html 今天是周末,想来想去,还是写一篇这样的博文吧.算是对语音识别这一段时间的总结,为后来的人融入铺好前面的路. ...

  8. 如何下载spring sts

    1.打开https://spring.io/ 2.翻到页面最底部点击tools 3.页面下滑点击Download STS4 Windows 64-bit

  9. 用户ID与权限

    目录 用户ID与权限 文件系统查看 权限ID概览 设置位 黏着位 UMASK chmod与chown 代码附录 chmod title: 用户ID与权限 date: 2019/11/25 21:20: ...

  10. 31.网络协议介绍tcp/udp

    网络协议 TCP:网络中传输数据的协议,打电话 解决了我可能在网络中找不到别人(数据无法传输到) 保证数据传输的稳定性,可靠性 保证数据的安全性,完整性 对方要有响应 尝试重新发送 UDP:传输数据的 ...