From f98964d99f2ab721cc718b2be3afa78305867b6b Mon Sep 17 00:00:00 2001 From: metagn Date: Sun, 3 Nov 2024 19:57:31 +0300 Subject: [PATCH] cbuilder: add `for` range statements (#24391) Finishes `genEnumInfo` as followup to #24351. As #24381 mentions this covers every use of `for` loops in the codegen. --------- Co-authored-by: Andreas Rumpf --- compiler/cbuilderstmts.nim | 26 ++++++++++++++++++++++++++ compiler/ccgtypes.nim | 22 +++++++++++++++------- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/compiler/cbuilderstmts.nim b/compiler/cbuilderstmts.nim index a96571d1b8b4..e2d272e79524 100644 --- a/compiler/cbuilderstmts.nim +++ b/compiler/cbuilderstmts.nim @@ -93,6 +93,32 @@ template addElseBranch(builder: var Builder, stmt: var IfStmt, body: typed) = body builder.add("}") +proc addForRangeHeader(builder: var Builder, i, start, bound: Snippet, inclusive: bool = false) = + builder.add("for (") + builder.add(i) + builder.add(" = ") + builder.add(start) + builder.add("; ") + builder.add(i) + if inclusive: + builder.add(" <= ") + else: + builder.add(" < ") + builder.add(bound) + builder.add("; ") + builder.add(i) + builder.add("++) {\n") + +template addForRangeExclusive(builder: var Builder, i, start, bound: Snippet, body: typed) = + addForRangeHeader(builder, i, start, bound, false) + body + builder.add("}\n") + +template addForRangeInclusive(builder: var Builder, i, start, bound: Snippet, body: typed) = + addForRangeHeader(builder, i, start, bound, true) + body + builder.add("}\n") + template addScope(builder: var Builder, body: typed) = builder.add("{") body diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index eb6b6bd9f31f..04b740aa92d9 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -1503,13 +1503,20 @@ proc genEnumInfo(m: BModule; typ: PType, name: Rope; info: TLineInfo) = m.s[cfsTypeInit1].addArrayVarWithInitializer( kind = Global, name = enumArray, - elementType = "char* NIM_CONST", # XXX maybe do this in `addVar` + elementType = constPtrType("char"), len = typ.n.len): m.s[cfsTypeInit1].add(extract(enumNames)) - m.s[cfsTypeInit3].addf("for ($1 = 0; $1 < $2; $1++) {$n" & - "$3[$1+$4].kind = 1;$n" & "$3[$1+$4].offset = $1;$n" & - "$3[$1+$4].name = $5[$1];$n" & "$6[$1] = &$3[$1+$4];$n" & "}$n", [counter, - rope(typ.n.len), m.typeNodesName, rope(firstNimNode), enumArray, nodePtrs]) + m.s[cfsTypeInit3].addForRangeExclusive(i = counter, + start = cIntValue(0), + bound = cIntValue(typ.n.len)): + let nodeLoc = subscript(m.typeNodesName, + cOp(Add, "NI", counter, cIntValue(firstNimNode))) + m.s[cfsTypeInit3].addFieldAssignment(nodeLoc, "kind", cIntValue(1)) + m.s[cfsTypeInit3].addFieldAssignment(nodeLoc, "offset", counter) + m.s[cfsTypeInit3].addFieldAssignment(nodeLoc, "name", + subscript(enumArray, counter)) + m.s[cfsTypeInit3].addSubscriptAssignment(nodePtrs, counter, + cAddr(nodeLoc)) m.s[cfsTypeInit3].add(extract(specialCases)) let n = getNimNode(m) m.s[cfsTypeInit3].addFieldAssignment(n, "len", typ.n.len) @@ -1518,8 +1525,9 @@ proc genEnumInfo(m: BModule; typ: PType, name: Rope; info: TLineInfo) = cAddr(subscript(nodePtrs, cIntValue(0)))) m.s[cfsTypeInit3].addFieldAssignment(tiNameForHcr(m, name), "node", cAddr(n)) if hasHoles: - # 1 << 2 is {ntfEnumHole} - m.s[cfsTypeInit3].addf("$1.flags = 1<<2;$n", [tiNameForHcr(m, name)]) + m.s[cfsTypeInit3].addFieldAssignment(tiNameForHcr(m, name), "flags", + # 1 << 2 is {ntfEnumHole} + cOp(Shl, "NU8", cIntValue(1), cIntValue(2))) proc genSetInfo(m: BModule; typ: PType, name: Rope; info: TLineInfo) = assert(typ.elementType != nil)