在以下示例中,程序应打印"foo called":
// foo.c
#include <stdio.h>
__attribute__((constructor)) void foo()
{
printf("foo called\n");
}
// main.c
int main()
{
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果程序是这样编译的,它可以工作:
gcc -o test main.c foo.c
Run Code Online (Sandbox Code Playgroud)
但是,如果将foo.c编译为静态库,则程序不会打印任何内容.
gcc -c main.c
gcc -c foo.c
as rcs foo.a foo.o
gcc -o test foo.a main.o
Run Code Online (Sandbox Code Playgroud)
为什么会这样?
我目前正在选择一个项目,以便在接下来的8周内完成毕业级编译器课程.我想做一些与优化相关的事情,因为我以前在那个领域没有多少工作,但是该领域的任何事情都是公平的.
你做过的最有趣的编译器相关项目是什么?你从中学到了什么?
编辑:谢谢大家的好建议.我很抱歉没有更新这个问题.
我最终做的项目是在LLVM上进行简单的自动向量化优化.LLVM有矢量类型,但似乎没有任何方法可以在不支持前端的情况下利用它们.此优化将正常标量代码转换为矢量代码.
由于自动矢量化是一个相当难以实现的优化,因此我们尽可能地限制了我们的范围.首先,为了在代码中公开指令级并行性,我们寻找符合我们标准的单块循环,然后将它们展开特定次数,以便它们可以方便地进行矢量化.然后,我们实现了Larsen和Amarasinghe 在利用多媒体指令集开发超级词级并行中所规定的打包算法.
即使是这种优化的简化版本也非常复杂.有很多限制; 例如,您不希望对存在于循环之外的变量进行矢量化,因为程序的其余部分期望它是标量.我们在过去几周里花了很多时间.虽然这个项目很有趣,但我们学到了很多东西.
假设我们想尽快编译一个大型项目(比如GCC或Linux内核).具有超线程功能的CPU(比如Intel Core i7)是否可以在启用或禁用超线程的情况下更快地运行编译器?是否有任何已发布的测试基准测试?
我对超线程的理解是每个核心都可以从两个(或更多个进程)中选择指令.这通常使核心更有效,因为功能单元不太可能空闲.但是,由于在相同内核上运行的进程共享资源(如缓存)可能会相互干扰,因此可能会降低性能.性能是否实际增加取决于工作量.
那么对于编译器工作负载,性能是否会提高?如果是这样,多少钱?
据我所知,递归非常优雅,但在OOP和程序编程方面效率不高(参见精彩的"High Order perl",Mark Jason Dominus).我有一些信息,在函数式编程递归中很快 - 保持其优雅和简洁.有人可以确认并可能放大这个吗?我正在考虑XSLT和Haskell(我的下一个语言学习列表的高位)
谢谢
丹尼尔
xslt optimization haskell functional-programming tail-recursion
我想使用Scala为JUnit 4测试设置一个预期的异常.我目前正在做类似以下的事情:
@Test(expected=classOf[NullPointerException])
def someTest() = {
// Some test code
}
Run Code Online (Sandbox Code Playgroud)
但是我得到以下编译器错误:
error: wrong number of arguments for constructor Test: ()org.junit.Test
Run Code Online (Sandbox Code Playgroud) 我正在为实验语言写一个翻译.该语言的三个主要结构是定义,语句和表达式.定义可以包含语句和表达式,语句可以包含定义和表达式,一种表达式可以包含语句.我使用union类型表示所有这些,因此我可以轻松地在它们上使用模式匹配.理想情况下,我想将这些代码放在不同的文件中,但OMake抱怨循环依赖问题.据我所知,不允许跨模块的循环类型定义.
我知道解决这个问题的唯一方法是一次定义所有三种类型:
type defn = ...
and stmt = ...
and expr = ...
Run Code Online (Sandbox Code Playgroud)
看起来这需要所有类型的代码都在同一个文件中.有没有办法解决?你如何处理代码中的循环定义?
看看这段代码:
#include <iostream>
using namespace std;
int main()
{
const char* str0 = "Watchmen";
const char* str1 = "Watchmen";
char* str2 = "Watchmen";
char* str3 = "Watchmen";
cerr << static_cast<void*>( const_cast<char*>( str0 ) ) << endl;
cerr << static_cast<void*>( const_cast<char*>( str1 ) ) << endl;
cerr << static_cast<void*>( str2 ) << endl;
cerr << static_cast<void*>( str3 ) << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这会产生如下输出:
0x443000
0x443000
0x443000
0x443000
Run Code Online (Sandbox Code Playgroud)
这是在Cygwin下运行的g ++编译器.即使没有打开优化(),指针也指向相同的位置.-O0
编译器是否总是进行优化以至于它会搜索所有字符串常量以查看它们是否相等?可以依赖这种行为吗?
我有一个64位版本的llvm-gcc,但我希望能够构建32位和64位二进制文件.这有旗帜吗?我尝试传递-m32(适用于常规gcc),但我收到如下错误信息:
[jay@andesite]$ llvm-gcc -m32 test.c -o test
Warning: Generation of 64-bit code for a 32-bit processor requested.
Warning: 64-bit processors all have at least SSE2.
/tmp/cchzYo9t.s: Assembler messages:
/tmp/cchzYo9t.s:8: Error: bad register name `%rbp'
/tmp/cchzYo9t.s:9: Error: bad register name `%rsp'
...
Run Code Online (Sandbox Code Playgroud)
这是倒退; 我想为64位处理器生成32位代码!
我正在运行llvm-gcc 4.2,这是Ubuntu 9.04 x86-64附带的.
编辑:当我使用-v标志运行llvm-gcc时,这是输出的相关部分:
[jay@andesite]$ llvm-gcc -v -m32 test.c -o test.bc
Using built-in specs.
Target: x86_64-linux-gnu
Configured with: ../llvm-gcc4.2-2.2.source/configure --host=x86_64-linux-gnu --build=x86_64-linux-gnu --prefix=/usr/lib/llvm/gcc-4.2 --enable-languages=c,c++ --program-prefix=llvm- --enable-llvm=/usr/lib/llvm --enable-threads --disable-nls --disable-shared --disable-multilib --disable-bootstrap
Thread model: posix
gcc version …
Run Code Online (Sandbox Code Playgroud) 我正在尝试解析ocamlyacc中的语法(几乎与常规yacc相同),它支持没有运算符的函数应用程序(如Ocaml或Haskell),以及二进制和一元运算符的常规分类.我正在使用' - '运算符进行减少/减少冲突,它可以用于减法和否定.这是我正在使用的语法示例:
%token <int> INT
%token <string> ID
%token MINUS
%start expr
%type <expr> expr
%nonassoc INT ID
%left MINUS
%left APPLY
%%
expr: INT
{ ExprInt $1 }
| ID
{ ExprId $1 }
| expr MINUS expr
{ ExprSub($1, $3) }
| MINUS expr
{ ExprNeg $2 }
| expr expr %prec APPLY
{ ExprApply($1, $2) };
Run Code Online (Sandbox Code Playgroud)
问题是,当你得到一个像"a - b"这样的表达式时,解析器不知道这是否应该减少为"a(-b)"(否定b,后跟应用程序)或"a - b"(减法).减法减少是正确的.如何解决有利于该规则的冲突?
我经常在C++中遇到大型的非模板类,其中简单的方法直接在头文件的类体中定义,而不是在实现文件中单独定义.例如:
class Foo {
int getBar() const { return bar; }
...
};
Run Code Online (Sandbox Code Playgroud)
为什么这样?好像有缺点.实现不是应该隐藏的,代码不太可读,如果类的头文件包含在许多不同的地方,编译器的负担也会增加.
我的猜测是人们打算在其他模块中内联这些功能,这可以显着提高性能.但是,我听说较新的编译器可以跨模块在链接时进行内联(和其他过程间优化).对这种链接时优化的支持有多广泛,它是否真的不需要这些定义?这些定义还有其他充分的理由吗?
optimization ×3
c ×2
c++ ×2
ocaml ×2
32-bit ×1
32bit-64bit ×1
64-bit ×1
annotations ×1
attributes ×1
compilation ×1
constants ×1
constructor ×1
grammar ×1
haskell ×1
junit4 ×1
llvm ×1
llvm-gcc ×1
parsing ×1
performance ×1
scala ×1
string ×1
xslt ×1
yacc ×1