LLVM新建全域性變數

2022-06-24 22:54:19 字數 4675 閱讀 8955

在llvm中,有原生的ast clone,卻沒有乙個比較好的stmt copy功能,基於scout在llvm上進行的修改,我們實現了自己的stmt clone功能。

要進行stmt clone,肯定需要新建新的ast節點,首先用乙個立即介紹如何進行ast節點的構建,以新建乙個全域性的variable為例。

首先分析下需求,新建variable,自然的有幾個問題:

1.變數如何新建

2.新建的變數應該處於程式的哪個部分

以如下的**為例子:

int

main()

我們有兩個地方可以插入新建的variable,乙個是將其作為全域性變數進行插入,乙個是作為main函式的區域性變數進行插入,這裡選擇作為全域性變數進行插入。那麼插入後,示例**會變成:

int

main()

inta;

(想要有個比較系統的了解的,建議看下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

)

如果想新建乙個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 col:6 a 'int *'

經過查詢,我們發現,假如我們在遍歷ast樹根節點的子節點的時候,新增如下的處理**:

else

if(isa(*d))

vartp = pointtp ->getpointeetype();

}std::cout

<<"

********

"<}

輸出的**如下:

vardecl 0xde9dcf0

2:1, col:6> col:6 a '

int *

'pointertype

0xd732d00

'int *

'`-builtintype 0xd6a8140

'int

'builtintype

0xd6a8140

'int

'<<>>

********

這裡就比較明顯了,這個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的,太多了,不好講,先鴿。

static全域性變數 全域性變數

1 全域性變數 外部變數 的說明之前再冠以static 就構成了靜態的全域性變數。全域性變數本身就是靜態儲存方式,靜態全域性變數當然也是靜態儲存方式。這兩者在儲存方式上並無不同。這兩者的區別在於非靜態全域性變數的作用域是整個源程式,當乙個源程式由多個原始檔組成時,非靜態的全域性變數在各個原始檔中都是...

全域性變數和靜態全域性變數

全域性變數和區域性變數是從變數的作用域的角度劃分。靜態變數和動態變數是從變數的記憶體分配的角度劃分。全域性變數本身就是靜態儲存方式,靜態全域性變數當然也是靜態儲存方式。這兩者在儲存方式上並無不同,區別在於非靜態全域性變數的作用域是整個源程式,當乙個源程式由多個原始檔組成時,非靜態的全域性變數在各個原...

c 全域性變數 靜態全域性變數

全域性變數是靜態儲存方式,靜態全域性變數也是靜態儲存方式,這兩者在儲存方式上並無不同。區別 雖在於非靜態全域性變數的作用域是整個源程式,當乙個源程式由多個原始檔組成時,靜態全域性變數在各個原始檔中都是有效的。靜態區域性變數則限制了其作用域,只在定義該變數的原始檔內有效,在同一源程式的其它原始檔中不能...