- 浏览: 58959 次
- 性别:
- 来自: 武汉
最新评论
-
NeuronR:
之前自搭 blog, 太累. 最近在研究 C艹 语言的错误处理 ...
C++ 中处理除零错误 -
lwwin:
话说很久没有看到你更新BLOG了,最近在研究LINUX开发^^ ...
C++ 中处理除零错误 -
lwwin:
RednaxelaFX 写道我的见识还是太少了……最近在某在x ...
[优化]删去 NOP 指令 -
RednaxelaFX:
我的见识还是太少了……最近在某在x86上跑的东西的手写汇编里的 ...
[优化]删去 NOP 指令 -
NeuronR:
lwwin 写道没想到一个NOP把FX也拉来了^^关于代码…… ...
[优化]删去 NOP 指令
文章列表
先来回顾上一篇开头处的一段代码的结尾处
EXIT_FREE_BUFFER:
free(buffer);
EXIT_CLOSE_DST:
fclose(dstf);
EXIT_CLOSE_SRC:
fclose(srcf);
return ret;
有一个问题是, 当有错误发生时 (ret 为非零值) 如果同时 free, fclose 这样的函数又出错, 那这个时候如何处理两个不同的错误呢? 答案是, 看一下手头任何一本 C 语言手册, 它都会说只要语言的使用者不手贱传递一个错误的指针到函数或者瞎掰似的连续释放两次, 函数都不 ...
C++ 标准库中的异常是标准库的一个组成部分, 但异常并不是 STL 的一部分, 所以下面这些内容里面不会展现任何关于泛型乃至模板相关可能令人不适的内容.
那, 先在 C 身上找点错误处理相关的乐子.
使用返回码进行错误处理
上篇文章聊的是一个非常具体的异常处理, 而在这个环境中, 使用异常是不得已的事情. 在 C 语言单调的世界里, 异常还是不存在的, 大家都非常和谐地使用特别的返回值来标记错误发生 (比如 fgetc 返回 EOF 表示文件读完了), 甚至返回值就直接是错误码本身 (如 fseek).
错误码机制会严重破坏结构化程序设计, 虽然 C 对 ...
转自 http://blog.bitfoc.us/?p=100
继承自 C 的"优良"传统, C++ 也是一门非常靠近底层的语言, 可是实在是太靠近了, 很多问题语言本身没有提供解决方案, 可执行代码贴近机器, 运行时没有虚拟机来反馈错误, 跑着跑着就毫 ...
在控制语句的指令生成过程中, 语句无法知道外界指令结构, 不能贸然将跳出语句定向到外部指令, 因此使用了 NOP 指令缓冲了这些跳转. 然而, 在全部指令生成结束后, 跳转指令就可以根据上下文选择正确的目标了, 那么 NOP 指令只是影响性能的冗余指令了. 本着兔死狗烹的原则, 现在去掉这些指令.
static void cleanNop(struct List* instructions);
具体的做法是, 为每个 NOP 指令记录它之后的第一条非 NOP 指令, 然后扫描指令序列, 重定向它们的目标, 然后删去全部 NOP 指令. 现在先给指令数据结构增加一个索引域
...
svn update 先.
测试约定
在 test 目录下, 有一坨 test-X.jerry 和 test-X.expect 文件, X=0, 1, 2, 3. 前者是 Jerry 源文件, 而 .expect 文件的则是, 当这个源文件被编译并执行以后应该输出的结果 (确实, 这些例子中没有对输入的测试).
test 目录下 ...
虚拟机
虚拟机的实现包含三个文件
jerry-vm.c
环境配置, 参数分析和 I/O 设定. main 函数在这个文件中
vm.h
类型定义, 以及全局变量的声明.
vm.c
指令的实现
这些文件编译链接后产生 JerryVM.out 可执行文件. 它的命令行参数之一是 Jerry 字节码. 它将读入指令然后执行它们.
双帧栈
所谓的双帧栈就是只栈内有两个栈段, 一个存放栈内数据, 一个进行算术运算. 这是一种简单, 但是非常浪费空间的处理方式.
正确的做法应该是根据符号表预估栈内变量总大小, 并留足这个空间, 使运算在这个空间之上进行 ...
- 2009-11-25 21:16
- 浏览 916
- 评论(4)
是的, 还有几个节点的指令生成没有测试呢, 包括流控制语句, IO. 不过呢, 流控制是相对比较容易优化的, 进行"生成指令再对比"的测试不太好维护, 而 IO 指令很简单: 所以要不这样, 把指令写出来, 然后开个虚拟机运行, 如果运行没问题就算测试通过了.
语义错误处理
一些常见的语义错误处理在之前的之前的内容中都以注释形式出现, 不过如果留心的话, 上次更新的代码这些错误处理都是完备的, 比如在 jerry-ui.h 和 jerry-ui.c 两个文件中给出了这些错误的 UI, 而 const.h 中更新了很多字符串字面常量宏作为错误信息. 当然你也可以随意修改 ...
- 2009-11-15 10:47
- 浏览 973
- 评论(2)
E, 这个算术节点指的是 ArithmaticNode.
由于之前已经测试了ArithmaticNode 全部可能的子节点项目, 因此这次要测试的非常简单, 只需要查看运算指令执行完毕后, 弹栈弹出的大小是不是期望的那么多. 所以, 直接上测试例子了
struct List* ins;
struct List* subIns;
struct ArithmaticNode* a;
struct IntegerNode* i = newIntegerNode(14);
a = newArithmaticNode((struct ...
- 2009-11-01 16:02
- 浏览 738
- 评论(0)
准备
在语法分析完结篇中我给出了一个压缩包, 里面包含了词法和语法分析的各个方面. 其中有一个叫做 jerry-ui.h 的文件中定义了一些 ui 以及 io 相关函数. 作为指令生成测试这样局部性质的测试, 也需要实现这些接口以免发生编译错误, 但没有必要使用 jerry-ui.c 中实现, 因此先在名为 test-ui.c 的文件中给出伪实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jerry-ui.h"
FILE* t ...
- 2009-10-18 11:09
- 浏览 799
- 评论(1)
最后还剩下一个, 声明语句的翻译. 因为符号表API已经很完善了, 所以声明语句的翻译不会太困难. 将一些小地方处理好了就行. 难对付的部分是设定初始值, 需要考虑到类型转换. OK, 代码说明一切.
struct List* insDeclarationNode(void* node)
{
struct DeclarationNode* self = (struct DeclarationNode*)node;
// 节点指令
struct List* insList = (struct List*)newArrayList();
Accep ...
- 2009-09-26 19:49
- 浏览 821
- 评论(2)
运算. 首先是单目运算指令, 相对而言比较简单, 只有3种情况
struct List* insUnaryOperationNode(void* node)
{
struct UnaryOperationNode* self = (struct UnaryOperationNode*)node;
AcceptType type = self->typeOf(self);
// 如果是常数
if (INTEGER == type) {
int intVal;
if (0 == self->staticInt ...
- 2009-09-12 16:46
- 浏览 861
- 评论(0)
首先回顾一下符号表提供的接口
AcceptType typeOf(struct VariableNode* var);
int staticOffset(struct VariableNode* var, int* offsets);
前面一个获取类型在这里并不是特别需要——那是在加载变量值的时候考虑的。至于 staticOffset 这个函数,功能已 ...
- 2009-09-01 20:31
- 浏览 934
- 评论(0)
非常抱歉我选择的字体有些问题,导致字符绘制的图表中右侧竖线没有对齐,追求视觉效果的同学可以将它们拷贝下来,粘贴之后改用“宋体”或其它等宽,并且1个中文字符宽度等于2个ASCII字符宽度的字体显示。
Jerry语言比较简单,流程控制仅限于分支和循环(而且只有while循环)。这里并不会对它们的指令生成做优化,只是给出能够运作的最基本解决方案。
首先是分支语句。完整的分支语句指令结构是这样的
+----------------------+
| condition 指令 |
+----------------------+
...
- 2009-08-15 11:15
- 浏览 865
- 评论(0)
每个节点生成的指令都是一个长长的指令列表,那么得弄几个小工具将这些列表给连接起来。
// 将一个指令追加到表末尾
static struct List* appendIns(struct List* list, void* ins)
{
list->addTo(list, ins, list->count(list));
return list;
}
// 将 back 连接到 front 之后
static struct List* appendInsList(struct List* front, struct List* back)
...
- 2009-07-31 19:47
- 浏览 929
- 评论(0)
继续向语法树节点结构中追加成员。
#define memberAbstractSyntaxNode \
unsigned int line; \
struct AbstractSyntaxNode* nextNode; \
struct List* (*createInstruction)(void*); \
void (*delNode)(void*); \
void (*printree)(void*, int ...
- 2009-07-24 10:15
- 浏览 797
- 评论(0)