Skip to content

Commit

Permalink
Merge branch 'devel' into pr_strictdefs
Browse files Browse the repository at this point in the history
  • Loading branch information
ringabout authored Nov 5, 2024
2 parents 63e83ed + c71de10 commit 433b967
Show file tree
Hide file tree
Showing 8 changed files with 288 additions and 109 deletions.
37 changes: 37 additions & 0 deletions compiler/cbuilderdecls.nim
Original file line number Diff line number Diff line change
Expand Up @@ -471,9 +471,31 @@ template addProcParams(builder: var Builder, params: out ProcParamBuilder, body:
body
finishProcParamBuilder(builder, params)

template addProcHeaderWithParams(builder: var Builder, callConv: TCallingConvention,
name: string, rettype: Snippet, paramBuilder: typed) =
# on nifc should build something like (proc name params type pragmas
# with no body given
# or enforce this with secondary builder object
builder.add(CallingConvToStr[callConv])
builder.add("(")
builder.add(rettype)
builder.add(", ")
builder.add(name)
builder.add(")")
paramBuilder

proc addProcHeader(builder: var Builder, callConv: TCallingConvention,
name: string, rettype, params: Snippet) =
# on nifc should build something like (proc name params type pragmas
# with no body given
# or enforce this with secondary builder object
addProcHeaderWithParams(builder, callConv, name, rettype):
builder.add(params)

proc addProcHeader(builder: var Builder, m: BModule, prc: PSym, name: string, params, rettype: Snippet, addAttributes: bool) =
# on nifc should build something like (proc name params type pragmas
# with no body given
# or enforce this with secondary builder object
let noreturn = isNoReturn(m, prc)
if sfPure in prc.flags and hasDeclspec in extccomp.CC[m.config.cCompiler].props:
builder.add("__declspec(naked) ")
Expand Down Expand Up @@ -525,3 +547,18 @@ proc addProcVar(builder: var Builder, m: BModule, prc: PSym, name: string, param
builder.add(" __attribute__((noreturn))")
# ensure we are just adding a variable:
builder.add(";\n")

proc addProcVar(builder: var Builder, callConv: TCallingConvention,
name: string, params, rettype: Snippet, isStatic = false) =
# on nifc, builds full variable
if isStatic:
builder.add("static ")
builder.add(CallingConvToStr[callConv])
builder.add("_PTR(")
builder.add(rettype)
builder.add(", ")
builder.add(name)
builder.add(")")
builder.add(params)
# ensure we are just adding a variable:
builder.add(";\n")
3 changes: 3 additions & 0 deletions compiler/cbuilderexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ proc procPtrTypeUnnamed(rettype, params: Snippet): Snippet =
proc procPtrTypeUnnamedNimCall(rettype, params: Snippet): Snippet =
rettype & "(N_RAW_NIMCALL*)" & params

proc procPtrTypeUnnamed(callConv: TCallingConvention, rettype, params: Snippet): Snippet =
CallingConvToStr[callConv] & "_PTR(" & rettype & ", )" & params

proc cCast(typ, value: Snippet): Snippet =
"((" & typ & ") " & value & ")"

Expand Down
55 changes: 55 additions & 0 deletions compiler/cbuilderstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,61 @@ template addForRangeInclusive(builder: var Builder, i, start, bound: Snippet, bo
body
builder.add("}\n")

template addSwitchStmt(builder: var Builder, val: Snippet, body: typed) =
builder.add("switch (")
builder.add(val)
builder.add(") {\n")
body
builder.add("}\n")

template addSingleSwitchCase(builder: var Builder, val: Snippet, body: typed) =
builder.add("case ")
builder.add(val)
builder.add(":\n")
body

type
SwitchCaseState = enum
None, Of, Else, Finished
SwitchCaseBuilder = object
state: SwitchCaseState

proc addCase(builder: var Builder, info: var SwitchCaseBuilder, val: Snippet) =
if info.state != Of:
assert info.state == None
info.state = Of
builder.add("case ")
builder.add(val)
builder.add(":\n")

proc addCaseRange(builder: var Builder, info: var SwitchCaseBuilder, first, last: Snippet) =
if info.state != Of:
assert info.state == None
info.state = Of
builder.add("case ")
builder.add(first)
builder.add(" ... ")
builder.add(last)
builder.add(":\n")

proc addCaseElse(builder: var Builder, info: var SwitchCaseBuilder) =
assert info.state == None
info.state = Else
builder.add("default:\n")

template addSwitchCase(builder: var Builder, info: out SwitchCaseBuilder, caseBody, body: typed) =
info = SwitchCaseBuilder(state: None)
caseBody
info.state = Finished
body

template addSwitchElse(builder: var Builder, body: typed) =
builder.add("default:\n")
body

proc addBreak(builder: var Builder) =
builder.add("break;\n")

template addScope(builder: var Builder, body: typed) =
builder.add("{")
body
Expand Down
61 changes: 34 additions & 27 deletions compiler/ccgreset.nim
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,28 @@ proc specializeResetN(p: BProc, accessor: Rope, n: PNode;
if disc.loc.snippet == "": fillObjectFields(p.module, typ)
if disc.loc.t == nil:
internalError(p.config, n.info, "specializeResetN()")
lineF(p, cpsStmts, "switch ($1.$2) {$n", [accessor, disc.loc.snippet])
for i in 1..<n.len:
let branch = n[i]
assert branch.kind in {nkOfBranch, nkElse}
if branch.kind == nkOfBranch:
genCaseRange(p, branch)
else:
lineF(p, cpsStmts, "default:$n", [])
specializeResetN(p, accessor, lastSon(branch), typ)
lineF(p, cpsStmts, "break;$n", [])
lineF(p, cpsStmts, "} $n", [])
specializeResetT(p, "$1.$2" % [accessor, disc.loc.snippet], disc.loc.t)
let discField = dotField(accessor, disc.loc.snippet)
p.s(cpsStmts).addSwitchStmt(discField):
for i in 1..<n.len:
let branch = n[i]
assert branch.kind in {nkOfBranch, nkElse}
var caseBuilder: SwitchCaseBuilder
p.s(cpsStmts).addSwitchCase(caseBuilder):
if branch.kind == nkOfBranch:
genCaseRange(p, branch, caseBuilder)
else:
p.s(cpsStmts).addCaseElse(caseBuilder)
do:
specializeResetN(p, accessor, lastSon(branch), typ)
p.s(cpsStmts).addBreak()
specializeResetT(p, discField, disc.loc.t)
of nkSym:
let field = n.sym
if field.typ.kind == tyVoid: return
if field.loc.snippet == "": fillObjectFields(p.module, typ)
if field.loc.t == nil:
internalError(p.config, n.info, "specializeResetN()")
specializeResetT(p, "$1.$2" % [accessor, field.loc.snippet], field.loc.t)
specializeResetT(p, dotField(accessor, field.loc.snippet), field.loc.t)
else: internalError(p.config, n.info, "specializeResetN()")

proc specializeResetT(p: BProc, accessor: Rope, typ: PType) =
Expand All @@ -58,10 +61,8 @@ proc specializeResetT(p: BProc, accessor: Rope, typ: PType) =
of tyArray:
let arraySize = lengthOrd(p.config, typ.indexType)
var i: TLoc = getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt))
linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",
[i.snippet, arraySize])
specializeResetT(p, ropecg(p.module, "$1[$2]", [accessor, i.snippet]), typ.elementType)
lineF(p, cpsStmts, "}$n", [])
p.s(cpsStmts).addForRangeExclusive(i.snippet, cIntValue(0), cIntValue(arraySize)):
specializeResetT(p, subscript(accessor, i.snippet), typ.elementType)
of tyObject:
var x = typ.baseClass
if x != nil: x = x.skipTypes(skipPtrs)
Expand All @@ -70,28 +71,34 @@ proc specializeResetT(p: BProc, accessor: Rope, typ: PType) =
of tyTuple:
let typ = getUniqueType(typ)
for i, a in typ.ikids:
specializeResetT(p, ropecg(p.module, "$1.Field$2", [accessor, i]), a)
specializeResetT(p, dotField(accessor, "Field" & $i), a)

of tyString, tyRef, tySequence:
lineCg(p, cpsStmts, "#unsureAsgnRef((void**)&$1, NIM_NIL);$n", [accessor])
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "unsureAsgnRef"),
cCast("void**", cAddr(accessor)),
"NIM_NIL")

of tyProc:
if typ.callConv == ccClosure:
lineCg(p, cpsStmts, "#unsureAsgnRef((void**)&$1.ClE_0, NIM_NIL);$n", [accessor])
lineCg(p, cpsStmts, "$1.ClP_0 = NIM_NIL;$n", [accessor])
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "unsureAsgnRef"),
cCast("void**", cAddr(dotField(accessor, "ClE_0"))),
"NIM_NIL")
p.s(cpsStmts).addFieldAssignment(accessor, "ClP_0", "NIM_NIL")
else:
lineCg(p, cpsStmts, "$1 = NIM_NIL;$n", [accessor])
p.s(cpsStmts).addAssignment(accessor, "NIM_NIL")
of tyChar, tyBool, tyEnum, tyRange, tyInt..tyUInt64:
lineCg(p, cpsStmts, "$1 = 0;$n", [accessor])
p.s(cpsStmts).addAssignment(accessor, cIntValue(0))
of tyCstring, tyPointer, tyPtr, tyVar, tyLent:
lineCg(p, cpsStmts, "$1 = NIM_NIL;$n", [accessor])
p.s(cpsStmts).addAssignment(accessor, "NIM_NIL")
of tySet:
case mapSetType(p.config, typ)
of ctArray:
lineCg(p, cpsStmts, "#nimZeroMem($1, sizeof($2));$n",
[accessor, getTypeDesc(p.module, typ)])
let t = getTypeDesc(p.module, typ)
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "nimZeroMem"),
accessor,
cSizeof(t))
of ctInt8, ctInt16, ctInt32, ctInt64:
lineCg(p, cpsStmts, "$1 = 0;$n", [accessor])
p.s(cpsStmts).addAssignment(accessor, cIntValue(0))
else:
raiseAssert "unexpected set type kind"
of tyNone, tyEmpty, tyNil, tyUntyped, tyTyped, tyGenericInvocation,
Expand Down
53 changes: 29 additions & 24 deletions compiler/ccgstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -960,26 +960,26 @@ proc ifSwitchSplitPoint(p: BProc, n: PNode): int =
if branch.kind == nkOfBranch and branchHasTooBigRange(branch):
result = i

proc genCaseRange(p: BProc, branch: PNode) =
proc genCaseRange(p: BProc, branch: PNode, info: var SwitchCaseBuilder) =
for j in 0..<branch.len-1:
if branch[j].kind == nkRange:
if hasSwitchRange in CC[p.config.cCompiler].props:
var litA = newBuilder("")
var litB = newBuilder("")
genLiteral(p, branch[j][0], litA)
genLiteral(p, branch[j][1], litB)
lineF(p, cpsStmts, "case $1 ... $2:$n", [extract(litA), extract(litB)])
p.s(cpsStmts).addCaseRange(info, extract(litA), extract(litB))
else:
var v = copyNode(branch[j][0])
while v.intVal <= branch[j][1].intVal:
var litA = newBuilder("")
genLiteral(p, v, litA)
lineF(p, cpsStmts, "case $1:$n", [extract(litA)])
p.s(cpsStmts).addCase(info, extract(litA))
inc(v.intVal)
else:
var litA = newBuilder("")
genLiteral(p, branch[j], litA)
lineF(p, cpsStmts, "case $1:$n", [extract(litA)])
p.s(cpsStmts).addCase(info, extract(litA))

proc genOrdinalCase(p: BProc, n: PNode, d: var TLoc) =
# analyse 'case' statement:
Expand All @@ -994,26 +994,31 @@ proc genOrdinalCase(p: BProc, n: PNode, d: var TLoc) =

# generate switch part (might be empty):
if splitPoint+1 < n.len:
lineF(p, cpsStmts, "switch ($1) {$n", [rdCharLoc(a)])
var hasDefault = false
for i in splitPoint+1..<n.len:
# bug #4230: avoid false sharing between branches:
if d.k == locTemp and isEmptyType(n.typ): d.k = locNone
var branch = n[i]
if branch.kind == nkOfBranch:
genCaseRange(p, branch)
else:
# else part of case statement:
lineF(p, cpsStmts, "default:$n", [])
hasDefault = true
exprBlock(p, branch.lastSon, d)
lineF(p, cpsStmts, "break;$n", [])
if not hasDefault:
if hasBuiltinUnreachable in CC[p.config.cCompiler].props:
lineF(p, cpsStmts, "default: __builtin_unreachable();$n", [])
elif hasAssume in CC[p.config.cCompiler].props:
lineF(p, cpsStmts, "default: __assume(0);$n", [])
lineF(p, cpsStmts, "}$n", [])
let rca = rdCharLoc(a)
p.s(cpsStmts).addSwitchStmt(rca):
var hasDefault = false
for i in splitPoint+1..<n.len:
# bug #4230: avoid false sharing between branches:
if d.k == locTemp and isEmptyType(n.typ): d.k = locNone
var branch = n[i]
var caseBuilder: SwitchCaseBuilder
p.s(cpsStmts).addSwitchCase(caseBuilder):
if branch.kind == nkOfBranch:
genCaseRange(p, branch, caseBuilder)
else:
# else part of case statement:
hasDefault = true
p.s(cpsStmts).addCaseElse(caseBuilder)
do:
exprBlock(p, branch.lastSon, d)
p.s(cpsStmts).addBreak()
if not hasDefault:
if hasBuiltinUnreachable in CC[p.config.cCompiler].props:
p.s(cpsStmts).addSwitchElse():
p.s(cpsStmts).addCallStmt("__builtin_unreachable")
elif hasAssume in CC[p.config.cCompiler].props:
p.s(cpsStmts).addSwitchElse():
p.s(cpsStmts).addCallStmt("__assume", cIntValue(0))
if lend != "": fixLabel(p, lend)

proc genCase(p: BProc, t: PNode, d: var TLoc) =
Expand Down
Loading

0 comments on commit 433b967

Please sign in to comment.