Skip to content

Commit

Permalink
progress
Browse files Browse the repository at this point in the history
  • Loading branch information
Araq committed Sep 24, 2024
1 parent a1035ab commit 95fbaf7
Show file tree
Hide file tree
Showing 6 changed files with 232 additions and 52 deletions.
5 changes: 5 additions & 0 deletions src/nifc/amd64/asm_grammar.nif
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,17 @@
(jz Label)
(jnz Label)
(jg Label)
(jng Label)
(jge Label)
(jnge Label)
(ja Label)
(jna Label)
(jae Label)
(jnae Label)
(nop)
(ret)
(syscall)
(lab "" SYMBOLDEF)
(comment "; " (OR IDENT SYMBOL STRINGLITERAL))
) (DO "nl"))
)
87 changes: 69 additions & 18 deletions src/nifc/amd64/asm_grammar.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1254,8 +1254,8 @@ proc genInstruction(c: var Context): bool =
or2 = true
break or3
var kw66 = false
if isTag(c, JgeT):
emitTag(c, "jge")
if isTag(c, JngT):
emitTag(c, "jng")
if not genLabel(c):
error(c, "Label expected")
break or3
Expand All @@ -1264,8 +1264,8 @@ proc genInstruction(c: var Context): bool =
or2 = true
break or3
var kw67 = false
if isTag(c, JaT):
emitTag(c, "ja")
if isTag(c, JgeT):
emitTag(c, "jge")
if not genLabel(c):
error(c, "Label expected")
break or3
Expand All @@ -1274,15 +1274,55 @@ proc genInstruction(c: var Context): bool =
or2 = true
break or3
var kw68 = false
if isTag(c, JaeT):
emitTag(c, "jae")
if isTag(c, JngeT):
emitTag(c, "jnge")
if not genLabel(c):
error(c, "Label expected")
break or3
kw68 = matchParRi(c)
if kw68:
or2 = true
break or3
var kw69 = false
if isTag(c, JaT):
emitTag(c, "ja")
if not genLabel(c):
error(c, "Label expected")
break or3
kw69 = matchParRi(c)
if kw69:
or2 = true
break or3
var kw70 = false
if isTag(c, JnaT):
emitTag(c, "jna")
if not genLabel(c):
error(c, "Label expected")
break or3
kw70 = matchParRi(c)
if kw70:
or2 = true
break or3
var kw71 = false
if isTag(c, JaeT):
emitTag(c, "jae")
if not genLabel(c):
error(c, "Label expected")
break or3
kw71 = matchParRi(c)
if kw71:
or2 = true
break or3
var kw72 = false
if isTag(c, JnaeT):
emitTag(c, "jnae")
if not genLabel(c):
error(c, "Label expected")
break or3
kw72 = matchParRi(c)
if kw72:
or2 = true
break or3
if matchAndEmitTag(c, NopT, "nop"):
or2 = true
break or3
Expand All @@ -1292,25 +1332,36 @@ proc genInstruction(c: var Context): bool =
if matchAndEmitTag(c, SyscallT, "syscall"):
or2 = true
break or3
var kw69 = false
var kw73 = false
if isTag(c, LabT):
emit(c, "")
var sym74 = declareSym(c)
if not success(sym74):
error(c, "SYMBOLDEF expected")
break or3
kw73 = matchParRi(c)
if kw73:
or2 = true
break or3
var kw75 = false
if isTag(c, CommentT):
emit(c, "; ")
var or70 = false
block or71:
var or76 = false
block or77:
if matchIdent(c):
or70 = true
break or71
or76 = true
break or77
if lookupSym(c):
or70 = true
break or71
or76 = true
break or77
if matchStringLit(c):
or70 = true
break or71
if not or70:
or76 = true
break or77
if not or76:
error(c, "invalid Instruction")
break or3
kw69 = matchParRi(c)
if kw69:
kw75 = matchParRi(c)
if kw75:
or2 = true
break or3
if not or2: return false
Expand Down
22 changes: 15 additions & 7 deletions src/nifc/amd64/asm_model.nim
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,17 @@ const
JzT* = TagId(111)
JnzT* = TagId(112)
JgT* = TagId(113)
JgeT* = TagId(114)
JaT* = TagId(115)
JaeT* = TagId(116)
NopT* = TagId(117)
RetT* = TagId(118)
SyscallT* = TagId(119)
CommentT* = TagId(120)
JngT* = TagId(114)
JgeT* = TagId(115)
JngeT* = TagId(116)
JaT* = TagId(117)
JnaT* = TagId(118)
JaeT* = TagId(119)
JnaeT* = TagId(120)
NopT* = TagId(121)
RetT* = TagId(122)
SyscallT* = TagId(123)
CommentT* = TagId(124)

proc registerTags*() =
registerTag "global", GlobalT
Expand Down Expand Up @@ -234,9 +238,13 @@ proc registerTags*() =
registerTag "jz", JzT
registerTag "jnz", JnzT
registerTag "jg", JgT
registerTag "jng", JngT
registerTag "jge", JgeT
registerTag "jnge", JngeT
registerTag "ja", JaT
registerTag "jna", JnaT
registerTag "jae", JaeT
registerTag "jnae", JnaeT
registerTag "nop", NopT
registerTag "ret", RetT
registerTag "syscall", SyscallT
Expand Down
7 changes: 4 additions & 3 deletions src/nifc/amd64/genasm.nim
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,6 @@ proc getTempVar(c: var GeneratedCode): TempVar =
result = TempVar(c.temps)
inc c.temps

proc defineLabel(c: var GeneratedCode; lab: Label; info: PackedLineInfo) =
c.code.addSymDef "L." & $int(lab), info

proc useLabel(c: var GeneratedCode; lab: Label; info: PackedLineInfo) =
c.addSym "L." & $int(lab), info

Expand All @@ -140,6 +137,10 @@ template buildTreeI(c: var GeneratedCode; keyw: TagId; info: PackedLineInfo; bod
c.code.buildTree keyw, info:
body

proc defineLabel(c: var GeneratedCode; lab: Label; info: PackedLineInfo) =
c.code.buildTree LabT, info:
c.code.addSymDef "L." & $int(lab), info

# Type graph

include ".." / preasm / genpreasm_t
Expand Down
140 changes: 126 additions & 14 deletions src/nifc/amd64/genasm_e.nim
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,36 @@

# included from genpreasm.nim

proc opposite(t: TagId): TagId =
case t
of JeT: JneT
of JneT: JeT
of JzT: JnzT
of JnzT: JzT
of JgT: JngT
of JgeT: JngeT
of JngeT: JgeT
of JaT: JnaT
of JnaT: JaT
of JaeT: JnaeT
of JnaeT: JaeT
else: NopT

proc jumpToPutInstr(t: TagId): TagId =
case t
of JeT: SetneT
of JneT: SeteT
of JzT: SetnzT
of JnzT: SetzT
of JgT: SetngT
of JgeT: SetngeT
of JngeT: SetgeT
of JaT: SetnaT
of JnaT: SetaT
of JaeT: SetnaeT
of JnaeT: SetaeT
else: NopT

proc emitLoc*(c: var GeneratedCode; loc: Location) =
case loc.kind
of Undef:
Expand Down Expand Up @@ -132,6 +162,10 @@ proc genAsgn(c: var GeneratedCode; dest, src: Location) =
c.buildTree MovapdT:
c.emitLoc dest
c.emitLoc src
elif src.kind == InFlag:
assert dest.kind != InFlag
c.buildTree jumpToPutInstr(src.flag):
c.emitLoc dest
elif dest.typ.size < 0'i32 or dest.typ.size > 8'i32:
assert dest.typ.size > 0'i32, "size not set!"
assert false, "implement rep byte copy loop"
Expand All @@ -149,6 +183,8 @@ proc genAsgn(c: var GeneratedCode; dest, src: Location) =
proc into(c: var GeneratedCode; dest: var Location; src: Location) =
if dest.kind == Undef:
dest = src
elif dest.kind == InFlag and src.kind == InFlag and dest.flag == NopT:
dest.flag = src.flag
else:
genAsgn c, dest, src

Expand Down Expand Up @@ -306,6 +342,52 @@ proc genAddr(c: var GeneratedCode; t: Tree; n: NodePos; dest: var Location) =
else:
error c.m, "expected expression but got: ", t, n

proc genLoad(c: var GeneratedCode; dest: var Location; address: Location) =
if dest.kind == Undef:
dest = scratchReg(c.rega)
# XXX Floating point? What if it doesn't even fit a register?

let opc = if address.typ.kind == AFloat: MovapdT else: MovT
c.buildTree opc:
emitLoc c, dest
c.buildTree Mem1T:
emitLoc c, address

proc genLvalue(c: var GeneratedCode; t: Tree; n: NodePos; dest: var Location) =
let info = t[n].info
case t[n].kind
of Sym:
let lit = t[n].litId
let def = c.m.defs.getOrDefault(lit)
case def.kind
of ProcC:
let d = Location(typ: AddrTyp, kind: InData, data: lit)
into c, dest, d
of VarC, ParamC:
let d = c.locals[lit]
if d.kind in {InStack}:
genLoad c, dest, d
else:
into c, dest, d
of GvarC, ConstC:
let typ = c.globals[lit]
let d = Location(flags: {Indirect}, typ: typ, kind: InData, data: lit)
genLoad c, dest, d
of TvarC:
let typ = c.globals[lit]
let d = Location(flags: {Indirect}, typ: typ, kind: InTls, data: lit)
genLoad c, dest, d
of EfldC:
assert false, "enum fields not implemented"
else:
error c.m, "undeclared identifier: ", t, n
of DerefC, AtC, PatC, DotC:
var d = Location(kind: Undef)
genAddr c, t, n, d
genLoad c, dest, d
else:
error c.m, "expected expression but got: ", t, n

proc genStrLit(c: var GeneratedCode; s: string; info: PackedLineInfo; dest: var Location) =
var id = c.strings.getOrDefault(s, -1)
var symId: string
Expand Down Expand Up @@ -394,6 +476,36 @@ proc genFjmp(c: var GeneratedCode; t: Tree; n: NodePos; jmpTarget: Label; opc =
c.useLabel jmpTarget, info
]#

type
CondJmpKind = enum
Fjmp # jump if the condition is false (the `and` operator)
Tjmp # jump if the condition is true (the `or` operator)

proc genCond(c: var GeneratedCode; t: Tree; n: NodePos; dest: var Location; jk: CondJmpKind) =
let l1 = getLabel(c)
let (a, b) = sons2(t, n)
# tell the pipeline we need the result in a flag:
var destA = Location(kind: InFlag, flag: NopT)
genx(c, t, a, destA)
assert destA.kind == InFlag
let opc = if jk == Tjmp: destA.flag else: opposite(destA.flag)
c.buildTree opc:
c.useLabel l1, t[n].info
genx(c, t, b, dest)
c.defineLabel l1, t[n].info

proc genCmp(c: var GeneratedCode; t: Tree; n: NodePos; dest: var Location; opc: TagId) =
var d = Location(kind: InFlag, flag: opc)
let (a, b) = sons2(t, n)
let x = gen(c, t, a)
let y = gen(c, t, b)
c.buildTree CmpT:
emitLoc c, x
emitLoc c, y
c.freeTemp y
c.freeTemp x
c.into dest, d

proc genDataVal(c: var GeneratedCode; t: Tree; n: NodePos) =
let d = gen(c, t, n)
emitLoc c, d
Expand Down Expand Up @@ -521,18 +633,18 @@ proc genx(c: var GeneratedCode; t: Tree; n: NodePos; dest: var Location) =
of BitorC: typedBinOp OrT
of BitxorC: typedBinOp XorT
of BitnotC: typedUnOp NotT
of AndC: genCond c, t, n, FjmpT
of OrC: genCond c, t, n, TjmpT
of NotC: unOp NotT
of NegC: unOp NegT
of EqC: cmpOp EqT
of LeC: cmpOp LeT
of LtC: cmpOp LtT
of CastC, ConvC:
assert mode == WantValue
genConv c, t, n
of SufC:
let (value, suffix) = sons2(t, n)
genx(c, t, value, mode)
of NegC: typedUnOp NegT
of AndC: genCond c, t, n, dest, Fjmp
of OrC: genCond c, t, n, dest, Tjmp
of EqC: genCmp c, t, n, dest, JneT
of LeC: genCmp c, t, n, dest, JgT
of LtC: genCmp c, t, n, dest, JgeT

#of NotC: unOp NotT
#of CastC, ConvC:
# genConv c, t, n
#of SufC:
# let (value, suffix) = sons2(t, n)
# genx(c, t, value, mode)
else:
genLvalue c, t, n, mode, dest
genLvalue c, t, n, dest
Loading

0 comments on commit 95fbaf7

Please sign in to comment.