суббота, 12 августа 2023 г.

gcc plugin to collect cross-references, part 3

Part 1 & 2
Lets start walk climb on TREEs. Main sources for reference are tree.h, tree-core.h & print-tree.cc
 
Caution: bcs we traveling during RTL pass some of tree types already was removed so it is unlikely to meet TYPE_BINFO/BINFO_VIRTUALS etc

Main structure is tree_base, it included as first field in all other types - for example tree_type_non_common has first field with type tree_type_with_lang_specific,
which has field common with type tree_type_common,
which again has field common with type tree_common
which has field typed with type tree_typed,
which has field base with type tree_base 
Kind of ancient inheritance in pure C

Caution 2: many fields has totally different meaning for concrete types, so GCC strictly stimulate to use macros from tree.h to access all fields

Type of TREE can be obtained with CODE_TREE and name of code with function get_tree_code_name
CODE_TREE returns enum tree_code and it has a lot of values - MAX_TREE_CODES eq 0x175. So lets check only important subset

 

XXX_CST

represent some constant
  • STRING_CST - literal constant, length can be obtained with TREE_STRING_LENGTH and content with TREE_STRING_POINTER. Warning - types and declaration names are not literal constants!
  • INTEGER_CST - integer constant, value can be obtained with wi::to_wide call
  • POLY_INT_CST - also integer constant, but split to several elements. Count of such values can be extracted with NUM_POLY_INT_COEFFS and each value via POLY_INT_CST_COEFF 

 

BLOCK

represent some block (usually contains VAR & labels declarations and inlined functions). Variables can be obtained with BLOCK_VARS and BLOCK_NONLOCALIZED_VAR (don`t ask me why there is two kind of vars), embedded blocks with BLOCK_SUBBLOCKS and next block with BLOCK_CHAIN (there should be some joke about cryptocurrencies here)
See sample of traveling on function tree in dump_func_tree

 

XXX_DECL

represent declaration of structure, union, var etc. Often can have name - you should use DECL_NAME which return another tree with code IDENTIFIER_TREE or NULL_TREE. In first case you can get name via IDENTIFIER_POINTER and check if name is really presented via DECL_NAMELESS
 
Variables can have initial values - you can check this with DECL_INITIAL
Type of declaration can be extracted with TREE_TYPE
 
For functions you can access first argument with DECL_ARGUMENTS (and remained with DECL_CHAIN) and result with DECL_RESULT
 
Fields of records can be extracted with TYPE_FIELDS
Offset of field can be extracted with DECL_FIELD_OFFSET
 
One remarkable declaration is

 

LABEL_DECL

has type tree_label_decl and contains rtx for some code label which can be extracted with DECL_RTL_IF_SET

 

XXX_TYPE

represent some type. This is huge topic so I cover only basic things
You can get types name with TYPE_NAME. It again returns another tree with code IDENTIFIER_TREE or NULL_TREE
 
You can quickly check if some type is function/record/union with XXX_TYPE_P macros like RECORD_OR_UNION_TYPE_P, FUNC_OR_METHOD_TYPE_P, POINTER_TYPE_P etc
 
Size of type can be extracted with TYPE_SIZE - it returns tree usually with type INTEGER_CST
 
Enum values can be extracted with TYPE_VALUES
Fields of record/union can be extracted with TYPE_FIELDS
for pointers and references you can extract base type with TREE_TYPE 

Комментариев нет:

Отправить комментарий