GCC与平台关联关系 - 学习笔记

简介: 注 本文以 riscv-tools 为基础进行分析 gcc 与平台之间的关系,及porting基础描述。GCC 平台描述GCC 使用 RTL 和 C 宏的结合来描述平台,后缀为 "md" 的文件(gcc/config/*/.md)定义了 Machine description 。

本文以 riscv-tools 为基础进行分析 gcc 与平台之间的关系,及porting基础描述。

GCC 平台描述

GCC 使用 RTL 和 C 宏的结合来描述平台,后缀为 "md" 的文件(gcc/config/*/.md)定义了 Machine description 。它是 RTL 的子集,描述目标机模型的指令集和用于代码优化的指令属性、指令延迟特性及窥孔优化策略等辅助信息。编译后转换为 C 的结构、数组或函数,作为共用算法的参数。

其他平台特性信息用C的宏定义来表示,也作为共用算法的参数。宏定义的内容有存储器的定义、源语言数据类型的宽度、栈定义、函数调用参数/返回方式、寻址模式、汇编输出的符号定义、GCC命令参数,以及调试信息格式等。

GCC的抽象机是一套标准名(包括宏), 它定义了一套标准指令集,各个不同平台对标准指令名提供语义模板或库函数实现。当语法树节点被分析为某一标准指令名所表示的操作时,代入平台对此标准指令的解释。GCC各平台的目标机模型实现抽象机时所表现的功能特性,即GCC使用参数代入的方法将目标机的具体参数代入抽象机,然后操作抽象机。

编译系统的平台移植时,首先确定新平台将要实现的系统抽象机子集。并书写新平台的描述文件,然后交叉编译生成新平台的编译程序。

GCC 定义抽象机的指令集,它以操作类型来划分指令并建立标准操作表。标准操作表由一组子表组成,每个子表代表一类操作。

GCC 标准指令与平台指令的连接

gcc/gensupport.h 文件中定义了 optab 结构体,并通过 OPTAB_CL 等宏将 optabs.def 文件中定义的操作函数定义到 optab 枚举中,如下所示:

#define OPTAB_CL(name, pat, c, b, l)        name,
#define OPTAB_CX(name, pat)
#define OPTAB_CD(name, pat)         name,
#define OPTAB_NL(name, pat, c, b, s, l)     name,
#define OPTAB_NC(name, pat, c)          name,
#define OPTAB_NX(name, pat)
#define OPTAB_VL(name, pat, c, b, s, l)     name,
#define OPTAB_VC(name, pat, c)          name,
#define OPTAB_VX(name, pat)
#define OPTAB_DC(name, pat, c)          name,
#define OPTAB_D(name, pat)          name,

/* Enumerates all optabs.  */
typedef enum optab_tag {
  unknown_optab,
#include "optabs.def"
  NUM_OPTABS
} optab;

而在 gcc/gensupport.c 文件中将所有 optabs.def 中的函数定义到 optabs 数组内,如下:


#define NS "NULL"
#define ZS "'\\0'"
#define OPTAB_CL(o, p, c, b, l)    { #o, p, #b, ZS, #l, o, c, UNKNOWN, 1 },
#define OPTAB_CX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 1 },
#define OPTAB_CD(o, p) { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 2 },
#define OPTAB_NL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, c, 3 },
#define OPTAB_NC(o, p, c)          { #o, p, NS, ZS, NS, o, c, c, 3 },
#define OPTAB_NX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 },
#define OPTAB_VL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, UNKNOWN, 3 },
#define OPTAB_VC(o, p, c)          { #o, p, NS, ZS, NS, o, c, UNKNOWN, 3 },
#define OPTAB_VX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 },
#define OPTAB_DC(o, p, c)          { #o, p, NS, ZS, NS, o, c, c, 4 },
#define OPTAB_D(o, p)  { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 4 },

/* An array of all optabs.  Note that the same optab can appear more
   than once, with a different pattern.  */
optab_def optabs[] = {
  { "unknown_optab", NULL, NS, ZS, NS, unknown_optab, UNKNOWN, UNKNOWN, 0 },
#include "optabs.def"
};

/* The number of entries in optabs[].  */
unsigned int num_optabs = ARRAY_SIZE (optabs);

/** 省略中间代码 */

/* Describes one entry in optabs.def.  */
struct optab_def
{
  /* The name of the optab (e.g. "add_optab").  */
  const char *name;

  /* The pattern that matching define_expands and define_insns have.
     See the comment at the head of optabs.def for details.  */
  const char *pattern;

  /* The initializers (in the form of C code) for the libcall_basename,
     libcall_suffix and libcall_gen fields of (convert_)optab_libcall_d.  */
  const char *base;
  const char *suffix;
  const char *libcall;

  /* The optab's enum value.  */
  unsigned int op;

  /* The value returned by optab_to_code (OP).  */
  enum rtx_code fcode;

  /* CODE if code_to_optab (CODE) should return OP, otherwise UNKNOWN.  */
  enum rtx_code rcode;

  /* 1: conversion optabs with libcall data,
     2: conversion optabs without libcall data,
     3: non-conversion optabs with libcall data ("normal" and "overflow"
        optabs in the optabs.def comment)
     4: non-conversion optabs without libcall data ("direct" optabs).  */
  unsigned int kind;
};

gcc/optabs.def 文件中定义了 add_optabsub_optab 等基础的标准表操作如下:

OPTAB_NL(add_optab, "add$P$a3", PLUS, "add", '3', gen_int_fp_fixed_libfunc)
OPTAB_NX(add_optab, "add$F$a3")
OPTAB_NX(add_optab, "add$Q$a3")
OPTAB_VL(addv_optab, "addv$I$a3", PLUS, "add", '3', gen_intv_fp_libfunc)
OPTAB_VX(addv_optab, "add$F$a3")
OPTAB_NL(ssadd_optab, "ssadd$Q$a3", SS_PLUS, "ssadd", '3', gen_signed_fixed_libfunc)
OPTAB_NL(usadd_optab, "usadd$Q$a3", US_PLUS, "usadd", '3', gen_unsigned_fixed_libfunc)
OPTAB_NL(sub_optab, "sub$P$a3", MINUS, "sub", '3', gen_int_fp_fixed_libfunc)
OPTAB_NX(sub_optab, "sub$F$a3")
OPTAB_NX(sub_optab, "sub$Q$a3")
OPTAB_VL(subv_optab, "subv$I$a3", MINUS, "sub", '3', gen_intv_fp_libfunc)
OPTAB_VX(subv_optab, "sub$F$a3")
OPTAB_NL(sssub_optab, "sssub$Q$a3", SS_MINUS, "sssub", '3', gen_signed_fixed_libfunc)
OPTAB_NL(ussub_optab, "ussub$Q$a3", US_MINUS, "ussub", '3', gen_unsigned_fixed_libfunc)

对于 add_optab 实际定义为

#define OPTAB_NL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, c, 3 },


OPTAB_NL(add_optab, "add$P$a3", PLUS, "add", '3', gen_int_fp_fixed_libfunc)

# 而 optab_def 定义如下:
# {name,         pattern,     base,  suffix,  libcall,                  op,        fcode,    rcode,   kind}
  {"add_optab",  "add$P$a3",  "add", "3",     gen_int_fp_fixed_libfunc, add_optab, PLUS,     PLUS,    3   }

因此,对于 add_optab 来说,主要实现 add 指令操作,其对应与 gcc/config/riscv/riscv.md 文件中的如下定义:

(define_insn "add<mode>3"
  [(set (match_operand:ANYF            0 "register_operand" "=f")
    (plus:ANYF (match_operand:ANYF 1 "register_operand" " f")
           (match_operand:ANYF 2 "register_operand" " f")))]
  "TARGET_HARD_FLOAT"
  "fadd.<fmt>\t%0,%1,%2"
  [(set_attr "type" "fadd")
   (set_attr "mode" "<UNITMODE>")])

(define_insn "addsi3"
  [(set (match_operand:SI          0 "register_operand" "=r,r")
    (plus:SI (match_operand:SI 1 "register_operand" " r,r")
         (match_operand:SI 2 "arith_operand"    " r,I")))]
  ""
  { return TARGET_64BIT ? "add%i2w\t%0,%1,%2" : "add%i2\t%0,%1,%2"; }
  [(set_attr "type" "arith")
   (set_attr "mode" "SI")])

(define_insn "adddi3"
  [(set (match_operand:DI          0 "register_operand" "=r,r")
    (plus:DI (match_operand:DI 1 "register_operand" " r,r")
         (match_operand:DI 2 "arith_operand"    " r,I")))]
  "TARGET_64BIT"
  "add%i2\t%0,%1,%2"
  [(set_attr "type" "arith")
   (set_attr "mode" "DI")])

目录
相关文章
|
3月前
|
NoSQL 编译器 开发工具
006.gcc编译器
gcc是什么?
44 0
006.gcc编译器
|
4月前
|
存储 NoSQL 算法
从一个crash问题展开,探索gcc编译优化细节
问题分析的过程也正是技术成长之路,本文以一个gcc编译优化引发的crash为切入点,逐步展开对编译器优化细节的探索之路,在分析过程中打开了新世界的大门……
414 1
|
9天前
|
C语言
转载 - gcc/ld 动态连接库和静态连接库使用方法
本文介绍了如何在GCC中实现部分程序静态链接、部分动态链接。使用`-Wl`标志传递链接器参数,`-Bstatic`强制链接静态库,`-Bdynamic`强制链接动态库。
16 0
|
1月前
|
编译器 C语言 C++
列举gcc 常见和有用的编译警告选项
列举gcc 常见和有用的编译警告选项
11 0
|
1月前
|
编译器 C语言
gcc编译警告:warning: suggest parentheses around assignment used as truth value
gcc编译警告:warning: suggest parentheses around assignment used as truth value
18 0
|
1月前
|
编译器 Linux C语言
gcc编译器的使用方法
gcc编译器的使用方法
21 1
|
2月前
|
编译器 C语言
gcc/g++语法
gcc/g++语法
|
4月前
|
C语言
gcc静态编译/usr/bin/ld: cannot find -lc
gcc静态编译/usr/bin/ld: cannot find -lc
|
5月前
|
编译器 程序员 C语言
gcc的编译过程和gcc与g++的区别
gcc的编译过程和gcc与g++的区别
53 0
|
6月前
|
C语言
编译安装gcc
编译安装gcc