- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一段时间正在尝试 LLVM , 仅仅是因为。然而,它确实比我想象的花费了更多的时间。
我曾涉足 C++ 绑定(bind),但几年前我出于显而易见的原因离开了 C++。我尝试了 OCaml 绑定(bind),但我不喜欢 OCaml,主要是因为它存在繁琐的构建系统以及其他问题。
所以我被 LLVM module for Haskell 困住了,它非常类型安全并且感觉非常 Haskell。但文档有些缺乏,因为唯一的例子是一些 Blog 中的例子。 .
简而言之,我已经开始为 PL/0 做一个简单的编译器。 。经过两天的奉献,我已经解决了这个问题(解析器没问题,秒差距是我的 friend ):
AST 模块
module AST where
data Statement
= Assign String Expression
| Call String
| Write String
| If Condition Statement
| While Condition Statement
| Begin [Statement]
deriving (Show, Eq)
data Condition
= Odd Expression
| Eq Expression Expression
| Ne Expression Expression
| Gt Expression Expression
| Lt Expression Expression
| Ge Expression Expression
| Le Expression Expression
deriving (Show, Eq)
data Expression
= Identifier String
| Number Integer
| Plus Expression Expression
| Minus Expression Expression
| Multiply Expression Expression
| Divide Expression Expression
deriving (Show, Eq)
data Block = Block {
blockConsts :: [(String, Integer)],
blockVars :: [String],
blockProcs :: [Procedure],
blockStatement :: Statement
}
deriving (Show, Eq)
data Procedure = Procedure String Block
deriving (Show, Eq)
代码生成模块:
module Codegen {-(writeModule)-} where
import LLVM.Core
import AST
import Data.Int (Int64)
import Data.Word (Word8, Word32)
codegenExpr :: [(String, Value (Ptr Int64))] -> Expression -> CodeGenFunction r (Value Int64)
codegenExpr ls (Identifier s) = case lookup s ls of
Nothing -> error $ "unknown identifier: " ++ s
(Just v) -> load v
codegenExpr _ (Number n) = return $ valueOf $ fromIntegral n
codegenExpr ls (Plus e1 e2) = arith ls e1 e2 iadd
codegenExpr ls (Minus e1 e2) = arith ls e1 e2 isub
codegenExpr ls (Multiply e1 e2) = arith ls e1 e2 imul
codegenExpr ls (Divide e1 e2) = arith ls e1 e2 idiv
arith ls e1 e2 f = do
lhs <- codegenExpr ls e1
rhs <- codegenExpr ls e2
f lhs rhs
codegenCond :: [(String, Value (Ptr Int64))] -> Condition -> CodeGenFunction r (Value Bool)
codegenCond ls (Eq e1 e2) = cnd ls e1 e2 CmpEQ
codegenCond ls (Ne e1 e2) = cnd ls e1 e2 CmpNE
codegenCond ls (Gt e1 e2) = cnd ls e1 e2 CmpGT
codegenCond ls (Lt e1 e2) = cnd ls e1 e2 CmpLT
codegenCond ls (Ge e1 e2) = cnd ls e1 e2 CmpGE
codegenCond ls (Le e1 e2) = cnd ls e1 e2 CmpLE
cnd ls e1 e2 f = do
lhs <- codegenExpr ls e1
rhs <- codegenExpr ls e2
cmp f lhs rhs
codegenStatement :: [(String, Value (Ptr Int64))] -> Statement -> CodeGenFunction () ()
codegenStatement ls (Assign id e) = case lookup id ls of
Nothing -> error $ "unknown identifier: " ++ id
(Just v) -> do
val <- codegenExpr ls e
store val v
codegenStatement ls (Begin stmts) = mapM_ (codegenStatement ls) stmts
codegenStatement ls (If cond s1) = do
ifbl <- newBasicBlock
thenbl <- newBasicBlock
cnd <- codegenCond ls cond
condBr cnd ifbl thenbl
defineBasicBlock ifbl
codegenStatement ls s1
ret ()
defineBasicBlock thenbl
ret ()
codegenStatement ls (While cond s) = do
exit <- newBasicBlock
while <- newBasicBlock
defineBasicBlock while
cnd <- codegenCond ls cond
codegenStatement ls s
condBr cnd while exit
defineBasicBlock exit
ret ()
codegenBlock :: [(String, Value (Ptr Int64))] -> Block -> CodeGenModule (Function ())
codegenBlock vls (Block _ vars _ stmt) = do
-- And here is the type error
func <- createFunction ExternalLinkage $ do
ls <- mapM named vars
codegenStatement (vls ++ ls) stmt
mapM_ (free . snd) ls
return func
where
named n = do
v <- alloca
return (n, v)
writeModule bl file = do
m <- newModule
defineModule m $ codegenBlock [] bl
writeBitcodeToFile file m
是的,代码很多,但很完整。我得到的类型错误是这样的:
GHCi, version 7.0.3: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
[1 of 2] Compiling AST ( AST.hs, interpreted )
[2 of 2] Compiling Codegen ( Codegen.hs, interpreted )
Codegen.hs:71:13:
No instances for (IsFunction (),
FunctionArgs () (CodeGenFunction () ()) (CodeGenFunction r0 ()))
arising from a use of `createFunction'
Possible fix:
add instance declarations for
(IsFunction (),
FunctionArgs () (CodeGenFunction () ()) (CodeGenFunction r0 ()))
In the expression: createFunction ExternalLinkage
In a stmt of a 'do' expression:
func <- createFunction ExternalLinkage
$ do { ls <- mapM named vars;
codegenStatement (vls ++ ls) stmt;
mapM_ (free . snd) ls }
In the expression:
do { func <- createFunction ExternalLinkage
$ do { ls <- mapM named vars;
codegenStatement (vls ++ ls) stmt;
.... };
return func }
正如我所说,我已经从提到的 block 中获取了大部分示例,并且它是这样写的。我不知何故不知道如何解决这个问题。
一如既往,我花在满足类型检查器上的时间比编写新代码的时间更多。
最佳答案
我对 LLVM 一点也不熟悉,所以我不知道它是否有意义,但是将 codegenBlock
的类型签名更改为
[(String, Value (Ptr Int64))] -> Block -> CodeGenModule (Function ())
至
[(String, Value (Ptr Int64))] -> Block -> CodeGenModule (Function (IO ()))
满足类型检查器的要求,因为没有实例 IsFunction ()
,但有一个 IsFunction (IO a)
。
关于haskell - 使用 LLVM/Haskell 的 CodeGenFunction/CodeGenModule 的类型问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6050721/
我有一段时间正在尝试 LLVM , 仅仅是因为。然而,它确实比我想象的花费了更多的时间。 我曾涉足 C++ 绑定(bind),但几年前我出于显而易见的原因离开了 C++。我尝试了 OCaml 绑定(b
我是一名优秀的程序员,十分优秀!