gcc编译器分析

news2024/11/23 7:29:44

gcc编译器分析

    • 参考
    • 词法分析
    • 语法分析
      • 预读一个符号
      • 语法分析函数调用关系
      • 重点函数分析
        • c_parse_file
        • c_parser_translation_unit

参考

《gcc源码分析》

词法分析

词法分析的过程就是将源代码识别成一个一个的词法符号,并在词法分析的过程中创建一些树节点,用来保存某些词法符号的值(value)。这些需要创建树节点的词法符号主要包括标识符(CPP_NAME)、关键字(CPP_KEYWORD)、数值(CPP_NUMBER)常量等。在后续的语法分析过程中,会将这些AST节点(或者AST子树)根据语法规则链接起来,形成某个函数完整的AST结构。

语法分析

语法分析就是,提前预读两个词法符号的自顶向下的语法推导过程:包括提前预读词法符号,语法分析状态以及上下文信息。

这些信息通常将保存在c_parser 这个结构体当中:

/* A parser structure recording information about the state and
   context of parsing.  Includes lexer information with up to two
   tokens of look-ahead; more are not needed for C.  */
typedef struct c_parser GTY(())
{
  /* The look-ahead tokens.  */
  c_token tokens[2];
  /* How many look-ahead tokens are available (0, 1 or 2).  */
  short tokens_avail;
  /* True if a syntax error is being recovered from; false otherwise.
     c_parser_error sets this flag.  It should clear this flag when
     enough tokens have been consumed to recover from the error.  */
  BOOL_BITFIELD error : 1;
  /* True if we're processing a pragma, and shouldn't automatically
     consume CPP_PRAGMA_EOL.  */
  BOOL_BITFIELD in_pragma : 1;
  /* True if we're parsing the outermost block of an if statement.  */
  BOOL_BITFIELD in_if_block : 1;
  /* True if we want to lex an untranslated string.  */
  BOOL_BITFIELD lex_untranslated_string : 1;
  /* Objective-C specific parser/lexer information.  */
  BOOL_BITFIELD objc_pq_context : 1;
  /* The following flag is needed to contextualize Objective-C lexical
     analysis.  In some cases (e.g., 'int NSObject;'), it is
     undesirable to bind an identifier to an Objective-C class, even
     if a class with that name exists.  */
  BOOL_BITFIELD objc_need_raw_identifier : 1;
} c_parser;

gcc对c语言进行语法分析的入口函数为c_parse_file :


/* Parse a single source file.  */

void
c_parse_file (void)
{
  /* Use local storage to begin.  If the first token is a pragma, parse it.
     If it is #pragma GCC pch_preprocess, then this will load a PCH file
     which will cause garbage collection.  */
  c_parser tparser;

  memset (&tparser, 0, sizeof tparser);
  the_parser = &tparser;

  if (c_parser_peek_token (&tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
    c_parser_pragma_pch_preprocess (&tparser);

  the_parser = GGC_NEW (c_parser);
  *the_parser = tparser;

  c_parser_translation_unit (the_parser);
  the_parser = NULL;
}

预读一个符号

预读一个符号,如果是PRAGMA_GCC_PCH_PREPROCESS,将进行编译的预处理工作,c_parser_pragma_pch_preprocess 为预处理函数。
c_parser_peek_token 会解析出一个token,这时会返回指向下个token的指针:

/* Return a pointer to the next token from PARSER, reading it in if
   necessary.  */

static inline c_token *
c_parser_peek_token (c_parser *parser)
{
  if (parser->tokens_avail == 0)
    {
      c_lex_one_token (parser, &parser->tokens[0]);
      parser->tokens_avail = 1;
    }
  return &parser->tokens[0];
}

解析一个单独的词法符号时,调用c_lex_one_token

/* Read in and lex a single token, storing it in *TOKEN.  */

static void
c_lex_one_token (c_parser *parser, c_token *token)
{
  timevar_push (TV_LEX);

  token->type = c_lex_with_flags (&token->value, &token->location, NULL,
				  (parser->lex_untranslated_string
				   ? C_LEX_STRING_NO_TRANSLATE : 0));
  token->id_kind = C_ID_NONE;
  token->keyword = RID_MAX;
  token->pragma_kind = PRAGMA_NONE;

  switch (token->type)
    {
    case CPP_NAME:
      {
	tree decl;

	bool objc_force_identifier = parser->objc_need_raw_identifier;
	if (c_dialect_objc ())
	  parser->objc_need_raw_identifier = false;

	if (C_IS_RESERVED_WORD (token->value))
	  {
	    enum rid rid_code = C_RID_CODE (token->value);

	    if (rid_code == RID_CXX_COMPAT_WARN)
	      {
		warning_at (token->location,
			    OPT_Wc___compat,
			    "identifier %qs conflicts with C++ keyword",
			    IDENTIFIER_POINTER (token->value));
	      }
	    else if (c_dialect_objc ())
	      {
		if (!objc_is_reserved_word (token->value)
		    && (!OBJC_IS_PQ_KEYWORD (rid_code)
			|| parser->objc_pq_context))
		  {
		    /* Return the canonical spelling for this keyword.  */
		    token->value = ridpointers[(int) rid_code];
		    token->type = CPP_KEYWORD;
		    token->keyword = rid_code;
		    break;
		  }
	      }
	    else
	      {
		token->type = CPP_KEYWORD;
		token->keyword = rid_code;
		break;
	      }
	  }

	decl = lookup_name (token->value);
	if (decl)
	  {
	    if (TREE_CODE (decl) == TYPE_DECL)
	      {
		token->id_kind = C_ID_TYPENAME;
		break;
	      }
	  }
	else if (c_dialect_objc ())
	  {
	    tree objc_interface_decl = objc_is_class_name (token->value);
	    /* Objective-C class names are in the same namespace as
	       variables and typedefs, and hence are shadowed by local
	       declarations.  */
	    if (objc_interface_decl
		&& (global_bindings_p ()
		    || (!objc_force_identifier && !decl)))
	      {
		token->value = objc_interface_decl;
		token->id_kind = C_ID_CLASSNAME;
		break;
	      }
	  }
        token->id_kind = C_ID_ID;
      }
      break;
    case CPP_AT_NAME:
      /* This only happens in Objective-C; it must be a keyword.  */
      token->type = CPP_KEYWORD;
      token->keyword = C_RID_CODE (token->value);
      break;
    case CPP_COLON:
    case CPP_COMMA:
    case CPP_CLOSE_PAREN:
    case CPP_SEMICOLON:
      /* These tokens may affect the interpretation of any identifiers
	 following, if doing Objective-C.  */
      if (c_dialect_objc ())
	parser->objc_need_raw_identifier = false;
      break;
    case CPP_PRAGMA:
      /* We smuggled the cpp_token->u.pragma value in an INTEGER_CST.  */
      token->pragma_kind = (enum pragma_kind) TREE_INT_CST_LOW (token->value);
      token->value = NULL;
      break;
    default:
      break;
    }
  timevar_pop (TV_LEX);
}

语法分析函数调用关系

在这里插入图片描述

重点函数分析

c_parse_file

函数c_parse_filer如上所述,是C语法分析的入口函数,该函数首先对当前的词法符号进行判断,如果该符号的编译制导类型是PRAGMA_GCC_PCH_PREPROCESS,则调用函数c_parser_pragma_pch_preprocess对进行源代码的预处理,否则,调用函数c_parser_translation_unit()进行语法推导。

c_parser_translation_unit

这个函数是进行语法分析的主流程函数:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1644475.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

YashanDB与帆软信创商业智能软件完成兼容互认证

近日,深圳计算科学研究院崖山数据库系统YashanDB与帆软信创商业智能软件(V6.0)顺利完成兼容性互认证,经严格测试,双方产品能够相互兼容,稳定运行。 崖山数据库系统YashanDB是深圳计算科学研究院自主研发设计…

一分钱不花从HTTP升级到HTTPS

HTTP升级到HTTPS是一个涉及安全性和技术实施的过程,主要目的是为了提升网站数据传输的安全性,防止数据被窃取或篡改。以下是一些关于从HTTP升级到HTTPS的技术性要点和步骤概述,结合上述信息资源: 一、理解HTTPS的重要性 HTTPS (…

[图解]SysML和EA建模住宅安全系统-01

1 00:00:00,980 --> 00:00:03,100 接下来,我们来看一下案例 2 00:00:04,930 --> 00:00:06,750 我们这次课程的案例 3 00:00:07,090 --> 00:00:13,800 选用了SysML实用指南的书上 4 00:00:13,810 --> 00:00:16,180 第十七章这个案例 5 00:00:16,350 …

《QT实用小工具·五十六》自适应界面变化的控件

1、概述 源码放在文章末尾 该项目实现了网格显示多张带文字的图片在界面中自适应布局 特点 跟随窗口大小变换位置,并带移动动画 响应鼠标事件,图片缩放动画 点击水波纹动画 项目demo演示如下所示: 项目部分代码如下所示: #i…

​可视化大屏C位图:3D模型,可视化大屏的画龙点睛之处

Hello,我是大千UI工场,本期可视化大屏的焦点图(C位)分享将图表作为焦点图的情形,欢迎友友们关注、评论,如果有订单可私信。 3D模型在可视化大屏中有很大的价值,以下是一些相关的优点&#xff1a…

优优嗨聚集团:法律明灯,个债处理中的法律咨询力量

在现代社会,个人债务问题日益突出,无论是因生活消费、投资失利还是其他原因,债务问题都可能成为个人财务的一大负担。面对复杂的债务困境,许多人感到迷茫和无助。此时,法律咨询如同一盏明灯,能够为个人债务…

GEE数据集——全球冰川海拔变化产品(2000-2019 年)

全球冰川海拔变化产品(2000-2019 年) 该数据集提供了 2000 年至 2019 年期间冰川海拔和质量变化的全面且全球一致的记录。它利用大量卫星图像(主要来自美国国家航空航天局(NASA)的高级星载热发射和反射辐射计&#xf…

ABAP开发(1)事物代码

文章目录 1、查看系统部分功能的T-code2、T-code使用3、查看未知程序的T-code4、常用T-code 在SAPGUI中,事务代码(transaction code),简称T-code,是一个特定的编号,支持自定义,使用户能够快速访…

【AI+音视频总结】如何在几分钟内用智能工具摘取音视频精华?揭秘下一代学习和内容创作神器!

今天无意发现一个网站,可以一步到位完成AI音视频总结。 我之前对于音视频总结的步骤还是借助 工具下载 剪映来完成的。详情可以参考之前写的一篇文章 【AI应用】模仿爆款视频二次创作短视频操作步骤 。 这里介绍的网站是 BibiGPT 。 BibiGPT AI 音视频助理 - 它是…

项目管理-项目沟通管理

项目管理:每天进步一点点~ 活到老,学到老 ヾ(◍∇◍)ノ゙ 何时学习都不晚,加油 1.项目沟通管理-主要内容 项目沟通管理过程--重点: ①ITTO 输入,输出工具和技术。 ②问题和解决方案。 ③论文…

公共代理IP和独享代理IP之间的区别?

公共代理IP和独享代理IP在网络应用中扮演着不同的角色,它们之间的区别主要体现在使用方式、性能、安全性以及隐私保护等方面。以下是对这两种代理IP的详细对比和分析。 第一点就是使用的方式以及成本上的不同,公共代理IP,顾名思义&#xff0…

同向双指针(滑动窗口)算法

209. 长度最小的子数组 这里的更新结果就题来定 class Solution {public int minSubArrayLen(int target, int[] nums) {int sum 0;int len 0;int f 0;for(int left 0, right 0; right < nums.length;){//求和sum nums[right];while(sum > target){//lenint t ri…

浪漫编码:手把手教你实现校园表白墙功能

&#x1f493; 博客主页&#xff1a;从零开始的-CodeNinja之路 ⏩ 收录文章&#xff1a;浪漫编码&#xff1a;手把手教你实现校园表白墙功能 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 这里写目录标题 表白墙数据准备引入MyBatis和MySQL驱动依赖…

部分设计模式概述

单例模式 工厂模式 适配器模式 模板方法模式 策略模式 责任链 观察者模式&#xff08;又叫发布订阅模式&#xff09;

MySql#MySql数据库基础

目录 一、什么是数据库 二、主流数据库 三、基本使用 1.连接服务器 2.使用 1.查看你数据库 2.创建数据库 ​编辑 ​编辑 ​编辑​编辑 3.使用数据库 ​编辑 4.创建数据库表 5.表中插入数据 6.服务器&#xff0c;数据库&#xff0c;表之间的关系 四、MySQL架构…

【Docker】docker compose服务编排

docker compose 简介 Dockerfile模板文件可以定义一个单独的应用容器&#xff0c;如果需要定义多个容器就需要服务编排。 docker swarm&#xff08;管理跨节点&#xff09; Dockerfile可以让用户管理一个单独的应用容器&#xff1b;而Compose则允许用户在一个模板&#xff08…

关于信息泄露的危害,听听圈内人怎么说......

信息泄露危害之短信轰炸 信息泄露这个事大家要引起重视&#xff0c;会给日常生活带来很多安全风险&#xff0c;例如说&#xff0c;经常收到的垃圾短信、骚扰电话、钓鱼邮件等&#xff0c;一轮接一轮的“轰炸”&#xff0c;让你不堪其扰。 我之前收到的垃圾短信大部分是商铺的广…

You don’t have permission.

The document “XXX” could not be saved. You don’t have permission. 1.查看修改了iOS系统库导致的, 根据提示, 进入到"XXX"文件中, 然后commandz回退/取消 2. Xcode 调试遇到的报错&#xff08;持续更新&#xff09;

Python量化炒股的数据信息获取—获取上市公司分红送股数据信息

Python量化炒股的数据信息获取—获取上市公司分红送股数据信息 上市公司分红送股数据&#xff0c;都存放在STK_XR_XD表中&#xff0c;该表保存在finance包中。要查看表中的数据信息&#xff0c;需要使用query()函数。 单击聚宽JoinQuant量化炒股平台中的“策略研究/研究环境”…

华为OD机试 - 符号运算 - 递归(Java 2024 C卷 100分)

华为OD机试 2024C卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测试…