Mercurial > repos > rhope
diff genasm.rhope @ 2:73e978d590c7
Adding WIP compiler code
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Wed, 29 Apr 2009 02:58:03 -0400 |
parents | |
children | 31f8182f3433 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/genasm.rhope Wed Apr 29 02:58:03 2009 -0400 @@ -0,0 +1,940 @@ +//Import extendlib.rhope +Escape Rhope Name[name:escaped] +{ + escaped <- [[[[[[[[[name]Replace["_","__"] + ]Replace["@","_AT_"] + ]Replace[" ","_SP_"] + ]Replace[":","_CN_"] + ]Replace["?","_QN_"] + ]Replace["+","_PL_"] + ]Replace["-","_MN_"] + ]Replace["*","_TM_"] + ]Replace["/","_DV_"] +} + +Blueprint Registers +{ + Names + Can Data + Can Pointer + Available? + Need Save + Max Size +} + +Set Yes[in:out] +{ + out <- Yes +} + +_Flip[dest,val,index:out] +{ + out <- [dest]Set[val,index] +} +Flip[list,dest:out] +{ + out <- Fold["_Flip", dest, list] +} + +Registers[names, data, pointer, need save, max size:out] +{ + out <- [[[[[[Build["Registers"] + ]Names << [names] + ]Can Data << [data] + ]Can Pointer << [pointer] + ]Available? << [ Map[names, "Set Yes"] ] + ]Need Save << [ Flip[need save, ()] ] + ]Max Size <<[max size] +} + +Name@Registers[regs,num:out] +{ + out <- [[regs]Names >>]Index[num] +} + +Allocate Helper@Registers[regs, try, current:found, not found] +{ + reg <- [try]Index[current] + If[[[regs]Available? >>]Index[reg]] + { + found <- Val[reg] + }{ + [try]Next[current] + { + found, not found <- [regs]Allocate Helper[try, ~] + }{ + not found <- Yes + } + } +} + +Allocate Reg@Registers[regs,try:next regs,found,need save?,not found] +{ + [try]First + { + found, not found <- [regs]Allocate Helper[try, ~] + { + next regs <- [regs]Available? << [ [[regs]Available? >>]Set[~, No] ] + [[regs]Need Save >>]Index[~] + { + need save? <- Yes + }{ + need save? <- No + } + } + }{ + not found <- Yes + } +} + +Free Reg@Registers[regs,num:out] +{ + out <- [regs]Available? <<[ [[regs]Available? >>]Set[num, Yes] ] +} + +Processor Reg[func,type:next func,num,not found] +{ + regs <- [func]Registers >> + If[[type] = ["pointer"]] + { + source <- [regs]Can Pointer >> + }{ + source <- [regs]Can Data >> + } + next regs, reg num, need save?, not found <- [regs]Allocate Reg[source] {} + { + If[need save?] + { + next func <- [[func]Need Save << [ [[func]Need Save >>]Set[reg num, Yes] ] + ]Registers << [next regs] + }{ + next func <- [func]Registers << [next regs] + } + num <- Val[reg num] + } +} + +Processor Free Reg[func,num:out func] +{ + out func <- [func]Registers <<[ [[func]Registers >>]Free Reg[num] ] +} + +Processor Allocate[func,name,size,type:out func,out] +{ + regs <- [func]Registers >> + If[[type] = ["pointer"]] + { + alloc size <- [func]Pointer Size + }{ + alloc size <- size + } + If[[alloc size] > [[regs]Max Size >>]] { + stack alloc <- Val[alloc size] + }{ + next func <- [func]Processor Reg[type] {} + { + location <- Register[~, alloc size] + }{ + stack alloc <- Val[alloc size] + } + } + Val[stack alloc] + { + next func, location <- [func]Allocate Stack[alloc size] + } + out func <- [next func]Variables <<[ [[next func]Variables >>]Set[name, location] ] + out <- Val[location] +} + +Blueprint Register +{ + Number + Value Size +} +Register[num,size:out] +{ + If[[size] = [3]] + { + value size <- 4 + }{ + value size <- size + } + out <- [[Build["Register"]]Number <<[num]]Value Size <<[value size] +} + +In Memory?@Register[reg:out] +{ + out <- No +} + +=@Register[reg,other:out] +{ + ,out <- If[[Type Of[reg]] = [Type Of[other]]] + { + out <- [[reg]Number >>] = [[other]Number >>] + } +} + +Op ASM@Register[reg,func,regs,extra offset:out] +{ + out <- [regs]Index[ [reg]Number >> ] +} + +Size@Register[reg:out] +{ + out <- [reg]Value Size >> +} + +Blueprint Immediate +{ + Value +} + +Immediate[val:out] +{ + out <- [Build["Immediate"]]Value <<[val] +} + +In Memory?@Immediate[val:out] +{ + out <- No +} + +=@Immediate[val,other:out] +{ + ,out <- If[[Type Of[val]] = [Type Of[other]]] + { + out <- [[val]Value >>] = [[other]Value >>] + } +} + +Op ASM@Immediate[val,func,regs,extra offset:out] +{ + out <- [val]Value >> +} + +Size@Immediate[val:out] +{ + out <- 4 +} + +Blueprint None +{ + Dummy +} + +None[:out] +{ + out <- Build["None"] +} + +In Memory?@None[none:out] +{ + out <- No +} + +Op ASM@None[none,func,regs,extra offset:out] +{ + out <- "" +} + +Size@None[none:out] +{ + out <- 0 +} + +Blueprint Stack Location +{ + Offset + Size +} + +Stack Location[offset,size:out] +{ + out <- [[Build["Stack Location"]]Offset <<[offset]]Size <<[size] +} + +In Memory?@Stack Location[location:out] +{ + out <- Yes +} + +=@Stack Location[loc,other:out] +{ + ,out <- If[[Type Of[loc]] = [Type Of[other]]] + { + out <- [[loc]Offset >>] = [[other]Offset >>] + } +} + +Op ASM@Stack Location[loc,func,regs,extra offset:out] +{ + offset <- [[[func]Stack Size >>] - [[loc]Offset >>]] - [[loc]Size >>] + If[[offset] > [0]] + { + toffset <- ["+"]Append[offset] + }{ + toffset <- "" + } + out <- [["[esp"]Append[toffset]]Append["]"] +} + +Size@Stack Location[loc:out] +{ + out <- [loc]Size >> +} + +Blueprint Pointer +{ + Base + Offset + Target Size +} + +Pointer[base,offset,size:out] +{ + out <- [[[Build["Pointer"]]Base <<[base]]Offset <<[offset]]Target Size <<[size] +} + +In Memory?@Pointer[location:out] +{ + out <- Yes +} + +=@Pointer[pointer,other:out] +{ + ,out <- If[[Type Of[loc]] = [Type Of[other]]] + { + out <- [[loc]Storage >>] = [[other]Storage >>] + } +} + +Op ASM@Pointer[pointer,func,regs,extra offset:out] +{ + If[[Type Of[ [pointer]Offset >> ]] = ["None"]] + { + out <- [["["]Append[ [[pointer]Base >>]Op ASM[func,regs,extra offset] ]]Append["]"] + }{ + out <- [[[["[" + ]Append[ [[pointer]Base >>]Op ASM[func,regs,extra offset] ] + ]Append["+"] + ]Append[ [[pointer]Offset >>]Op ASM[func,regs,extra offset] ] + ]Append["]"] + } +} + +Size@Pointer[pointer:out] +{ + out <- [pointer]Target Size >> +} + +Blueprint X86 Instruction +{ + Name + Op1 + Op2 + Width + Extra Offset +} + +X86 Instruction[name, op1, op2, width:out] +{ + out <- [[[[[Build["X86 Instruction"]]Name << [name]]Op1 << [op1]]Op2 <<[op2]]Width <<[width]]Extra Offset <<[0] +} + +CAppend[left,right:out] +{ + If[[right] = [""]] + { + out <- "" + }{ + out <- [left]Append[right] + } +} + +Inst ASM@X86 Instruction[inst,func:out] +{ + If[[[inst]Width >>] = [4]] + { + regs <- ("eax","ecx","edx","ebx","esi","edi","esp") + }{ + If[[[inst]Width >>] = [2]] + { + regs <- ("ax","cx","dx","bx","si","di") + }{ + regs <- ("al","cl","dl","bl","si","di") + } + } + out <- [[[inst]Name >> + ]Append[ [" "]CAppend[[[inst]Op1>>]Op ASM[func, regs, [inst]Extra Offset >>]] ] + ]Append[ [", "]CAppend[[[inst]Op2>>]Op ASM[func, regs, [inst]Extra Offset >>]] ] +} + +Blueprint X86 Function +{ + Name + Registers + Variables + Scratch + Need Save + Free Stack Locations + Stack Size + Param Size + Temp Stack + Convention + Instructions +} + +X86 Function[name,params,convention:out] +{ + [[[[[[[[[Build["X86 Function"] + ]Name << [name] + ]Registers << [Registers[("eax","ecx","edx","ebx","esi","edi"), (0,1,2,3,4,5), (0,1,2,3,4,5), (3,4,5), 4]] + ]Variables <<[New@Dictionary[]] + ]Need Save <<[()] + ]Free Stack Locations <<[()] + ]Stack Size <<[0] + ]Instructions <<[()] + ]Convention <<[convention] + ]Alloc Params[params, convention] + { + out <- [~]Param Size <<[ [~]Stack Size >> ] + } +} + +Pointer Size@X86 Function[func:out] +{ + out <- 4 +} + +Param Helper@X86 Function[func, param:out] +{ + ,loc <- [func]Allocate Stack[4] + { + out <- [~]Variables << [ [[~]Variables >>]Set[param, loc] ] + } +} + +Alloc Params@X86 Function[func,params,convention:out] +{ + If[[convention] = ["fastcall"]] + { + [params]Index[0] + { + next func <- [[func]Registers <<[ [[func]Registers >>]Available? <<[ [[[func]Registers >>]Available? >>]Set[1, No] ]] + ]Variables <<[ [[func]Variables >>]Set[~, Register[1,4]] ] + [params]Index[1] + { + next func2 <- [[next func]Registers <<[ [[next func]Registers >>]Available? <<[ [[[next func]Registers >>]Available? >>]Set[2, No] ]] + ]Variables <<[ [[next func]Variables >>]Set[~, Register[2,4]] ] + [params]Index[2] + { + out <- _Fold[params, 2, next func2, "Param Helper"] + }{ + out <- Val[next func2] + } + }{ + out <- Val[next func] + } + }{ + out <- func + } + }{ + out <- Fold["Param Helper", func, params] + } +} + +Add Instruction@X86 Function[func, inst:out] +{ + out <- [func]Instructions << [ [[func]Instructions >>]Append[ [inst]Extra Offset <<[[func]Temp Stack >>] ] ] +} + +Allocate Stack@X86 Function[func,size:func out,out] +{ + out <- Stack Location[[func]Stack Size >>, size] + func out <- [func]Stack Size <<[ [[func]Stack Size >>]+[size] ] +} + +Allocate Var@X86 Function[func,name,size,type:out func,out] +{ + out func, out <- Processor Allocate[func,name,size,type] +} + +Resolve@X86 Function[func,op:out,out func] +{ + If[[Type Of[op]] = ["String"]] + { + out <- [[func]Variables >>]Index[op] + }{ + out <- op + } +} + +Allocate Scratch@X86 Function[func,size:out func,scratch] +{ + out func,scratch <- Processor Reg[func,"data"] {} {} + { + //FIXME: need to use a reg that's not involved in the current op + //FIXME: Also, might need two scratch regs and both might be in use + ,stack inc <- [func]Save Reg[0] + { + out func <- [~]Scratch << [ [[~]Scratch >>]Set[0, Yes] ] + } + } +} + +Free Scratch@X86 Function[func,scratch:out func] +{ + [[func]Scratch >>]Index[scratch] + { + [func]Restore Reg[scratch] + { + out func <- [~]Scratch << [ [[~]Scratch >>]Remove[scratch] ] + } + }{ + out func <- Processor Free Reg[func, scratch] + } + If[[scratch]Index[1]] + { + + }{ + + } +} + +Classify Op@X86 Function[func,op:class] +{ + If[[op]In Memory?] + { + If[[Type Of[op]] = ["Pointer"]] + { + If[[[[op]Base >>]In Memory?] Or [[[op]Offset >>]In Memory?]] + { + class <- "u" + }{ + class <- "m" + } + }{ + class <- "m" + } + }{ + class <- "r" + } +} + +RegMem2Op@X86 Function[func,dest,notdest,op,size:out] +{ + out <- [func]Add Instruction[X86 Instruction[op, dest, notdest, size]] +} + +MemPointer2Op@X86 Function[func,dest,notdest,op,size:out] +{ + ,scratch <- [func]Allocate Scratch[size] + { + out <- [[[~]Fetch[notdest,scratch] + ]Add Instruction[X86 Instruction[op, dest, scratch, size]] + ]Free Scratch[scratch] + } +} + +//Make sure to map this to both r, (m or r) -> m and r, (m or r) -> r +RegMemToNotPointer@X86 Function[func,source1,source2,dest,op,size:out] +{ + out <- [[func]Move[source2,dest] + ]Add Instruction[X86 Instruction[op, dest, source1, size]] +} + +RegMemToPointer@X86 Function[func,source1,source2,dest,op,size:out] +{ + ,scratch <- [func]Allocate Scratch[size] + { + spointer <- Pointer[scratch, None[], size] + out <- [[[[~]Calculate Address[dest, scratch] + ]Move[source2, spointer] + ]Add Instruction[X86 Instruction[op, spointer, source1, size]] + ]Free Scratch[scratch] + } +} + +RegPointerToMem@X86 Function[func,source1,source2,dest,op,size:out] +{ + ,scratch <- [func]Allocate Scratch[size] + { + spointer <- Pointer[scratch, None[], size] + out <- [[[[~]Calculate Address[source2, scratch] + ]Move[spointer, dest] + ]Add Instruction[X86 Instruction[op, dest, source1, size]] + ]Free Scratch[scratch] + } +} + +RegPointerReg2Op@X86 Function[func,dest,notdest,op,size:out] +{ + ,scratch <- [func]Allocate Scratch[size] + { + spointer <- Pointer[scratch, None[], size] + out <- [[[~]Calculate Address[notdest, scratch] + ]Add Instruction[X86 Instruction[op, dest, spointer, size]] + ]Free Scratch[scratch] + } +} + +RegPointerPointer2Op@X86 Function[func,dest,notdest,op,size:out] +{ + ,scratch <- [func]Allocate Scratch[size] + { + spointer <- Pointer[scratch, None[], size] + out <- [[[~]Calculate Address[dest, scratch] + ]Add Instruction[X86 Instruction[op, spointer, notdest, size]] + ]Free Scratch[scratch] + } +} + +RegPointerToPointer@X86 Function[func,source1,source2,dest,op,size:out] +{ + ,scratch <- [func]Allocate Scratch[size] + { + spointer <- Pointer[scratch, None[], size] + ,scratch2 <- [~]Allocate Scratch[size] + { + spointer2 <- Pointer[scratch2, None[], size] + out <- [[[[[[~]Calculate Address[source2, scratch] + ]Calculate Address[dest, scratch2] + ]Move[spointer2, spointer] + ]Add Instruction[X86 Instruction[op, spointer2, source1, size]] + ]Free Scratch[scratch2] + ]Free Scratch[scratch] + } + } +} + +//If source1, source2 and dest are all pointers with register offsets, allocating a scratch register could +//become a problem unless I let ebp be used as a scratch register. Should be doable as long as thread local +//variables properly report ebp as a used register. Alternatively, one register could be reserved for scratch +//usage +MemPointerToMem@X86 Function[func,source1,source2,dest,op,size:out] +{ + ,scratch <- [func]Allocate Scratch[size] + { + out <- [[[[~]Fetch[source2, scratch] + ]Add Instruction[X86 Instruction[op, scratch, source1, size]] + ]Move[scratch, dest] + ]Free Scratch[scratch] + } +} + +MemPointerToPointer@X86 Function[func,source1,source2,dest,op,size:out] +{ + ,scratch <- [func]Allocate Scratch[size] + { + ,scratch2 <- [~]Allocate Scratch[size] + { + spointer2 <- Pointer[scratch2, None[], size] + out <- [[[[[[~]Fetch[source2, scratch] + ]Add Instruction[X86 Instruction[op, scratch, source1, size]] + ]Calculate Address[dest, scratch2] + ]Move[scratch, spointer2] + ]Free Scratch[scratch2] + ]Free Scratch[scratch] + } + } +} + +//This does almost the same thing as RegMemToNotPointer, depending on how I do the pattern matching I could maybe combine them +PointerMemToReg@X86 Function[func,source1,source2,dest,op,size:out] +{ + out <- [[func]Fetch[source1,dest] + ]Add Instruction[X86 Instruction[op, dest, source2, size]] +} + +PointerPointer2Op@X86 Function[func,dest,notdest,op,size:out] +{ + ,scratch <- [func]Allocate Scratch[size] + { + spointer <- Pointer[scratch, None[], size] + ,scratch2 <- [~]Allocate Scratch[size] + { + out <- [[[[[[[~]Calculate Address[dest, scratch] + ]Fetch[notdest, scratch2] + ]Add Instruction[X86 Instruction[op, scratch, scratch2, size]] + ]Calculate Address[dest, scratch2] + ]Move[scratch, spointer2] + ]Free Scratch[scratch2] + ]Free Scratch[scratch] + } + } +} + +PointerPointerToPointer@X86 Function[func,source1,source2,dest,op,size:out] +{ + ,scratch <- [func]Allocate Scratch[size] + { + ,scratch2 <- [~]Allocate Scratch[size] + { + spointer2 <- Pointer[scratch2, None[], size] + out <- [[[[[[[~]Fetch[source1, scratch] + ]Calculate Address[source2, scratch2] + ]Add Instruction[X86 Instruction[op, scratch, spointer2, size]] + ]Calculate Address[dest, scratch2] + ]Move[scratch, spointer2] + ]Free Scratch[scratch2] + ]Free Scratch[scratch] + } + } +} + +PointerPointerToMem@X86 Function[func,source1,souce2,dest,op,size:out] +{ + ,scratch <- [func]Allocate Scratch[size] + { + spointer <- Pointer[scratch, None[], size] + out <- [[[[[~]Calculate Address[source1, scratch] + ]Move[dest, spointer] + ]Fetch[source2, scratch] + ]Add Instruction[X86 Instruction[op, dest, scratch, size]] + ]Free Scratch[scratch] + } +} + +PointerPointerToReg@X86 Function[func,source1,souce2,dest,op,size:out] +{ + ,scratch <- [func]Allocate Scratch[size] + { + spointer <- Pointer[scratch, None[], size] + out <- [[[[~]Fetch[source1, dest] + ]Calculate Address[source2, scratch] + ]Add Instruction[X86 Instruction[op, dest, scratch, size]] + ]Free Scratch[scratch] + } +} + +2Op Associative@X86 Function[func,psource1,psource2,pdest,name:out func] +{ + source1 <- [func]Resolve[psource1] + source2 <- [func]Resolve[psource2] + dest <- [func]Resolve[pdest] + dest class <- [func]Classify Op[dest] + width <- Min[Min[Min[[source1]Size,[source2]Size], [dest]Size], 4] + swapper <- (1,0) + sources <- [[()]Append[source1]Append[source2] + [sources]Find[dest] + { + source <- [swapper]Index[~] + source class <- [func]Classify Op[source] + If[[dest class] = ["u"]] + { + If[[source class] = ["r"]] + { + out func <- [func]RegPointerPointer2Op[dest,source,name,width] + }{ + out func <- [func]PointerPointer2Op[dest,source,name,width] + } + }{ + If[[dest class] = ["r"]] + { + If[[source class] = ["u"]] + { + out func <- [func]RegPointerReg2Op[dest,source,name,width] + }{ + out func <- [func]RegMem2Op[dest,source,name,width] + } + }{ + If[[source class] = ["r"]] + { + out func <- [func]RegMem2Op[dest,source,name,width] + }{ + out func <- [func]MemPointer2Op[dest,source,name,width] + } + } + } + }{ + sclasses <- Map[sources, ["Classify Op"]Set Input[0, func]] + first <- [sources]Index[found index] + other index <- [swapper]Index[found index] + other <- [sources]Index[other index] + other class <- [sclasses]Index[other index] + found index <- [sclasses]Find["r"] + { + If[[other class] = ["u"]] + { + If[[dest class] = ["m"]] + { + out func <- [func]RegPointerToMem[first,other,dest,name,width] + }{ + If[[dest class] = ["u"]] + { + out func <- [func]RegPointerToPointer[first,other,dest,name,width] + }{ + out func <- [func]PointerMemToReg[other,first,dest,name,width] + } + } + }{ + If[[dest class] = ["u"]] + { + out func <- [func]RegMemToPointer[first,other,dest,name,width] + }{ + out func <- [func]RegMemToNotPointer[first,other,dest,name,width] + } + } + }{ + found index <- [sclasses]Find["m"] + { + If[[dest class] = ["r"]] + { + out func <- [func]PointerMemToReg[other,first,dest,name,width] + }{ + If[[dest class] = ["m"]] + { + out func <- [func]MemPointerToMem[first,other,dest,name,width] + }{ + out func <- [func]MemPointerToPointer[first,other,dest,name,width] + } + } + }{ + If[[dest class] = ["r"]] + { + out func <- [func]PointerPointerToReg[first,other,dest,name,width] + }{ + If[[dest class] = ["m"]] + { + out func <- [func]PointerPointerToMem[first,other,dest,name,width] + }{ + out func <- [func]PointerPointerToPointer[first,other,dest,name,width] + } + } + } + } + } +} + +2Op@X86 Function[func,psource1,psource2,pdest,name:out func] +{ + source1 <- [func]Resolve[psource1] + source2 <- [func]Resolve[psource2] + dest <- [func]Resolve[pdest] + width <- Min[Min[Min[[source1]Size,[source2]Size], [dest]Size], 4] + If[[source1] = [dest]] + { + If[[[source1]In Memory?] And [[source2]In Memory?]] + { + ,scratch, stack inc <- [func]Allocate Scratch[width] + { + out func <- [[[~]Add Instruction[X86 Instruction["mov", [scratch]Index[0], source2, width, stack inc]] + ]Add Instruction[X86 Instruction[name, source1, [scratch]Index[0], width, stack inc]] + ]Free Scratch[scratch] + } + }{ + out func <- [func]Add Instruction[X86 Instruction[name, dest, source2, width, 0]] + } + }{ + If[[dest]In Memory?] + { + If[[source2]In Memory?] + { + ,scratch, stack inc <- [func]Allocate Scratch[width] + { + out func <- [[[[~]Add Instruction[X86 Instruction["mov", [scratch]Index[0], source1, width, stack inc]] + ]Add Instruction[X86 Instruction[name, [scratch]Index[0], source2, width, stack inc]] + ]Add Instruction[X86 Instruction["mov", dest, [scratch]Index[0], width, stack inc]] + ]Free Scratch[scratch] + } + }{ + out func <- [[func]Move[source1,dest] + ]Add Instruction[X86 Instruction[name, dest, source2, width, 0]] + } + }{ + out func <- [[func]Move[source1,dest] + ]Add Instruction[X86 Instruction[name, dest, source2, width, 0]] + } + } +} + +Add@X86 Function[func,source1,source2,dest:out func] +{ + out func <- [func]2Op Associative[source1,source2,dest,"add"] +} + +Sub@X86 Function[func,source1,source2,dest:out func] +{ + out func <- [func]2Op[source1,source2,dest,"sub"] +} + +Move@X86 Function[func,psource,pdest:out func] +{ + source <- [func]Resolve[psource] + dest <- [func]Resolve[pdest] + out func <- [func]Add Instruction[X86 Instruction["mov", dest, source, 4]] +} + +Instruction ASM[current,instruction,func:out] +{ + out <- [[[current]Append["\t"]]Append[ [instruction]Inst ASM[func] ]]Append["\n"] +} + +Save Reg@X86 Function[func,reg:out] +{ + out <- [[func]Add Instruction[X86 Instruction["push", Register[reg, 4], None[], 4]] + ]Temp Stack << [ [[func]Temp Stack >>]+[4] ] +} + +Prolog Save@X86 Function[func,junk,reg:out] +{ + out <- [[func]Add Instruction[X86 Instruction["push", Register[reg, 4], None[], 4]] + ]Stack Size << [ [[func]Stack Size >>]+[4] ] +} + +Restore Reg@X86 Function[func,reg:out] +{ + out <- [[func]Add Instruction[X86 Instruction["pop", Register[reg, 4], None[], 4]] + ]Temp Stack << [ [[func]Temp Stack >>]-[4] ] +} + +Epilogue Restore@X86 Function[func,junk,reg:out] +{ + out <- [func]Add Instruction[X86 Instruction["pop", Register[reg, 4], None[], 4]] +} + +Finalize@X86 Function[func:out] +{ + alloc stack <- [[func]Stack Size >>] - [[func]Param Size >>] + + oldstream <- [func]Instructions >> + + If[[alloc stack] > [0]] + { + start <- [()]Append[X86 Instruction["sub", Register[6, 4],Immediate[alloc stack], Register[6, 4], 4], func] + }{ + start <- () + } + + If[[[func]Convention >>] = ["cdecl"]] + { + If[ [alloc stack] > [0] ] + { + retparam <- Immediate[alloc stack] + }{ + retparam <- None[] + } + }{ + retparam <- Immediate[[func]Stack Size >>] + } + + [[func]Need Save >>]First + { + prolog <- Fold["Prolog Save", [func]Instructions << [start], [func]Need Save >>] + out <- [Reverse Fold["Epilogue Restore", body, [func]Need Save >>]]Add Instruction[X86 Instruction["ret", retparam, None[], 4]] + }{ + prolog <- [func]Instructions <<[start] + out <- [body]Add Instruction[X86 Instruction["ret", retparam, None[], 4]] + } + + body <- Fold["Add Instruction", prolog, oldstream] +} + +Text@X86 Function[func:out] +{ + name line <- [Escape Rhope Name[[func]Name >>] + ]Append[":\n"] + + out <- Fold[["Instruction ASM"]Set Input[2, func], name line, [func]Instructions >>] +}