デバッグ情報

http://llvm.org/docs/SourceLevelDebugging.htmlを読んで、大いに感動したものです。こんなに簡単にデバッグ情報が吐けるとは……。
いざ。
a.bas

?1+1
END

a.ll

declare void @llvm.dbg.func.start({  }*)
declare void @llvm.dbg.stoppoint(i32, i32, {  }*)
declare void @llvm.dbg.region.end({  }*)
declare i32 @printf(i8*, ...)
; main
%llvm.dbg.anchor.type = type {i32, i32}
%llvm.dbg.compile_unit.type = type {i32, {  }*, i32, i8*, i8*, i8*}
%llvm.dbg.subprogram.type = type {i32, {  }*, {  }*, i8*, i8*, i8*, {  }*, i32, {  }*, i1, i1}
;@main_disp = internal constant [5 x i8] c"list\00", section "llvm.metadata"
@main_name = internal constant [5 x i8] c"main\00", section "llvm.metadata"
@llvm.dbg.subprogram = internal constant %llvm.dbg.subprogram.type {
    i32 393262, 
    {  }* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.subprograms to {  }*), 
    {  }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to {  }*), 
    i8* getelementptr ([5 x i8]* @main_name, i32 0, i32 0), 
    i8* getelementptr ([5 x i8]* @main_name, i32 0, i32 0), 
    i8* null, 
    {  }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to {  }*), 
    i32 1, {  }* null, i1 true, i1 true}, section "llvm.metadata"
@llvm.dbg.subprograms = linkonce constant %llvm.dbg.anchor.type {
	i32 393216, i32 46}, section "llvm.metadata"
@source = internal constant [6 x i8] c"a.bas\00", section "llvm.metadata"
@path = internal constant [3 x i8] c"./\00", section "llvm.metadata"
@compiler = internal constant [13 x i8] c"handcompiled\00", section "llvm.metadata"
@llvm.dbg.compile_unit = internal constant %llvm.dbg.compile_unit.type {
    i32 393233, {  }* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.compile_units to {  }*), i32 1, 
    i8* getelementptr ([6 x i8]* @source, i32 0, i32 0), 
    i8* getelementptr ([3 x i8]* @path, i32 0, i32 0), 
    i8* getelementptr ([13 x i8]* @compiler, i32 0, i32 0)}, section "llvm.metadata"
@llvm.dbg.compile_units = linkonce constant %llvm.dbg.anchor.type {i32 393216, i32 17}, section "llvm.metadata"
; for printf
@format = internal constant [3 x i8] c"%d\00"
; main
define i32 @main() {
entry:
; start
    call void @llvm.dbg.func.start ({  }* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram to {  }*))
; line 1 ?1+1
    call void @llvm.dbg.stoppoint (i32 1, i32 0, {  }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to {  }*))
    %x = add i32 1, 1
    %format1 = getelementptr [3 x i8]* @format, i64 0, i64 0
    call i32 (i8*, ...)* @printf(i8* %format1, i32 %x)
; line 2 end
    call void @llvm.dbg.stoppoint (i32 2, i32 0, {  }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to {  }*))
; end
    call void @llvm.dbg.region.end ({  }* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram to {  }*))
    ret i32 0
}

断っておきますが、LLVM用BASICコンパイラが実在するわけでもなんでもなくて、ハンドアセンブルならぬハンドコンパイルです。

...>llvm-db a.bc
NOTE: llvm-db is known useless right now.
llvm-db: The LLVM source-level debugger
Loading program... successfully loaded 'aa.bc'!
(llvm-db) b main
Error: Program contains no debugging information!
(llvm-db) run
Starting program: a.bc
Error: No supported binding to inferior processes (debugger not implemented).

llvm-dbは、.exeとして存在するだけでnot implementedのようです。
しかし我々にはgdbというよく落ちて使い物にならない素晴らしいデバッガがあります。

C:\mingw\home>..\insight\bin\gdb.exe a.exe
GNU gdb 6.6
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-mingw32"...
(gdb) run
Starting program: C:\mingw\home/a.exe
Loaded symbols for C:\WINNT\system32\KERNEL32.DLL
Loaded symbols for C:\WINNT\system32\msvcrt.dll
2
Program exited with code 017777370000.
(gdb) b main
Breakpoint 1 at 0x401340
(gdb) run
Starting program: C:\mingw\home/a.exe

error return ../../../../insight-6.6-mingw/gdb/win32-nat.c:1439 was 6

error return ../../../../insight-6.6-mingw/gdb/win32-nat.c:1439 was 6
Loaded symbols for C:\WINNT\system32\KERNEL32.DLL
Loaded symbols for C:\WINNT\system32\msvcrt.dll
error return ../../../../insight-6.6-mingw/gdb/win32-nat.c:1439 was 6

Program received signal SIGTRAP, Trace/breakpoint trap.
0x77f85ead in ?? ()
(gdb) start
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Breakpoint 2 at 0x401340
Starting program: C:\mingw\home/a.exe
Loaded symbols for C:\WINNT\system32\KERNEL32.DLL
Warning:
Cannot insert breakpoint 1.
Error accessing memory address 0x401340: Input/output error.

(gdb)

壮絶にデバッグ情報がぶっ壊れていますねこれは。
insightで見てみますと、main関数とa.basは共に列挙はされるのですが、このふたつが結びついていないことが確認できます。
実際これは私のせいではなくて、次のようなコードをllvm-gccに喰わせても全く同じです。
a.c

#include<stdio.h>
int main()
{
	printf("%d",1+1);
}

しかも、llcが出力した.sが.secrel32の使い方を間違っていて、asが通りません。

	.long		.secrel32	abbrev_begin

これが正しい。

	.secrel32	Labbrev_begin

結論として、現状LLVM向けにフロントエンドを書いてもデバッガが使えません。
よくこんなのでバージョン2.0を名乗ってるな?LLVM……。
バックエンドとしてのスタンスは、他のどれよりも正しいと思えるだけに残念です。今月出る2.1に期待ですね。
おまけ。LLVMはMSILもサポートしています。もしかしてこれが一番まともにデバッグできるターゲットでは……と思えたので-march=msilを指定。

C:\mingw\home>llc -march=msil a.bc
: CommandLine Error: Argument 'mattr' defined more than once!
: CommandLine Error: Argument 'mcpu' defined more than once!
: CommandLine Error: Argument 'march' defined more than once!
llc: CommandLine Error: Argument 'mattr' defined more than once!
llc: CommandLine Error: Argument 'mcpu' defined more than once!
llc: CommandLine Error: Argument 'march' defined more than once!
Assertion failed: 0 && "Module use not supporting pointer size", file MSILWriter
.cpp, line 407

abnormal program termination