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

本文以 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")])

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容