微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – 太多的部分,汇编错误,使用boost :: spirit

我正在为一个 Java子集编写一个编译器,使用boost :: spirit来进行词法和解析.在编译词法分析器/解析器阶段时,编译器会消耗1.6GB的RAM(g(GCC)4.8.1),但这并不是一个问题,因为这台机器上有大量的内存.

然而,一个问题是,当编译器完成并且汇编器开始运行(GNU汇编器(GNU Binutils)2.23.52.20130604)时,它崩溃了;

as: build/src/ast_generate.o: too many sections (33098)
/tmp/cc0ZyvKK.s: Assembler messages:
/tmp/cc0ZyvKK.s: Fatal error: can't write build/src/ast_generate.o: File too big
as: build/src/ast_generate.o: too many sections (33098)
/tmp/cc0ZyvKK.s: Fatal error: can't close build/src/ast_generate.o: File too big
scons: *** [build/src/ast_generate.o] Error 1

将“-Os”添加到我的编译器标志中,允许汇编程序处理编译器输出,但正如我所看到的,这只是一个时间问题,直到我遇到同样的问题,即使使用小的优化标志.

检查大小优化的对象文件(ast_generate.o)使用objdump,告诉我,我正在生成pe-x86-64,这是我期望在Windows上.

2358生成的部分,对我来说是震惊的.大多数情况下,似乎已经为boost :: spirit的每个部分生成一个部分;

CONTENTS,ALLOC,LOAD,READONLY,DATA,LINK_ONCE_disCARD
 ...
 60 .pdata$_ZNK5boost5lexer6detail8end_node9unique_idEv 0000000c  0000000000000000  0000000000000000  00030750  2**2
 61 .text$_ZNK5boost5lexer6detail8end_node11lexer_stateEv 00000010  0000000000000000  0000000000000000  0003075c  2**4
 ...

所以我的问题是

>错误中的数字(太多的部分(X)),要生成的部分数,还是错误代码
>为什么为每个数据类型生成一个段?
>我可以做什么,以避免将’-Os’传递给我的编译器.也就是说,如何解决问题,而不是解决问题?
>将词法分析和分析阶段分成两个不同的阶段(和编译单元),只有通过词法迭代器连接才能帮助我?

注意;我正在使用cygwin64进行编译.

解决方法

在这里做了一些黑客,并重构了一个显示非运行时多态的样式:

> https://bitbucket.org/sehe/joos2compiler-refactor(根据你的12d01e5提交).

我希望它不会增加编译次数:)(我没有实际分解语法,但它变小).

特征:

>没有更多的堆分配AST节点(甚至对于树,如表达式和/或语句);因此没有更明确的克隆和/或伪造成员.
>我已经用Maybe.hpp替换了

#pragma once
#include <boost/optional.hpp>

template <typename T> using Maybe = boost::optional<T>;

它是快速和脏,但它都编译
>我用我自己的小小的努力取代了开放类型切换(我无法得到它的工作;还有boost-variant它全部内置):

namespace visitor_galore // this is my make-shift replacement for typeswitch (I Couldn't find it/make it work)
{
    template<typename T,class...Fs> struct visitor_t;

    template<typename T,class F1,class...Fs>
    struct visitor_t<T,F1,Fs...> : F1,visitor_t<T,Fs...>::type {
        typedef visitor_t type;
        visitor_t(F1 head,Fs...tail) : F1(head),Fs...>::type(tail...) {}

        using F1::operator();
        using visitor_t<T,Fs...>::type::operator();
    };

    template<typename T,class F> struct visitor_t<T,F> : F,boost::static_visitor<T> {
        typedef visitor_t type;
        visitor_t(F f) : F(f) {}
        using F::operator();
    };

    template<typename T=void,class...Fs>
    typename visitor_t<T,Fs...>::type make_visitor(Fs...x) { return {x...}; }
}

using visitor_galore::make_visitor;

要了解如何使用,请查看ast_pp.cpp:

void pretty_print(expression_incdec const& exp)
{
     boost::apply_visitor(
            make_visitor(
                [&exp](inc_dec_op_preinc const& op)  { std::cout << "++"; pretty_print(exp.variable); },[&exp](inc_dec_op_predec const& op)  { std::cout << "--"; pretty_print(exp.variable); },[&exp](inc_dec_op_postinc const& op) { pretty_print(exp.variable); std::cout << "++"; },[&exp](inc_dec_op_postdec const& op) { pretty_print(exp.variable); std::cout << "--"; }
                ),exp.operatur);
}

奖金如果您不在意分列列表中的所有类型,例如因为它们都调用相同的自由函数(或重载),您可以使用多态访问器:

static const struct pretty_print_visitor_ : boost::static_visitor<>
{
    template<typename T>
    void operator ()(T const& v) const { pretty_print(v); }
} pretty_print_visitor;

例如.现在你可以用24个分支替换表达式

boost::apply_visitor(
        make_visitor(
            [](expression_binop const& exp)              { pretty_print(exp); },[](expression_unop const& exp)               { pretty_print(exp); },[](expression_integer_constant const& exp)   { pretty_print(exp); },[](expression_character_constant const& exp) { pretty_print(exp); },[](expression_string_constant const& exp)    { pretty_print(exp); },[](expression_boolean_constant const& exp)   { pretty_print(exp); },[](expression_null const& exp)               { pretty_print(exp); },[](expression_this const& exp)               { pretty_print(exp); },[](expression_static_invoke const& exp)      { pretty_print(exp); },[](expression_non_static_invoke const& exp)  { pretty_print(exp); },[](expression_simple_invoke const& exp)      { pretty_print(exp); },[](expression_ambiguous_invoke const& exp)   { pretty_print(exp); },[](expression_new const& exp)                { pretty_print(exp); },[](expression_new_array const& exp)          { pretty_print(exp); },[](expression_lvalue const& exp)             { pretty_print(exp); },[](expression_assignment const& exp)         { pretty_print(exp); },[](expression_incdec const& exp)             { pretty_print(exp); },[](expression_cast const& exp)               { pretty_print(exp); },[](expression_ambiguous_cast const& exp)     { pretty_print(exp); },[](expression_instance_of const& exp)        { pretty_print(exp); },[](expression_parentheses const& exp)        { pretty_print(exp); },[](lvalue_non_static_field const& exp)       { pretty_print(exp); },[](lvalue_array const& exp)                  { pretty_print(exp); },[](lvalue_ambiguous_name const& exp)         { pretty_print(exp); }
       ),exp);

一个简单的

boost::apply_visitor(pretty_print_visitor,exp);

>注意几次,我已经把// Todo或// FIXME注释(值得注意的是concat,不太想为我编译).
>请注意,Ast类明显更简单(特别是内存分配更为正确)
>请注意,Parser本身由于对语义动作和Phoenix适应功能的需求减少而缩小
>请注意,我现在选择忘记了LexerPosition信息(以前在基类中是“隐藏”的,现在已经消失).有一个编译器教程示例,显示如何使用qi :: on_error(qi :: success,…)非常优雅地将源位置信息附加到所选的Ast节点(非侵入式).
>而不是在ast_helpers中的各种谓词,我预计可能会有一些有用的基于特征的谓词(例如is_lvalue或is_true_const).我选择“保持”帮助者或多或少的原样(这可能是完全错误的,我没有测试任何东西).
>我经常尝试将参数传递值替换为通过const& (compare e.g. the ast_pp.hpp),但我知道我已经留下了一些地方,因为任务足够大,因为它是.

巨额免责声明:我可能以各种方式破解了解析器.我没有试图用它解析任何东西.编辑是按原样提供的,没有任何声明的有用性.我以不同的方式解决了类似的问题(一旦traits :: tranform_attribute>专业化,一次大规模的语义动作和一些其他方法):

我的目标是告诉你,当我提到可能的时候,我在想什么

>显着降低动态多态性,>避免语义行为>在可能的情况下拥抱增强构架,以获得更多的“自动化”与精神融合>显示各种想法,你可以从以下选择你最喜欢的:

原文地址:https://www.jb51.cc/c/115624.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐