TCC(TinyC)编译器汉化(中文编译器、汉语编程)之八:汇编处理

汇编处理源码如下:

/*
 *  GAS之类的ZHI汇编程序
 */

#定义 全局_使用
#导入 "zhi.h"
#如果已定义 配置_ZHI_汇编

静态 段 *最后_代码_段; /* 处理.previous asm指令 */

静态_函数 整数型 汇编_获取_局部_标签_名称(知心状态机 *状态机1, 无符号 整数型 n)
{
    字符型 buf[64];
    单词存储结构 *ts;

    snprintf(buf, 取大小(buf), "L..%u", n);
    ts = 单词表_查找(buf, strlen(buf));
    返回 ts->单词编码;
}

静态 整数型 zhi_汇编_内部(知心状态机 *状态机1, 整数型 do_preprocess, 整数型 global);
静态 符号* 汇编_新_标签(知心状态机 *状态机1, 整数型 label, 整数型 is_local);
静态 符号* 汇编_新_标签1(知心状态机 *状态机1, 整数型 label, 整数型 is_local, 整数型 sh_num, 整数型 value);

/* 如果C名称以_开头,则通过删除第一个_来仅在C中表示以_开头的asm标签。 开头没有_的ASM名称与C名称不对应,但是我们也使用全局C单词表来跟踪ASM名称,因此我们需要将其转换为与C名称不冲突的名称,因此在前面添加 一个 '。' 为他们,但强制设置ELF汇编名称。  */
静态 整数型 汇编2c名称(整数型 v, 整数型 *addeddot)
{
    常量 字符型 *name;
    *addeddot = 0;
    如果 (!zhi_状态->前导_下划线)
      返回 v;
    name = 取_单词字符串(v, NULL);
    如果 (!name)
      返回 v;
    如果 (name[0] == '_') {
        v = 单词表_查找(name + 1, strlen(name) - 1)->单词编码;
    } 否则 如果 (!strchr(name, '.')) {
        整数型 n = strlen(name) + 2;
        字符型 newname[n];
        snprintf(newname, n, ".%s", name);
        v = 单词表_查找(newname, n - 1)->单词编码;
        *addeddot = 1;
    }
    返回 v;
}

静态 符号 *汇编_标签_查找(整数型 v)
{
    符号 *sym;
    整数型 addeddot;
    v = 汇编2c名称(v, &addeddot);
    sym = 符号_查询(v);
    判断 (sym && sym->符号_范围 && !(sym->type.t & VT_静态))
        sym = sym->prev_tok;
    返回 sym;
}

静态 符号 *汇编_标签_推送(整数型 v)
{
    整数型 addeddot, v2 = 汇编2c名称(v, &addeddot);
    /* 我们总是为临时的符号定义(对于.set,对于实际的defs删除)添加VT_EXTERN,对于仅引用而言,它是正确的。  */
    符号 *sym = 推送_一个_全局标识符(v2, VT_汇编 | VT_外部 | VT_静态, 0);
    如果 (addeddot)
        sym->汇编_label = v;
    返回 sym;
}

/* 返回一个可以在汇编器内部使用的符号,名称为NAME。 来自asm和C源代码的符号共享一个名称空间。 如果我们生成一个asm符号,
 * 它也是一个(文件全局)C符号,但是它不能按名称访问(例如“ L.123”),或者其类型信息使得没有适当的C声明就无法使用。
 * 有时我们需要从asm可以通过名称访问的符号,这些符号在C中是匿名的,在这种情况下,可以使用CSYM将所有信息从该符号传输到
 * (可能是新创建的)asm符号。  */
静态_函数 符号* 获取_汇编_符号(整数型 name, 符号 *csym)
{
    符号 *sym = 汇编_标签_查找(name);
    如果 (!sym) {
	sym = 汇编_标签_推送(name);
	如果 (csym)
	  sym->c = csym->c;
    }
    返回 sym;
}

静态 符号* 汇编_段_符号(知心状态机 *状态机1,*sec)
{
    字符型 buf[100];
    整数型 label = 单词表_查找(buf,
        snprintf(buf, 取大小 buf, "L.%s", sec->name)
        )->单词编码;
    符号 *sym = 汇编_标签_查找(label);
    返回 sym ? sym : 汇编_新_标签1(状态机1, label, 1, sec->sh_num, 0);
}

/* 我们不使用C表达式解析器来处理符号。 也许可以对C表达式解析器进行调整。 */

静态 无类型 汇编_表达式_一元(知心状态机 *状态机1, 表达式值 *pe)
{
    符号 *sym;
    整数型 op, label;
    uint64_t n;
    常量 字符型 *p;

    选择(单词编码) {
    分支 常量_预处理编号:
        p = 单词值.str.data;
        n = strtoull(p, (字符型 **)&p, 0);
        如果 (*p == 'b' || *p == 'f') {
            /* 后退或前进标签 */
            label = 汇编_获取_局部_标签_名称(状态机1, n);
            sym = 汇编_标签_查找(label);
            如果 (*p == 'b') {
                /* backward : find the last corresponding 已定义 label */
                如果 (sym && (!sym->c || elf符号(sym)->st_shndx == SHN_UNDEF))
                    sym = sym->prev_tok;
                如果 (!sym)
                    错误_打印("找不到本地标签 '%d' ", (整数型)n);
            } 否则 {
                /* forward */
                如果 (!sym || (sym->c && elf符号(sym)->st_shndx != SHN_UNDEF)) {
                    /* 如果 the last label is 已定义, then 定义 a new one */
		    sym = 汇编_标签_推送(label);
                }
            }
	    pe->v = 0;
	    pe->sym = sym;
	    pe->pcrel = 0;
        } 否则 如果 (*p == '\0') {
            pe->v = n;
            pe->sym = NULL;
	    pe->pcrel = 0;
        } 否则 {
            错误_打印("无效的数字语法");
        }
        带有宏替换的下个标记();
        跳出;
    分支 '+':
        带有宏替换的下个标记();
        汇编_表达式_一元(状态机1, pe);
        跳出;
    分支 '-':
    分支 '~':
        op = 单词编码;
        带有宏替换的下个标记();
        汇编_表达式_一元(状态机1, pe);
        如果 (pe->sym)
            错误_打印("invalid operation with label");
        如果 (op == '-')
            pe->v = -pe->v;
        否则
            pe->v = ~pe->v;
        跳出;
    分支 常量_字符型:
    分支 常量_长字符型:
	pe->v = 单词值.i;
	pe->sym = NULL;
	pe->pcrel = 0;
	带有宏替换的下个标记();
	跳出;
    分支 '(':
        带有宏替换的下个标记();
        汇编_表达式(状态机1, pe);
        跳过(')');
        跳出;
    分支 '.':
        pe->v = 输出代码索引;
        pe->sym = 汇编_段_符号(状态机1, 当前_生成代码_段);
        pe->pcrel = 0;
        带有宏替换的下个标记();
        跳出;
    default:
        如果 (单词编码 >= 符_识别) {
	    ELF符号 *esym;
            /* label 分支 : 如果 the label was not found, add one */
	    sym = 获取_汇编_符号(单词编码, NULL);
	    esym = elf符号(sym);
            如果 (esym && esym->st_shndx == SHN_ABS) {
                /* 如果 absolute symbol, no need to put a symbol value */
                pe->v = esym->st_value;
                pe->sym = NULL;
		pe->pcrel = 0;
            } 否则 {
                pe->v = 0;
                pe->sym = sym;
		pe->pcrel = 0;
            }
            带有宏替换的下个标记();
        } 否则 {
            错误_打印("错误的表达语法 [%s]", 取_单词字符串(单词编码, &单词值));
        }
        跳出;
    }
}
    
静态 无类型 汇编_表达式_乘除余(知心状态机 *状态机1, 表达式值 *pe)
{
    整数型 op;
    表达式值 e2;

    汇编_表达式_一元(状态机1, pe);
    循环(;;) {
        op = 单词编码;
        如果 (op != '*' && op != '/' && op != '%' && 
            op != 双符号_左位移 && op != 双符号_右位移)
            跳出;
        带有宏替换的下个标记();
        汇编_表达式_一元(状态机1, &e2);
        如果 (pe->sym || e2.sym)
            错误_打印("无效的操作标签");
        选择(op) {
        分支 '*':
            pe->v *= e2.v;
            跳出;
        分支 '/':  
            如果 (e2.v == 0) {
            div_error:
                错误_打印("被零除");
            }
            pe->v /= e2.v;
            跳出;
        分支 '%':  
            如果 (e2.v == 0)
                去向 div_error;
            pe->v %= e2.v;
            跳出;
        分支 双符号_左位移:
            pe->v <<= e2.v;
            跳出;
        default:
        分支 双符号_右位移:
            pe->v >>= e2.v;
            跳出;
        }
    }
}

静态 无类型 汇编_表达式_逻辑(知心状态机 *状态机1, 表达式值 *pe)
{
    整数型 op;
    表达式值 e2;

    汇编_表达式_乘除余(状态机1, pe);
    循环(;;) {
        op = 单词编码;
        如果 (op != '&' && op != '|' && op != '^')
            跳出;
        带有宏替换的下个标记();
        汇编_表达式_乘除余(状态机1, &e2);
        如果 (pe->sym || e2.sym)
            错误_打印("invalid operation with label");
        选择(op) {
        分支 '&':
            pe->v &= e2.v;
            跳出;
        分支 '|':  
            pe->v |= e2.v;
            跳出;
        default:
        分支 '^':
            pe->v ^= e2.v;
            跳出;
        }
    }
}

静态 内联 无类型 汇编_表达式_和(知心状态机 *状态机1, 表达式值 *pe)
{
    整数型 op;
    表达式值 e2;

    汇编_表达式_逻辑(状态机1, pe);
    循环(;;) {
        op = 单词编码;
        如果 (op != '+' && op != '-')
            跳出;
        带有宏替换的下个标记();
        汇编_表达式_逻辑(状态机1, &e2);
        如果 (op == '+') {
            如果 (pe->sym != NULL && e2.sym != NULL)
                去向 cannot_relocate;
            pe->v += e2.v;
            如果 (pe->sym == NULL && e2.sym != NULL)
                pe->sym = e2.sym;
        } 否则 {
            pe->v -= e2.v;
            /* 注意:在这种情况下,我们不如气体强大,因为我们在表达式中仅存储一个符号 */
	    如果 (!e2.sym) {
		/* OK */
	    } 否则 如果 (pe->sym == e2.sym) { 
		/* OK */
		pe->sym = NULL; /* 相同的符号可以减为NULL */
	    } 否则 {
		ELF符号 *esym1, *esym2;
		esym1 = elf符号(pe->sym);
		esym2 = elf符号(e2.sym);
		如果 (esym1 && esym1->st_shndx == esym2->st_shndx
		    && esym1->st_shndx != SHN_UNDEF) {
		    /* we also accept 已定义 symbols in the same section */
		    pe->v += esym1->st_value - esym2->st_value;
		    pe->sym = NULL;
		} 否则 如果 (esym2->st_shndx == 当前_生成代码_段->sh_num) {
		    /* When subtracting a 已定义 symbol in current section
		       this actually makes the value PC-relative.  */
		    pe->v -= esym2->st_value - 输出代码索引 - 4;
		    pe->pcrel = 1;
		    e2.sym = NULL;
		} 否则 {
cannot_relocate:
		    错误_打印("无效的操作标签");
		}
	    }
        }
    }
}

静态 内联 无类型 汇编_表达式_比较(知心状态机 *状态机1, 表达式值 *pe)
{
    整数型 op;
    表达式值 e2;

    汇编_表达式_和(状态机1, pe);
    循环(;;) {
        op = 单词编码;
	如果 (op != 双符号_等于 && op != 双符号_不等于
	    && (op > 符_GT || op < 符号_ULE))
            跳出;
        带有宏替换的下个标记();
        汇编_表达式_和(状态机1, &e2);
        如果 (pe->sym || e2.sym)
            错误_打印("无效的操作标签");
        选择(op) {
	分支 双符号_等于:
	    pe->v = pe->v == e2.v;
	    跳出;
	分支 双符号_不等于:
	    pe->v = pe->v != e2.v;
	    跳出;
	分支 符_LT:
	    pe->v = (int64_t)pe->v < (int64_t)e2.v;
	    跳出;
	分支 双符号_大于等于:
	    pe->v = (int64_t)pe->v >= (int64_t)e2.v;
	    跳出;
	分支 双符号_小于等于:
	    pe->v = (int64_t)pe->v <= (int64_t)e2.v;
	    跳出;
	分支 符_GT:
	    pe->v = (int64_t)pe->v > (int64_t)e2.v;
	    跳出;
        default:
            跳出;
        }
	/* GAS compare results are -1/0 not 1/0.  */
	pe->v = -(int64_t)pe->v;
    }
}

静态_函数 无类型 汇编_表达式(知心状态机 *状态机1, 表达式值 *pe)
{
    汇编_表达式_比较(状态机1, pe);
}

静态_函数 整数型 汇编_整数_表达式(知心状态机 *状态机1)
{
    表达式值 e;
    汇编_表达式(状态机1, &e);
    如果 (e.sym)
        应为("constant");
    返回 e.v;
}

静态 符号* 汇编_新_标签1(知心状态机 *状态机1, 整数型 label, 整数型 is_local,
                           整数型 sh_num, 整数型 value)
{
    符号 *sym;
    ELF符号 *esym;

    sym = 汇编_标签_查找(label);
    如果 (sym) {
	esym = elf符号(sym);
	/* A VT_外部 symbol, even 如果 it has a section is considered
	   overridable.  This is how we "定义" .set targets.  Real
	   definitions won't have VT_外部 set.  */
        如果 (esym && esym->st_shndx != SHN_UNDEF) {
            /* the label is already 已定义 */
            如果 (是_汇编_符号(sym)
                && (is_local == 1 || (sym->type.t & VT_外部)))
                去向 new_label;
            如果 (!(sym->type.t & VT_外部))
                错误_打印("assembler label '%s' already 已定义",
                          取_单词字符串(label, NULL));
        }
    } 否则 {
    new_label:
        sym = 汇编_标签_推送(label);
    }
    如果 (!sym->c)
      更新_外部_符号2(sym, SHN_UNDEF, 0, 0, 1);
    esym = elf符号(sym);
    esym->st_shndx = sh_num;
    esym->st_value = value;
    如果 (is_local != 2)
        sym->type.t &= ~VT_外部;
    返回 sym;
}

静态 符号* 汇编_新_标签(知心状态机 *状态机1, 整数型 label, 整数型 is_local)
{
    返回 汇编_新_标签1(状态机1, label, is_local, 当前_生成代码_段->sh_num, 输出代码索引);
}

/* 将LABEL的值设置为某些表达式的值(可能涉及其他符号)。 LABEL以后仍可以覆盖。  */
静态 符号* 设置_符号(知心状态机 *状态机1, 整数型 label)
{
    long n;
    表达式值 e;
    符号 *sym;
    ELF符号 *esym;
    带有宏替换的下个标记();
    汇编_表达式(状态机1, &e);
    n = e.v;
    esym = elf符号(e.sym);
    如果 (esym)
	n += esym->st_value;
    sym = 汇编_新_标签1(状态机1, label, 2, esym ? esym->st_shndx : SHN_ABS, n);
    elf符号(sym)->st_other |= ST_ASM_SET;
    返回 sym;
}

静态 无类型 使用_段1(知心状态机 *状态机1,*sec)
{
    当前_生成代码_段->数据_偏移 = 输出代码索引;
    当前_生成代码_段 = sec;
    输出代码索引 = 当前_生成代码_段->数据_偏移;
}

静态 无类型 使用_段(知心状态机 *状态机1, 常量 字符型 *name)
{*sec;
    sec = 查找_段(状态机1, name);
    使用_段1(状态机1, sec);
}

静态 无类型 推送_段(知心状态机 *状态机1, 常量 字符型 *name)
{*sec = 查找_段(状态机1, name);
    sec->prev = 当前_生成代码_段;
    使用_段1(状态机1, sec);
}

静态 无类型 弹出_段(知心状态机 *状态机1)
{*prev = 当前_生成代码_段->prev;
    如果 (!prev)
        错误_打印(".popsection without .pushsection");
    当前_生成代码_段->prev = NULL;
    使用_段1(状态机1, prev);
}

静态 无类型 汇编_解析_指令(知心状态机 *状态机1, 整数型 global)
{
    整数型 n, offset, v, size, tok1;*sec;
    uint8_t *ptr;

    /* 汇编指令 */
    sec = 当前_生成代码_段;
    选择(单词编码) {
    分支 符_汇编DIR_align:
    分支 符_汇编DIR_balign:
    分支 符_汇编DIR_p2align:
    分支 符_汇编DIR_skip:
    分支 符_汇编DIR_space:
        tok1 = 单词编码;
        带有宏替换的下个标记();
        n = 汇编_整数_表达式(状态机1);
        如果 (tok1 == 符_汇编DIR_p2align)
        {
            如果 (n < 0 || n > 30)
                错误_打印("invalid p2align, must be between 0 and 30");
            n = 1 << n;
            tok1 = 符_汇编DIR_align;
        }
        如果 (tok1 == 符_汇编DIR_align || tok1 == 符_汇编DIR_balign) {
            如果 (n < 0 || (n & (n-1)) != 0)
                错误_打印("alignment must be a positive power of two");
            offset = (输出代码索引 + n - 1) & -n;
            size = offset - 输出代码索引;
            /* 该部分必须具有兼容的对齐方式 */
            如果 (sec->sh_addralign < n)
                sec->sh_addralign = n;
        } 否则 {
	    如果 (n < 0)
	        n = 0;
            size = n;
        }
        v = 0;
        如果 (单词编码 == ',') {
            带有宏替换的下个标记();
            v = 汇编_整数_表达式(状态机1);
        }
    zero_pad:
        如果 (sec->sh_type != SHT_NOBITS) {
            sec->数据_偏移 = 输出代码索引;
            ptr = 段_ptr_添加(sec, size);
            memset(ptr, v, size);
        }
        输出代码索引 += size;
        跳出;
    分支 符_汇编DIR_quad:
#如果已定义 ZHI_TARGET_X86_64
	size = 8;
	去向 汇编_data;
#否则
        带有宏替换的下个标记();
        循环(;;) {
            uint64_t vl;
            常量 字符型 *p;

            p = 单词值.str.data;
            如果 (单词编码 != 常量_预处理编号) {
            error_constant:
                错误_打印("64 bit constant");
            }
            vl = strtoll(p, (字符型 **)&p, 0);
            如果 (*p != '\0')
                去向 error_constant;
            带有宏替换的下个标记();
            如果 (sec->sh_type != SHT_NOBITS) {
                /* XXX: endianness */
                生成_le32(vl);
                生成_le32(vl >> 32);
            } 否则 {
                输出代码索引 += 8;
            }
            如果 (单词编码 != ',')
                跳出;
            带有宏替换的下个标记();
        }
        跳出;
#结束如果
    分支 符_汇编DIR_byte:
        size = 1;
        去向 汇编_data;
    分支 符_汇编DIR_word:
    分支 符_汇编DIR_short:
        size = 2;
        去向 汇编_data;
    分支 符_汇编DIR_long:
    分支 符_汇编DIR_整数型:
        size = 4;
    汇编_data:
        带有宏替换的下个标记();
        循环(;;) {
            表达式值 e;
            汇编_表达式(状态机1, &e);
            如果 (sec->sh_type != SHT_NOBITS) {
                如果 (size == 4) {
                    生成_32位表达式(&e);
#如果已定义 ZHI_TARGET_X86_64
		} 否则 如果 (size == 8) {
		    生成_64位表达式(&e);
#结束如果
                } 否则 {
                    如果 (e.sym)
                        应为("constant");
                    如果 (size == 1)
                        生成(e.v);
                    否则
                        生成_le16(e.v);
                }
            } 否则 {
                输出代码索引 += size;
            }
            如果 (单词编码 != ',')
                跳出;
            带有宏替换的下个标记();
        }
        跳出;
    分支 符_汇编DIR_fill:
        {
            整数型 repeat, size, val, i, j;
            uint8_t repeat_buf[8];
            带有宏替换的下个标记();
            repeat = 汇编_整数_表达式(状态机1);
            如果 (repeat < 0) {
                错误_打印("repeat < 0; .fill ignored");
                跳出;
            }
            size = 1;
            val = 0;
            如果 (单词编码 == ',') {
                带有宏替换的下个标记();
                size = 汇编_整数_表达式(状态机1);
                如果 (size < 0) {
                    错误_打印("size < 0; .fill ignored");
                    跳出;
                }
                如果 (size > 8)
                    size = 8;
                如果 (单词编码 == ',') {
                    带有宏替换的下个标记();
                    val = 汇编_整数_表达式(状态机1);
                }
            }
            /* XXX: endianness */
            repeat_buf[0] = val;
            repeat_buf[1] = val >> 8;
            repeat_buf[2] = val >> 16;
            repeat_buf[3] = val >> 24;
            repeat_buf[4] = 0;
            repeat_buf[5] = 0;
            repeat_buf[6] = 0;
            repeat_buf[7] = 0;
            循环(i = 0; i < repeat; i++) {
                循环(j = 0; j < size; j++) {
                    生成(repeat_buf[j]);
                }
            }
        }
        跳出;
    分支 符_汇编DIR_rept:
        {
            整数型 repeat;
            单词字符串 *init_str;
            带有宏替换的下个标记();
            repeat = 汇编_整数_表达式(状态机1);
            init_str = 单词字符串_分配();
            判断 (带有宏替换的下个标记(), 单词编码 != 符_汇编DIR_endr) {
                如果 (单词编码 == CH_文件结尾)
                    错误_打印("we at end of file, .endr not found");
                单词字符串中添加当前解析的字符(init_str);
            }
            单词字符串_增加大小(init_str, -1);
            单词字符串_增加大小(init_str, 0);
            开始_宏(init_str, 1);
            判断 (repeat-- > 0) {
                zhi_汇编_内部(状态机1, (解析_标记 & 解析_标记_预处理),
				      global);
                宏_ptr = init_str->str;
            }
            结束_宏();
            带有宏替换的下个标记();
            跳出;
        }
    分支 符_汇编DIR_org:
        {
            无符号 long n;
	    表达式值 e;
	    ELF符号 *esym;
            带有宏替换的下个标记();
	    汇编_表达式(状态机1, &e);
	    n = e.v;
	    esym = elf符号(e.sym);
	    如果 (esym) {
		如果 (esym->st_shndx != 当前_生成代码_段->sh_num)
		  应为("constant or same-section symbol");
		n += esym->st_value;
	    }
            如果 (n < 输出代码索引)
                错误_打印("attempt to .org backwards");
            v = 0;
            size = n - 输出代码索引;
            去向 zero_pad;
        }
        跳出;
    分支 符_汇编DIR_set:
	带有宏替换的下个标记();
	tok1 = 单词编码;
	带有宏替换的下个标记();
	/* 也接受“ .set东西”,但是对此不做任何事情。 它在GAS中用于设置各种功能,例如“ .set mips16”。 */
	如果 (单词编码 == ',')
	    设置_符号(状态机1, tok1);
	跳出;
    分支 符_汇编DIR_globl:
    分支 符_汇编DIR_global:
    分支 符_汇编DIR_weak:
    分支 符_汇编DIR_hidden:
	tok1 = 单词编码;
	执行 { 
            符号 *sym;
            带有宏替换的下个标记();
            sym = 获取_汇编_符号(单词编码, NULL);
	    如果 (tok1 != 符_汇编DIR_hidden)
                sym->type.t &= ~VT_静态;
            如果 (tok1 == 符_汇编DIR_weak)
                sym->a.weak = 1;
	    否则 如果 (tok1 == 符_汇编DIR_hidden)
	        sym->a.visibility = STV_HIDDEN;
            更新_存储(sym);
            带有宏替换的下个标记();
	} 判断 (单词编码 == ',');
	跳出;
    分支 符_汇编DIR_string:
    分支 符_汇编DIR_ascii:
    分支 符_汇编DIR_asciz:
        {
            常量 uint8_t *p;
            整数型 i, size, t;

            t = 单词编码;
            带有宏替换的下个标记();
            循环(;;) {
                如果 (单词编码 != 常量_字符串)
                    应为("string constant");
                p = 单词值.str.data;
                size = 单词值.str.size;
                如果 (t == 符_汇编DIR_ascii && size > 0)
                    size--;
                循环(i = 0; i < size; i++)
                    生成(p[i]);
                带有宏替换的下个标记();
                如果 (单词编码 == ',') {
                    带有宏替换的下个标记();
                } 否则 如果 (单词编码 != 常量_字符串) {
                    跳出;
                }
            }
	}
	跳出;
    分支 符_汇编DIR_text:
    分支 符_汇编DIR_data:
    分支 符_汇编DIR_bss:
	{ 
            字符型 sname[64];
            tok1 = 单词编码;
            n = 0;
            带有宏替换的下个标记();
            如果 (单词编码 != ';' && 单词编码 != 符_换行) {
		n = 汇编_整数_表达式(状态机1);
		带有宏替换的下个标记();
            }
            如果 (n)
                sprintf(sname, "%s%d", 取_单词字符串(tok1, NULL), n);
            否则
                sprintf(sname, "%s", 取_单词字符串(tok1, NULL));
            使用_段(状态机1, sname);
	}
	跳出;
    分支 符_汇编DIR_file:
        {
            字符型 文件名[512];

            文件名[0] = '\0';
            带有宏替换的下个标记();

            如果 (单词编码 == 常量_字符串)
                连接_字符串(文件名, 取大小(文件名), 单词值.str.data);
            否则
                连接_字符串(文件名, 取大小(文件名), 取_单词字符串(单词编码, NULL));

            如果 (状态机1->警告_不支持)
                zhi_警告("ignoring .file %s", 文件名);

            带有宏替换的下个标记();
        }
        跳出;
    分支 符_汇编DIR_ident:
        {
            字符型 ident[256];

            ident[0] = '\0';
            带有宏替换的下个标记();

            如果 (单词编码 == 常量_字符串)
                连接_字符串(ident, 取大小(ident), 单词值.str.data);
            否则
                连接_字符串(ident, 取大小(ident), 取_单词字符串(单词编码, NULL));

            如果 (状态机1->警告_不支持)
                zhi_警告("ignoring .ident %s", ident);

            带有宏替换的下个标记();
        }
        跳出;
    分支 符_汇编DIR_size:
        { 
            符号 *sym;

            带有宏替换的下个标记();
            sym = 汇编_标签_查找(单词编码);
            如果 (!sym) {
                错误_打印("label not found: %s", 取_单词字符串(单词编码, NULL));
            }

            /* XXX .size name,label2-label1 */
            如果 (状态机1->警告_不支持)
                zhi_警告("ignoring .size %s,*", 取_单词字符串(单词编码, NULL));

            带有宏替换的下个标记();
            跳过(',');
            判断 (单词编码 != 符_换行 && 单词编码 != ';' && 单词编码 != CH_文件结尾) {
                带有宏替换的下个标记();
            }
        }
        跳出;
    分支 符_汇编DIR_type:
        { 
            符号 *sym;
            常量 字符型 *newtype;

            带有宏替换的下个标记();
            sym = 获取_汇编_符号(单词编码, NULL);
            带有宏替换的下个标记();
            跳过(',');
            如果 (单词编码 == 常量_字符串) {
                newtype = 单词值.str.data;
            } 否则 {
                如果 (单词编码 == '@' || 单词编码 == '%')
                    带有宏替换的下个标记();
                newtype = 取_单词字符串(单词编码, NULL);
            }

            如果 (!strcmp(newtype, "function") || !strcmp(newtype, "STT_FUNC")) {
                sym->type.t = (sym->type.t & ~VT_基本类型) | VT_函数;
            }
            否则 如果 (状态机1->警告_不支持)
                zhi_警告("change type of '%s' from 0x%x to '%s' ignored", 
                    取_单词字符串(sym->v, NULL), sym->type.t, newtype);

            带有宏替换的下个标记();
        }
        跳出;
    分支 符_汇编DIR_pushsection:
    分支 符_汇编DIR_section:
        {
            字符型 sname[256];
	    整数型 old_nb_section = 状态机1->数量_段数;

	    tok1 = 单词编码;
            /* XXX: support more options */
            带有宏替换的下个标记();
            sname[0] = '\0';
            判断 (单词编码 != ';' && 单词编码 != 符_换行 && 单词编码 != ',') {
                如果 (单词编码 == 常量_字符串)
                    连接_字符串(sname, 取大小(sname), 单词值.str.data);
                否则
                    连接_字符串(sname, 取大小(sname), 取_单词字符串(单词编码, NULL));
                带有宏替换的下个标记();
            }
            如果 (单词编码 == ',') {
                /* 跳过 section options */
                带有宏替换的下个标记();
                如果 (单词编码 != 常量_字符串)
                    应为("string constant");
                带有宏替换的下个标记();
                如果 (单词编码 == ',') {
                    带有宏替换的下个标记();
                    如果 (单词编码 == '@' || 单词编码 == '%')
                        带有宏替换的下个标记();
                    带有宏替换的下个标记();
                }
            }
            最后_代码_段 = 当前_生成代码_段;
	    如果 (tok1 == 符_汇编DIR_section)
	        使用_段(状态机1, sname);
	    否则
	        推送_段(状态机1, sname);
	    /* If we just allocated a new section reset its alignment to
	       1.  创建_节 normally acts 循环 GCC compatibility and
	       sets alignment to 指针_大小.  The assembler behaves different. */
	    如果 (old_nb_section != 状态机1->数量_段数)
	        当前_生成代码_段->sh_addralign = 1;
        }
        跳出;
    分支 符_汇编DIR_previous:
        {*sec;
            带有宏替换的下个标记();
            如果 (!最后_代码_段)
                错误_打印("no previous section referenced");
            sec = 当前_生成代码_段;
            使用_段1(状态机1, 最后_代码_段);
            最后_代码_段 = sec;
        }
        跳出;
    分支 符_汇编DIR_popsection:
	带有宏替换的下个标记();
	弹出_段(状态机1);
	跳出;
#如果已定义 ZHI_TARGET_I386
    分支 符_汇编DIR_code16:
        {
            带有宏替换的下个标记();
            状态机1->段_大小 = 16;
        }
        跳出;
    分支 符_汇编DIR_code32:
        {
            带有宏替换的下个标记();
            状态机1->段_大小 = 32;
        }
        跳出;
#结束如果
#如果已定义 ZHI_TARGET_X86_64
    /* added 循环 compatibility with GAS */
    分支 符_汇编DIR_code64:
        带有宏替换的下个标记();
        跳出;
#结束如果
    default:
        错误_打印("未知的汇编指令 '.%s'", 取_单词字符串(单词编码, NULL));
        跳出;
    }
}


/* 解析一个文件 */
静态 整数型 zhi_汇编_内部(知心状态机 *状态机1, 整数型 do_preprocess, 整数型 global)
{
    整数型 opcode;
    整数型 saved_解析_标记 = 解析_标记;

    解析_标记 = 解析_标记_汇编_文件 | 解析_标记_单词字符串;
    如果 (do_preprocess)
        解析_标记 |= 解析_标记_预处理;
    循环(;;) {
        带有宏替换的下个标记();
        如果 (单词编码 == 符_文件结尾)
            跳出;
        解析_标记 |= 解析_标记_换行符; /* XXX: suppress that hack */
    redo:
        如果 (单词编码 == '#') {
            /* horrible gas comment */
            判断 (单词编码 != 符_换行)
                带有宏替换的下个标记();
        } 否则 如果 (单词编码 >= 定义_汇编目录_第一个 && 单词编码 <= 定义_汇编目录_最后一个) {
            汇编_解析_指令(状态机1, global);
        } 否则 如果 (单词编码 == 常量_预处理编号) {
            常量 字符型 *p;
            整数型 n;
            p = 单词值.str.data;
            n = strtoul(p, (字符型 **)&p, 10);
            如果 (*p != '\0')
                应为("':'");
            /* new local label */
            汇编_新_标签(状态机1, 汇编_获取_局部_标签_名称(状态机1, n), 1);
            带有宏替换的下个标记();
            跳过(':');
            去向 redo;
        } 否则 如果 (单词编码 >= 符_识别) {
            /* instruction or label */
            opcode = 单词编码;
            带有宏替换的下个标记();
            如果 (单词编码 == ':') {
                /* new label */
                汇编_新_标签(状态机1, opcode, 0);
                带有宏替换的下个标记();
                去向 redo;
            } 否则 如果 (单词编码 == '=') {
		设置_符号(状态机1, opcode);
                去向 redo;
            } 否则 {
                汇编_指令代码(状态机1, opcode);
            }
        }
        /* end of line */
        如果 (单词编码 != ';' && 单词编码 != 符_换行)
            应为("end of line");
        解析_标记 &= ~解析_标记_换行符; /* XXX: suppress that hack */
    }

    解析_标记 = saved_解析_标记;
    返回 0;
}

/* 汇编当前文件 */
静态_函数 整数型 zhi_汇编(知心状态机 *状态机1, 整数型 do_preprocess)
{
    整数型 ret;
    zhi_调试_开始(状态机1);
    /* default section is text */
    当前_生成代码_段 = 生成代码_段;
    输出代码索引 = 当前_生成代码_段->数据_偏移;
    不需要_代码生成 = 0;
    ret = zhi_汇编_内部(状态机1, do_preprocess, 1);
    当前_生成代码_段->数据_偏移 = 输出代码索引;
    zhi_结束_调试(状态机1);
    返回 ret;
}

/********************************************************************/
/* GCC内联asm支持 */

/* 在不进行C预处理的情况下,在当前C编译单元中组装字符串'str'。 注意:通过在末尾修改'\ 0'来修改str */
静态 无类型 zhi_内联_汇编(知心状态机 *状态机1, 字符型 *str, 整数型 len, 整数型 global)
{
    常量 整数型 *saved_宏_ptr = 宏_ptr;
    整数型 dotid = 设置_等值数('.', IS_ID);
    整数型 dolid = 设置_等值数('$', 0);

    打开缓存文件(状态机1, ":asm:", len);
    memcpy(file->buffer, str, len);
    宏_ptr = NULL;
    zhi_汇编_内部(状态机1, 0, global);
    关闭文件();

    设置_等值数('$', dolid);
    设置_等值数('.', dotid);
    宏_ptr = saved_宏_ptr;
}

/* 通过编号或ID(gcc 3扩展语法)查找约束。 如果找不到,则返回-1。 约束后以char返回* pp */
静态_函数 整数型 查找_约束(汇编操作数 *operands, 整数型 数量_operands,
                           常量 字符型 *name, 常量 字符型 **pp)
{
    整数型 index;
    单词存储结构 *ts;
    常量 字符型 *p;

    如果 (是数字(*name)) {
        index = 0;
        判断 (是数字(*name)) {
            index = (index * 10) + (*name) - '0';
            name++;
        }
        如果 ((无符号)index >= 数量_operands)
            index = -1;
    } 否则 如果 (*name == '[') {
        name++;
        p = strchr(name, ']');
        如果 (p) {
            ts = 单词表_查找(name, p - name);
            循环(index = 0; index < 数量_operands; index++) {
                如果 (operands[index].id == ts->单词编码)
                    去向 found;
            }
            index = -1;
        found:
            name = p + 1;
        } 否则 {
            index = -1;
        }
    } 否则 {
        index = -1;
    }
    如果 (pp)
        *pp = name;
    返回 index;
}

静态 无类型 替代_汇编_操作数(汇编操作数 *operands, 整数型 数量_operands,动态字符串 *out_str, 动态字符串 *in_str)
{
    整数型 c, index, modifier;
    常量 字符型 *str;
    汇编操作数 *op;
    堆栈值 sv;

    动态字符串_初始化(out_str);
    str = in_str->指向字符串的指针;
    循环(;;) {
        c = *str++;
        如果 (c == '%') {
            如果 (*str == '%') {
                str++;
                去向 添加_字符;
            }
            modifier = 0;
            如果 (*str == 'c' || *str == 'n' ||
                *str == 'b' || *str == 'w' || *str == 'h' || *str == 'k' ||
		*str == 'q' ||
		/*在PIC模式下,GCC中的P将在符号引用中添加“ @PLT”,并使文字操作数不使用“ $”修饰。 */
		*str == 'P')
                modifier = *str++;
            index = 查找_约束(operands, 数量_operands, str, &str);
            如果 (index < 0)
                错误_打印("invalid operand reference after %%");
            op = &operands[index];
            sv = *op->vt;
            如果 (op->reg >= 0) {
                sv.r = op->reg;
                如果 ((op->vt->r & VT_值掩码) == VT_LLOCAL && op->is_memory)
                    sv.r |= VT_LVAL;
            }
            替换_汇编_操作数(out_str, &sv, modifier);
        } 否则 {
        添加_字符:
            动态字符串_追加单个字符(out_str, c);
            如果 (c == '\0')
                跳出;
        }
    }
}


静态 无类型 解析_汇编_操作数(汇编操作数 *operands, 整数型 *数量_operands_ptr,
                               整数型 is_output)
{
    汇编操作数 *op;
    整数型 数量_operands;

    如果 (单词编码 != ':') {
        数量_operands = *数量_operands_ptr;
        循环(;;) {
	    动态字符串 astr;
            如果 (数量_operands >= 最大_汇编_操作数)
                错误_打印("太多的汇编操作数");
            op = &operands[数量_operands++];
            op->id = 0;
            如果 (单词编码 == '[') {
                带有宏替换的下个标记();
                如果 (单词编码 < 符_识别)
                    应为("identifier");
                op->id = 单词编码;
                带有宏替换的下个标记();
                跳过(']');
            }
	    解析_多_字符串(&astr, "string constant");
            op->constraint = 内存_申请(astr.字符串长度);
            strcpy(op->constraint, astr.指向字符串的指针);
	    动态字符串_释放(&astr);
            跳过('(');
            通用表达式();
            如果 (is_output) {
                如果 (!(栈顶值->type.t & VT_数组))
                    测试_左值();
            } 否则 {
                /* 我们希望避免使用LLOCAL的情况,除非使用'm'约束。 请注意,它可能来自寄存器存储,因此我们需要转换(reg)大小写 */
                如果 ((栈顶值->r & VT_LVAL) &&
                    ((栈顶值->r & VT_值掩码) == VT_LLOCAL ||
                     (栈顶值->r & VT_值掩码) < VT_VC常量) &&
                    !strchr(op->constraint, 'm')) {
                    将rc寄存器值存储在栈顶值中(寄存器类_整数);
                }
            }
            op->vt = 栈顶值;
            跳过(')');
            如果 (单词编码 == ',') {
                带有宏替换的下个标记();
            } 否则 {
                跳出;
            }
        }
        *数量_operands_ptr = 数量_operands;
    }
}

/* 解析GCC asm()指令 */
静态_函数 无类型 汇编_指令字符串(无类型)
{
    动态字符串 astr, astr1;
    汇编操作数 operands[最大_汇编_操作数];
    整数型 数量_outputs, 数量_operands, i, must_subst, out_reg;
    uint8_t clobber_regs[NB_ASM_REGS];*sec;

    /* 由于我们总是生成asm()指令,因此可以忽略volatile */
    如果 (单词编码 == 关键字_VOLATILE1 || 单词编码 == 关键字_VOLATILE2 || 单词编码 == 关键字_VOLATILE3 || 单词编码 == 关键字_易变) {
        带有宏替换的下个标记();
    }
    解析_汇编_字符串(&astr);
    数量_operands = 0;
    数量_outputs = 0;
    must_subst = 0;
    memset(clobber_regs, 0, 取大小(clobber_regs));
    如果 (单词编码 == ':') {
        带有宏替换的下个标记();
        must_subst = 1;
        /* 输出参数 */
        解析_汇编_操作数(operands, &数量_operands, 1);
        数量_outputs = 数量_operands;
        如果 (单词编码 == ':') {
            带有宏替换的下个标记();
            如果 (单词编码 != ')') {
                /* 输入参数 */
                解析_汇编_操作数(operands, &数量_operands, 0);
                如果 (单词编码 == ':') {
                    /* 垃圾清单 */
                    /* XXX: 处理寄存器 */
                    带有宏替换的下个标记();
                    循环(;;) {
                        如果 (单词编码 != 常量_字符串)
                            应为("string constant");
                        汇编_破坏者(clobber_regs, 单词值.str.data);/**/
                        带有宏替换的下个标记();
                        如果 (单词编码 == ',') {
                            带有宏替换的下个标记();
                        } 否则 {
                            跳出;
                        }
                    }
                }
            }
        }
    }
    跳过(')');
    /* 注意:我们不吃';' 这样我们就可以在汇编程序解析后还原当前令牌 */
    如果 (单词编码 != ';')
        应为("';'");
    
    /* 将所有值保存在内存中 */
    保存_寄存器最多n个堆栈条目(0);

    /* 计算约束 */
    汇编_计算_约束(operands, 数量_operands, 数量_outputs, 
                            clobber_regs, &out_reg);

    /* 替换asm字符串中的操作数。 如果没有操作数(GCC行为),则不会进行替换*/
#如果已定义 ASM_DEBUG
    printf("asm: \"%s\"\n", (字符型 *)astr.指向字符串的指针);
#结束如果
    如果 (must_subst) {
        替代_汇编_操作数(operands, 数量_operands, &astr1, &astr);
        动态字符串_释放(&astr);
    } 否则 {
        astr1 = astr;
    }
#如果已定义 ASM_DEBUG
    printf("subst_asm: \"%s\"\n", (字符型 *)astr1.指向字符串的指针);
#结束如果

    /* 产生负荷 */
    汇编_生成_代码(operands, 数量_operands, 数量_outputs, 0, 
                 clobber_regs, out_reg);    

    /* 用zhi内部汇编器组装轴向  */
    sec = 当前_生成代码_段;
    /* 用zhi内部汇编器组装字符串 */
    zhi_内联_汇编(zhi_状态, astr1.指向字符串的指针, astr1.字符串长度 - 1, 0);
    如果 (sec != 当前_生成代码_段) {
        zhi_警告("内联 asm tries to change current section");
        使用_段1(zhi_状态, sec);
    }

    /* 恢复当前的C标识符 */
    带有宏替换的下个标记();

    /* 如果需要,存储输出值*/
    汇编_生成_代码(operands, 数量_operands, 数量_outputs, 1, 
                 clobber_regs, out_reg);
    
    /* 释放一切 */
    循环(i=0;i<数量_operands;i++) {
        汇编操作数 *op;
        op = &operands[i];
        内存_释放(op->constraint);
        弹出堆栈值();
    }
    动态字符串_释放(&astr1);
}

静态_函数 无类型 汇编_全局_instr(无类型)
{
    动态字符串 astr;
    整数型 saved_nocode_wanted = 不需要_代码生成;

    /* 始终会发出全局asm块。  */
    不需要_代码生成 = 0;
    带有宏替换的下个标记();
    解析_汇编_字符串(&astr);
    跳过(')');
    /* 注意:我们不吃';' 这样我们就可以在汇编程序解析后还原当前标识 */
    如果 (单词编码 != ';')
        应为("';'");
    
#如果已定义 ASM_DEBUG
    printf("汇编_global: \"%s\"\n", (字符型 *)astr.指向字符串的指针);
#结束如果
    当前_生成代码_段 = 生成代码_段;
    输出代码索引 = 当前_生成代码_段->数据_偏移;

    /* 用zhi内部汇编器组装字符串 */
    zhi_内联_汇编(zhi_状态, astr.指向字符串的指针, astr.字符串长度 - 1, 1);
    
    当前_生成代码_段->数据_偏移 = 输出代码索引;

    /* 恢复当前的C标识符 */
    带有宏替换的下个标记();

    动态字符串_释放(&astr);
    不需要_代码生成 = saved_nocode_wanted;
}
#结束如果 /* 配置_ZHI_汇编 */

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知语言

您的鼓励是我从事编译器汉化动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值