Haskell 无法跨LLVM或JIT中的模块访问符号

Haskell 无法跨LLVM或JIT中的模块访问符号,haskell,compiler-construction,llvm,jit,llvm-ir,Haskell,Compiler Construction,Llvm,Jit,Llvm Ir,我正在使用haskell、llvmhs和OrcJIT编写一个JIT编译器。这是我的主文件,它编译模块,将模块添加到JIT,获取并运行内部主要函数: main::IO() 主要= withContext$\ctx-> withExecutionSession$\es-> withHostTargetMachine Reloc.PIC CodeModel.Default CodeGenOpt.None$\tm-> 使用SymbolResolver es myResolver$\psr-> withO

我正在使用haskell、llvmhs和OrcJIT编写一个JIT编译器。这是我的主文件,它编译模块,将模块添加到JIT,获取并运行内部主要函数:

main::IO()
主要=
withContext$\ctx->
withExecutionSession$\es->
withHostTargetMachine Reloc.PIC CodeModel.Default CodeGenOpt.None$\tm->
使用SymbolResolver es myResolver$\psr->
withObjectLinkingLayer es(\\ u->返回psr)$\oll->
使用iCompileLayer oll tm$\iRL->do
LoadLibrary无任何内容
repl ctx es tm ircl
哪里
myResolver::SymbolResolver
myResolver=SymbolResolver$\mangled->do
ptr ExecutionSession->TargetMachine->iCompileLayer ObjectLinkingLayer->IO()
repl ctx es tm cl=runinput defaultSettings(循环C.initCmpState)
哪里
循环::C.CmpState->输入IO()
循环状态=
getInputLine“%”>=\minput->case minput of
无->返回()
只需“q”->返回()
只需输入->liftIO(进程状态输入)>>=循环
进程::C.CmpState->String->IO C.CmpState
进程状态源=
案例L.1.来源
左errStr->putStrLn errStr>>返回状态
右令牌->大小写(P.parseTokens-tokens)0
P.ParseOk ast->
let(res,state')=C.codeGen状态(head ast)in
案件
左错误->putStrLn(显示错误)>>返回状态
Right()->runDefinition(状态{C.externs=C.externs state})>>返回状态'
{C.globals=Map.empty
,C.说明=[]
}
运行定义::C.CmpState->IO()
rundefinitionstate=do
设globals=Map.elems(C.globals状态)
设externs=Map.elems(C.externs状态)
让指令=反向(C.指令状态)
让mainName=mkBSS“main.0”
让mainFn=GlobalDefinition$functionDefaults
{returnType=void
,name=name mainName
,BasicBlock=[BasicBlock(mkName“entry”)指令(Do$Ret Nothing[])]
}
案例说明
[]->do
设astmod=defaultModule
{moduleDefinitions=externs++globals
}
M.withModuleFromAST ctx astmod$\mod->do
理学士=
添加模块cl modKey mod
x->do
设astmod=defaultModule
{moduleDefinitions=externs++globals++[mainFn]
}
M.withModuleFromAST ctx astmod$\mod->do
理学士=
使用模块cl modKey mod$do
res findSymbol cl mangled False)=putStrLn(“找不到:”++显示mainName)
右(JIT符号fn)->do
运行$castprtofunptr(wordptrtofn)
诸如此打印语句之类的独立模块运行正常。具有主功能的模块在执行后将从JIT中删除:

print(234);

; ModuleID = '<string>'
source_filename = "<string>"

@0 = constant [4 x i8] c"%d\0A\00"

declare i32 @printf(i8*, ...)

define void @main.0() {
entry:
  %0 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @0, i32 0, i32 0), i32 234)
  ret void
}

234
打印(234);
; ModuleID=''
source_filename=“”
@0=常数[4 x i8]c“%d\0A\00”
声明i32@printf(i8*,…)
定义void@main.0(){
条目:
%0=调用i32(i8*,…)@printf(i8*getelementptr inbounds([4 x i8],[4 x i8]*@0,i32 0,i32 0),i32 234)
ret void
}
234
将4分配给符号“x”会导致一个具有全局变量的模块,此模块不会从JIT中删除:

x := 4;

; ModuleID = '<string>'
source_filename = "<string>"

@x = global i32 4
x:=4;
; ModuleID=''
source_filename=“”
@x=全局i32 4
但尝试在下一条语句中打印“x”会导致主函数的查找失败:

print(x);

; ModuleID = '<string>'
source_filename = "<string>"

@x = external global i32
@0 = constant [4 x i8] c"%d\0A\00"

declare i32 @printf(i8*, ...)

define void @main.0() {
entry:
  %0 = load i32, i32* @x
  %1 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @0, i32 0, i32 0), i32 %0)
  ret void
}

Couldn't find: "main.0"
打印(x);
; ModuleID=''
source_filename=“”
@x=外部全局i32
@0=常数[4 x i8]c“%d\0A\00”
声明i32@printf(i8*,…)
定义void@main.0(){
条目:
%0=负载i32,i32*@x
%1=调用i32(i8*,…)@printf(i8*getelementptr inbounds([4 x i8],[4 x i8]*@0,i32 0,i32 0),i32%0)
ret void
}
找不到:“main.0”
似乎在跨模块访问符号时出现问题

我尝试过的事情:

  • 访问函数而不是变量
  • 将我的符号解析器更改为使用“findSymbol”而不是llvm hs示例repo中的“getSymbolAddressInProcess”。这会阻止任何模块运行
  • 下载llvm hs示例repo并运行“orc”示例这也导致了符号错误
  • 在新的linux安装上重新下载haskell工具链和llvm/llvm hs(9.0.1)

如果有任何帮助,我将不胜感激

解决了!我被符号分解器弄糊涂了。在使用“findSymbol”时,它不用于检索符号,而是在JIT的编译和链接阶段getSymbolAddressInProcess'将仅搜索主机进程内的符号(如printf),而不是JIT内定义的符号(如x)

为了在JIT中使用从另一个模块检索外部符号“x”和从主机进程检索“printf”的模块,必须添加一个符号解析程序,该解析程序在JIT编译层和主机进程中搜索符号:

myResolver :: IRCompileLayer ObjectLinkingLayer -> SymbolResolver
myResolver ircl = SymbolResolver $ \mangled -> do
    symbol <- findSymbol ircl mangled False
    case symbol of
        Right _ -> return symbol
        Left _ -> do
            ptr <- getSymbolAddressInProcess mangled
            return $ Right $ JITSymbol
                { jitSymbolAddress = ptr 
                , jitSymbolFlags   = defaultJITSymbolFlags { jitSymbolExported = True }
                }
myResolver::IRCompileLayer ObjectLinkingLayer->SymbolResolver
myResolver ircl=SymbolResolver$\mangled->do
符号返回符号
左->做
ptr可能有用吗?这是一个来自内部模块的