gcc 源码分析-前端篇1

前年写了 gcc源码分析,感觉写的不好,如果没有源代码读起来很痛苦,基本上是读天书,这一次改了一种写法,用另一种思路来写,希望这一次能好一点:

1.基本数据结构

编译器前端主要的任务就是把输入的源码转换成一棵语法树,

在gcc中,树的每一个节点用一个结构体来表示,下面就来谈一谈gcc中用到的这个结构体:

union tree_node

{

struct tree_common common;

struct tree_identifier identifier;

struct tree_list list;

struct tree_exp exp;

struct tree_type type;

struct tree_decl decl;

struct tree_int_cst int_cst;

struct tree_string string;

struct tree_bind_stmt bind_stmt;

struct tree_stmt stmt;

};

这个结构体由两部分组成,一个通用部分struct tree_common,另一个就是同节点相关的部分;

比如如果这个节点记录的是一个ID,那相关部分就用struct tree_identifier,

如果记录的是一个整形数值就用struct tree_int_cst来表示。

所以这个结构体就用一个联合体来表示,所谓联合体就是它的所有成员的起始地址都一样,为了让两个

结构体不相互干扰,就让具体类型的结构体第一个成员变量所占据的空间恰恰就是通用部分的大小;比如struct tree_identifier结构体,它的定义如下:

struct tree_identifier

{

char common[sizeof (struct tree_common)];

int length;

char *pointer;

};

你看它前面部分的common成员变量,它占据的空间是sizeof (struct tree_common),恰恰就是通用结构的大小

后面就是这个表示ID有关系的部分了,对于ID来说,我们关心它的长度,就用一个length来记录,然后就是

ID的名称,这里就用char *来表示。

对任意一个ID来说,它通常还有一个类型,比如它是interger,char ,short 或者表示的是一个function,

这个类型记在tree_common中,下面看看tree_common结构:

struct tree_common

{

int uid;

union tree_node *chain;

union tree_node *type;

enum tree_code code : 8;

unsigned permanent_attr : 1;

unsigned external_attr : 1;

unsigned public_attr : 1;

unsigned inline_attr : 1;

unsigned static_attr : 1;

unsigned regdecl_attr : 1;

unsigned this_vol_attr : 1;

unsigned volatile_attr : 1;

unsigned packed_attr : 1;

unsigned readonly_attr : 1;

unsigned addressable_attr:1;

unsigned used_attr:1;

unsigned unsigned_attr:1;

unsigned literal_attr:1;

unsigned asm_written_attr: 1;

};

重要成员变量分析:

uid        : 就是不重复的一个标识ID,用来与其他节点区分开来;

chain    : 用于许多目的,比如记录输出到调试器的东西;

type       :对于表达式,它是一个数据类型;POINTER_TYPE节点就是一个指针,ARRAY_TYPE节点就使

元素的数据类型;

code     :表示这个节点的种类,所有的种类记录在tree.def中

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-10 23:15:49

gcc 源码分析-前端篇1的相关文章

gcc 源码分析-前端篇2

2. 对ID及保留字的处理 在c语言中,系统预留了很多关键字,也被称为保留字,比如表示数据类型的int,short,char,控制分支执行的if,then等. 任何关键字,本质上也是一个ID,比如它也有长度,对int就是3,对short就是5,也有内容,比如int,short.但比起一般id, 它还有其他一些属性,比如表示数据类型的int,它有一个数值范围,它的值范围是-xxx到xxx之间. 由于这样的关系,gcc把ID和关键字都保存在一张表中,这张表定义如下: #define MAX_HASH

gcc 源码分析-前端篇3

3. GCC如何函表示一个函数 对c语言来说,函数是其核心,所有的东西都在围绕着函数在转.对于一个函数来说,它主要的一些特性如下: 1. 有一个返回值,在这里我们没有把返回值的函数认为它的返回值是void; 2. 它有传入的参数,而这个参数个数不确定,可多可少,也可以没有: 3. 它有一个函数名称,这个名称具有唯一性,也就是同一个工程,不能有名称一样的多个函数: 4. 它有函数执行体: 对于函数来说,还是通过struct tree_decl结构来表示: filename:函数所在文件名: lin

Android事件传递机制详解及最新源码分析——ViewGroup篇

在上一篇<Android事件传递机制详解及最新源码分析--View篇>中,详细讲解了View事件的传递机制,没掌握或者掌握不扎实的小伙伴,强烈建议先阅读上一篇. 好了,废话还是少说,直奔主题,开始本篇的ViewGroup事件传递机制探索之旅. 依然从简单的Demo例子现象开始分析 新建安卓工程,首先自定义一个Button以及一个RelativeLayout,很简单,只是重写了主要与事件传递机制相关的方法,代码如下: 自定义WLButton类: 1 public class WLButton e

JUC源码分析-集合篇(三)ConcurrentLinkedQueue

JUC源码分析-集合篇(三)ConcurrentLinkedQueue 在并发编程中,有时候需要使用线程安全的队列.如果要实现一个线程安全的队列有两种方式:一种是使用阻塞算法,另一种是使用非阻塞算法.使用阻塞算法的队列可以用一个锁(入队和出队用同一把锁)或两个锁(入队和出队用不同的锁)等方式来实现.非阻塞的实现方 式则可以使用循环 CAS 的方式来实现.本节让我们一起来研究一下 Doug Lea 是如何使用非阻塞的方式来实现线程安全队列 ConcurrentLinkedQueue 的,相信从大师

JUC源码分析-集合篇(五)BlockingQueue 阻塞式队列实现原理

JUC源码分析-集合篇(五)BlockingQueue 阻塞式队列实现原理 以 LinkedBlockingQueue 分析 BlockingQueue 阻塞式队列的实现原理. 1. 数据结构 LinkedBlockingQueue 和 ConcurrentLinkedQueue 一样都是由 head 节点和 last 节点组成,每个节点(Node)由节点元素(item)和指向下一个节点(next)的引用组成,节点与节点之间就是通过这个 next 关联起来,从而组成一张链表结构的队列.默认情况下

JUC源码分析-集合篇(七)PriorityBlockingQueue

JUC源码分析-集合篇(七)PriorityBlockingQueue PriorityBlockingQueue 是带优先级的无界阻塞队列,每次出队都返回优先级最高的元素,是二叉树最小堆的实现. PriorityBlockingQueue 数据结构和 PriorityQueue 一致,而线程安全性使用的是 ReentrantLock. 1. 基本属性 // 最大可分配队列容量 Integer.MAX_VALUE - 8,减 8 是因为有的 VM 实现在数组头有些内容 private stati

Spring 事务源码分析——Hibernate篇

在Spring与Hibernate整合的时候,可以利用Spring的事务管理机制,为我们管理事务的开启.提交.回滚等操作.这样的方式极大的减少了我们的代码量,让我们只专注于业务代码的编写.在使用Hibernate的时候,每一个操作都要经历事务开启与提交这样的操作,他们在业务代码的周围,这样来看是不是就想到了AOP编程,把这部分代码抽取出来.没错,Spring正是这样做的,Spring的事务管理就是基于AOP的. 1 Spring的事务隔离与传播 Srping的事务定义了五个隔离等级(isolat

zepto源码分析------事件篇

说说zepto.js的源码.今天先分析事件,我比较懒,前面的基础函数就不分析了.直接按模块写就可以了. 在分析之前先简单的说一下zepto的大致结构 var Zepto = (function{})() // 事件模块 (function($){})(zepto) //ajax模块 (function($){})(zepto) // form事件 (function($){})(zepto) 大致结构就是这样了;其实里面的函数也挺简单的,我们都知道zepto这个框架是专为移动端开发,可谓是短小精

zepto源码分析------ajax篇

上级研究了zepto的事件,也说了一下zepto的主要模块构成.恩,今天来说说的zepto的ajax是如何实现. 好的,和上次一样,先上代码再说. $.ajax = function(options) { // 覆盖配置 var settings = $.extend({}, options || {}), // 没有找到在哪里 deferred = $.Deferred && $.Deferred(), urlAnchor // 完成完整对配置覆盖 for (key in $.ajaxS