# HG changeset patch # User Mike Pavone # Date 1377677145 25200 # Node ID 56b2100d9fffde4653fc2608952b5e7908d738ff # Parent cea671c4056c253b2ba5a20a21a3f30568aeb2f5 Add code for converting IL into x86 machine code diff -r cea671c4056c -r 56b2100d9fff modules/il.tp --- a/modules/il.tp Wed Aug 28 01:05:29 2013 -0700 +++ b/modules/il.tp Wed Aug 28 01:05:45 2013 -0700 @@ -412,20 +412,22 @@ } } } - save <- :regs :scope{ + save <- :regs :_scope{ #{ opcode <- { _save } numops <- { 0 } name <- { _names get: _save } + tosave <- { regs } + scope <- { _scope } string <- { - block <- scope join: "\n\t" - if: (scope length) > 0 { + block <- _scope join: "\n\t" + if: (_scope length) > 0 { block <- "\n\t" . block . "\n" } name . " " . (regs join: " ") . " {" . block . "}" } to2OpInst <- { - save: regs (to2Op: scope) + save: regs (to2Op: _scope) } } } @@ -609,7 +611,26 @@ } } + toBackend <- :program :backend { + prepped <- program map: :fun { + backend adjustIL: fun + } + labels <- prepped map: :_ { + backend label + } + outprog <- #[] + foreach: prepped :name instarr { + outprog append: (labels get: name) + foreach: instarr :_ inst { + backend convertIL: inst to: outprog withLabels: labels + } + } + outprog + } + main <- { + prog <- dict linear + fib <- #[ sub: 2 (arg: 0) (reg: 0) q skipIf: ge #[ @@ -626,17 +647,13 @@ foreach: fib :idx inst { print: (string: inst) . "\n" } - print: "\n\nUsage:\n\n" - fiba <- allocRegs: fib withSource: (x86 regSource) - print: "\n\nAfter Assignment:\n\n" - foreach: fiba :idx inst { - print: (string: inst) . "\n" - } - fib2 <- to2Op: fiba - print: "\n\n2-Operand:\n\n" - foreach: fib2 :idx inst { - print: (string: inst) . "\n" - } + prog set: "fib" fib + + mprog <- prog toBackend: x86 + ba <- bytearray executableFromBytes: mprog + res <- ba runWithArg: 30u64 + print: (string: res) . "\n" + 0 } } } diff -r cea671c4056c -r 56b2100d9fff modules/x86.tp --- a/modules/x86.tp Wed Aug 28 01:05:29 2013 -0700 +++ b/modules/x86.tp Wed Aug 28 01:05:45 2013 -0700 @@ -9,6 +9,7 @@ rm <- :tail { reg or 0xC0u8 | tail } validforSize? <- :size { true } isInteger? <- { false } + isString? <- { false } register? <- { true } label? <- { false } upper? <- { false } @@ -57,7 +58,7 @@ rexBitReg <- { 0u8 } rexBitRM <- { 0u8 } } - size <- :s { + _size <- :s { #{ num <- { s } = <- :other { @@ -85,10 +86,10 @@ } } } - byte <- size: 0 - word <- size: 1 - dword <- size: 2 - qword <- size: 3 + byte <- _size: 0 + word <- _size: 1 + dword <- _size: 2 + qword <- _size: 3 condition <- :num { #{ @@ -607,6 +608,118 @@ } } + adjustIL <- :ilfun { + il to2Op: (il allocRegs: ilfun withSource: regSource) + } + + convertIL:to:withLabels:withSaved <- :inst :outarr :labels :saved { + mapSize <- :ilsize { + if: (ilsize bytes) > 2 { + if: (ilsize bytes) = 8 { q } else: { d } + } else: { + if: (ilsize bytes) = 1 { b } else: { w } + } + } + mapcond <- :ilcond { + ccmap <- #[ + e + ne + ge + le + g + l + ae + be + a + c + ] + ccmap get: (ilcond cc) + } + opmap <- #[ + { outarr append: (add: (inst in) (inst out) (mapSize: (inst size))) } + { } //and + { } //or + { } //xor + { outarr append: (sub: (inst in) (inst out) (mapSize: (inst size))) } + { } //cmp + { } //not + { } //sl + { } //asr + { } //lsr + { } //rol + { } //ror + { outarr append: (mov: (inst in) (inst out) (mapSize: (inst size))) } + { + //call + arguments <- inst args + cur <- (arguments length) - 1 + while: { cur >= 0 } do: { + src <- (arguments get: cur) + if: cur < (_argregs length) { + dst <- _argregs get: cur + if: (not: dst = src) { + //TODO: Handle edge case in which src is a caller saved + //reg that has been pusehd onto the stack to preserve + //it across this call + outarr append: (mov: src dst q) + } + } else: { + outarr append: (push: src) + } + cur <- cur - 1 + } + toCall <- inst target + if: (toCall isString?) { + //TODO: Handle call to undefined label + toCall <- labels get: toCall + } + outarr append: (call: toCall) + } + { + //return + if: (not: _rax = (inst arg)) { + outarr append: (mov: (inst arg) _rax q) + } + foreach: saved :_ reg { + outarr append: (pop: reg) + } + outarr append: (ret: ) + } + { + //skipIf + endlab <- label: + outarr append: (jcc: (mapcond: (inst cond)) endlab) + foreach: (inst toskip) :_ inst { + convertIL: inst to: outarr withLabels: labels withSaved: saved + } + outarr append: endlab + } + { + //save + newsave <- [] + foreach: (inst tosave) :_ reg { + outarr append: (push: reg) + newsave <- reg | newsave + } + foreach: (inst scope) :_ inst { + convertIL: inst to: outarr withLabels: labels withSaved: newsave + } + if: ((inst scope) length) = 0 || (((inst scope) get: ((inst scope) length) - 1) opcode) != 14 { + foreach: newsave :_ reg { + outarr append: (pop: reg) + } + } + } + ] + fun <- opmap get: (inst opcode) + fun: + outarr + } + + convertIL:to:withLabels <- :inst :outarr :labels { + convertIL: inst to: outarr withLabels: labels withSaved: [] + } + main <- { fib <- label: notbase <- label: