从调用外部函数返回LLVM是错误的

时间:2014-01-12 12:50:02

标签: llvm-ir

我正在尝试使用LLVM并打一些墙,就像这样。 当我编译并运行下面的代码时,而不是获得当前年份,我得到了一周中的那一天:

target datalayout = "e"

declare dllimport x86_stdcallcc void @GetLocalTime(%SYSTEMTIME*)

%SYSTEMTIME = type {
    i16, ; wYear
    i16, ; wMonth
    i16, ; wDayOfWeek
    i16, ; wDay
    i16, ; wHour
    i16, ; wMinute
    i16, ; wSecond
    i16  ; wMilliseconds
}

define i32 @main() {
    %now = alloca %SYSTEMTIME
    call void @GetLocalTime(%SYSTEMTIME* %now)
    %ptr = getelementptr %SYSTEMTIME* %now, %i32 0, %i32 0
    %day = load i16* %ptr
    %int = zext i16 %day to i32
    ret i32 %int
}

请注意,我不是在编写C或C ++代码,我正在编写上面的代码。 有人能指出我做错了吗? SYSTEMTIME的所有成员似乎都被2个职位关闭......

2 个答案:

答案 0 :(得分:1)

你写道:

  

SYSTEMTIME的所有成员似乎都被2个职位拒绝......

这可能是错误对齐造成的。特别是,您在堆栈上分配结构,而LLVM默认数据布局不指定堆栈对齐,而Windows 32位requires 4 bytes。要满足此要求,请将S32添加到数据布局字符串(或者S128,我想,对于64位Windows。)

为了验证这一点,我检查了Clang在我的Windows系统上插入了什么数据布局字符串,实际上你最后可以看到S32

"e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S32"

答案 1 :(得分:0)

你声明:

declare dllimport x86_stdcallcc void @GetLocalTime(%SYSTEMTIME*)

这是绝对正确的;但是当你打电话给它时:

call void @GetLocalTime(%SYSTEMTIME* %now)

您忘记了x86_stdcallcc调用约定。来自the documentation of call

  

调用的调用约定必须与目标函数的调用约定匹配,否则行为未定义。

所以也许添加cc会解决这个问题。