Skip to content

Commit

Permalink
cbuilder: adapt switch generation with if fallbacks
Browse files Browse the repository at this point in the history
  • Loading branch information
metagn committed Nov 11, 2024
1 parent 9d61f2c commit 7575014
Showing 1 changed file with 44 additions and 22 deletions.
66 changes: 44 additions & 22 deletions compiler/ccgstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -884,18 +884,23 @@ proc genRaiseStmt(p: BProc, t: PNode) =
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "reraiseException"))
raiseInstr(p, p.s(cpsStmts))

template genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
rangeFormat, eqFormat: FormatStr, labl: TLabel) =
template genCaseGenericBranch(p: BProc, b: PNode, e: TLoc, labl: TLabel,
rangeFormat, eqFormat: untyped) =
var x, y: TLoc
for i in 0..<b.len - 1:
let rlabel {.inject.} = labl
if b[i].kind == nkRange:
x = initLocExpr(p, b[i][0])
y = initLocExpr(p, b[i][1])
lineCg(p, cpsStmts, rangeFormat,
[rdCharLoc(e), rdCharLoc(x), rdCharLoc(y), labl])
let ra {.inject.} = rdCharLoc(e)
let rb {.inject.} = rdCharLoc(x)
let rc {.inject.} = rdCharLoc(y)
rangeFormat
else:
x = initLocExpr(p, b[i])
lineCg(p, cpsStmts, eqFormat, [rdCharLoc(e), rdCharLoc(x), labl])
let ra {.inject.} = rdCharLoc(e)
let rb {.inject.} = rdCharLoc(x)
eqFormat

proc genCaseSecondPass(p: BProc, t: PNode, d: var TLoc,
labId, until: int): TLabel =
Expand All @@ -912,17 +917,16 @@ proc genCaseSecondPass(p: BProc, t: PNode, d: var TLoc,
result = lend

template genIfForCaseUntil(p: BProc, t: PNode, d: var TLoc,
rangeFormat, eqFormat: FormatStr,
until: int, a: TLoc): TLabel =
# XXX doesn't work with cbuilder
until: int, a: TLoc,
rangeFormat, eqFormat: untyped): TLabel =
# generate a C-if statement for a Nim case statement
var res: TLabel
var labId = p.labels
for i in 1..until:
inc(p.labels)
let lab = "LA" & $p.labels & "_"
if t[i].kind == nkOfBranch: # else statement
genCaseGenericBranch(p, t[i], a, rangeFormat, eqFormat, lab)
genCaseGenericBranch(p, t[i], a, lab, rangeFormat, eqFormat)
else:
p.s(cpsStmts).addGoto(lab)
if until < t.len-1:
Expand All @@ -936,10 +940,9 @@ template genIfForCaseUntil(p: BProc, t: PNode, d: var TLoc,
res

template genCaseGeneric(p: BProc, t: PNode, d: var TLoc,
rangeFormat, eqFormat: FormatStr) =
# XXX doesn't work with cbuilder
rangeFormat, eqFormat: untyped) =
var a: TLoc = initLocExpr(p, t[0])
var lend = genIfForCaseUntil(p, t, d, rangeFormat, eqFormat, t.len-1, a)
var lend = genIfForCaseUntil(p, t, d, t.len-1, a, rangeFormat, eqFormat)
fixLabel(p, lend)

proc genCaseStringBranch(p: BProc, b: PNode, e: TLoc, labl: TLabel,
Expand Down Expand Up @@ -1003,10 +1006,15 @@ proc genStringCase(p: BProc, t: PNode, stringKind: TTypeKind, d: var TLoc) =
var lend = genCaseSecondPass(p, t, d, labId, t.len-1)
fixLabel(p, lend)
else:
if stringKind == tyCstring:
genCaseGeneric(p, t, d, "", "if (#eqCstrings($1, $2)) goto $3;$n")
else:
genCaseGeneric(p, t, d, "", "if (#eqStrings($1, $2)) goto $3;$n")
let eqFn = cgsymValue(p.module,
if stringKind == tyCstring: "eqCstrings"
else: "eqStrings")
genCaseGeneric(p, t, d):
discard
do:
p.s(cpsStmts).addSingleIfStmt(
cCall(eqFn, ra, rb)):
p.s(cpsStmts).addGoto(rlabel)

proc branchHasTooBigRange(b: PNode): bool =
result = false
Expand Down Expand Up @@ -1054,10 +1062,17 @@ proc genOrdinalCase(p: BProc, n: PNode, d: var TLoc) =

# generate if part (might be empty):
var a: TLoc = initLocExpr(p, n[0])
var lend = if splitPoint > 0: genIfForCaseUntil(p, n, d,
rangeFormat = "if ($1 >= $2 && $1 <= $3) goto $4;$n",
eqFormat = "if ($1 == $2) goto $3;$n",
splitPoint, a) else: ""
var lend: TLabel = ""
if splitPoint > 0:
lend = genIfForCaseUntil(p, n, d, splitPoint, a):
p.s(cpsStmts).addSingleIfStmt(cOp(And,
cOp(GreaterEqual, ra, rb),
cOp(LessEqual, ra, rc))):
p.s(cpsStmts).addGoto(rlabel)
do:
p.s(cpsStmts).addSingleIfStmt(
removeSinglePar(cOp(Equal, ra, rb))):
p.s(cpsStmts).addGoto(rlabel)

# generate switch part (might be empty):
if splitPoint+1 < n.len:
Expand Down Expand Up @@ -1098,8 +1113,15 @@ proc genCase(p: BProc, t: PNode, d: var TLoc) =
of tyCstring:
genStringCase(p, t, tyCstring, d)
of tyFloat..tyFloat128:
genCaseGeneric(p, t, d, "if ($1 >= $2 && $1 <= $3) goto $4;$n",
"if ($1 == $2) goto $3;$n")
genCaseGeneric(p, t, d):
p.s(cpsStmts).addSingleIfStmt(cOp(And,
cOp(GreaterEqual, ra, rb),
cOp(LessEqual, ra, rc))):
p.s(cpsStmts).addGoto(rlabel)
do:
p.s(cpsStmts).addSingleIfStmt(
removeSinglePar(cOp(Equal, ra, rb))):
p.s(cpsStmts).addGoto(rlabel)
else:
if t[0].kind == nkSym and sfGoto in t[0].sym.flags:
genGotoForCase(p, t)
Expand Down

0 comments on commit 7575014

Please sign in to comment.