Generating x86 assembly with Haskell

code 4 November 2008 | 3 Comments

A quick and dirty example:

data Exp = Lit Int -- literal value
	| Call String Exp -- calling a function
	| Bin BinOp Exp Exp -- binary operations
	| Param -- the parameter
	deriving (Show,Eq)
 
data Function = Func String Exp -- a function has a name and expression
data BinOp = Add | Subtract | Multiply | Divide deriving(Show,Eq)
 
-- an instance to allow us to write nicer definitions
instance Num Exp where
	x * y = Bin Multiply x y
	x - y = Bin Subtract x y
	x + y = Bin Add x y
	fromInteger x = Lit (fromInteger x)
 
outFunc (Func name it) = name ++ -- output function name
	":\npush ebp\nmov ebp,esp\n" ++ -- save old stack frame
	output it ++ -- output function
	"pop eax\npop ebp\n" ++ -- restore old stack frame
	"ret 4\n\n" -- remove argument from stack and return
 
output (Bin op l r) = outBin op l r -- binary operations
output (Lit x) = "push dword " ++ show x ++ "\n" -- push literal
output (Param) = "push dword [ebp+8]\n" -- push parameter
output (Call name with) = output with ++
	"call " ++ name ++
	"\npush eax\n" -- put return value onto stack
 
outBin Add = outBinGen "add"
outBin Subtract = outBinGen "sub"
outBin Multiply = outBinGen "imul"
outBin Divide = outBinGen "idiv"
 
outBinGen op l r = output l ++ output r ++
	"pop ebx\npop eax\n" ++ op ++ " eax,ebx\npush eax\n"

And an example of using it:

main = putStr $ concatMap outFunc [double,quad]
double = Func "double" (Param * 2)
quad = Func "quad" (Call "double" (2*Param))

This example outputs:

double:
	push ebp
	mov ebp,esp
	push dword [ebp+8]
	push dword 2
	pop ebx
	pop eax
	imul eax,ebx
	push eax
	pop eax
	pop ebp
	ret 4
 
quad:
	push ebp
	mov ebp,esp
	push dword 2
	push dword [ebp+8]
	pop ebx
	pop eax
	imul eax,ebx
	push eax
	call double
	push eax
	pop eax
	pop ebp
	ret 4

Not the most efficient code in the world The calling convention is somewhat ad-hoc; the callee must remove its arguments from the stack and returns its value in eax.

Tagged in , , ,

3 Responses on “Generating x86 assembly with Haskell”

  1. Andy says:

    Hi George – this is a great bit of code!
    I’m just starting to get into poking around with compilers, and I’m looking at doing a public-domain compiler for a small FP language. Given that, it’s possible that I may look at using some of this code.
    So I was just wondering – is this code basically P.D.? (In other words, “use as you like, but attribution is appreciated”?) If I do use any of it, I’ll certainly give aknowledgement to you!
    Looking forward to hearing from you – bye for now!
    - Andy

  2. Porges says:

    Hi Andy,

    You can consider this PD

    In general, everything on this blog is under a Creative Commons BY-NC-SA license. I used to have this noted but it seems to have disappeared

  3. Andy says:

    Great! Thanks very much, George!
    Keep up the good work – this kind of post is really interesting!
    Bye for now –
    - Andy

Leave a Reply