From 683755b5c2938c2e076408ac512a8dc36497c81c Mon Sep 17 00:00:00 2001 From: metagn Date: Mon, 25 Nov 2024 12:26:41 +0300 Subject: [PATCH] do everything except varargs and `cIfExpr` --- compiler/cbuilderexprs.nim | 459 ++++++++++++++++++++-------- compiler/cbuilderstmts.nim | 594 +++++++++++++++++++++++++------------ compiler/ccgexprs.nim | 12 +- compiler/ccgreset.nim | 2 +- compiler/ccgstmts.nim | 46 +-- compiler/ccgtrav.nim | 4 +- compiler/ccgtypes.nim | 3 +- 7 files changed, 773 insertions(+), 347 deletions(-) diff --git a/compiler/cbuilderexprs.nim b/compiler/cbuilderexprs.nim index dce8c65214d93..01cf2b6167997 100644 --- a/compiler/cbuilderexprs.nim +++ b/compiler/cbuilderexprs.nim @@ -1,98 +1,172 @@ proc constType(t: Snippet): Snippet = - # needs manipulation of `t` in nifc - "NIM_CONST " & t + when buildNifc: + # XXX can't just string modify `t`, need to deeply insert (ro) somehow + t + else: + "NIM_CONST " & t + +proc ptrType(t: Snippet): Snippet = + when buildNifc: + "(ptr " & t & ")" + else: + t & "*" proc constPtrType(t: Snippet): Snippet = - t & "* NIM_CONST" + when buildNifc: + "(ptr " & t & " (ro))" + else: + t & "* NIM_CONST" proc ptrConstType(t: Snippet): Snippet = - "NIM_CONST " & t & "*" - -proc ptrType(t: Snippet): Snippet = - t & "*" + # NIM_CONST `t`* + ptrType(constType(t)) proc cppRefType(t: Snippet): Snippet = - t & "&" - -const - CallingConvToStr: array[TCallingConvention, string] = ["N_NIMCALL", - "N_STDCALL", "N_CDECL", "N_SAFECALL", - "N_SYSCALL", # this is probably not correct for all platforms, - # but one can #define it to what one wants - "N_INLINE", "N_NOINLINE", "N_FASTCALL", "N_THISCALL", "N_CLOSURE", "N_NOCONV", - "N_NOCONV" #ccMember is N_NOCONV - ] + when buildNifc: + # XXX not implemented in nifc + ptrType(t) + else: + t & "&" + +when buildNifc: + const + CallingConvToStr: array[TCallingConvention, string] = ["(fastcall)", + "(stdcall)", "(cdecl)", "(safecall)", + "(syscall)", + "(inline)", "(noinline)", "(fastcall)", "(thiscall)", "(fastcall)", "(noconv)", + "(member)" + ] +else: + const + CallingConvToStr: array[TCallingConvention, string] = ["N_NIMCALL", + "N_STDCALL", "N_CDECL", "N_SAFECALL", + "N_SYSCALL", # this is probably not correct for all platforms, + # but one can #define it to what one wants + "N_INLINE", "N_NOINLINE", "N_FASTCALL", "N_THISCALL", "N_CLOSURE", "N_NOCONV", + "N_NOCONV" #ccMember is N_NOCONV + ] proc procPtrTypeUnnamed(rettype, params: Snippet): Snippet = - rettype & "(*)" & params + when buildNifc: + "(proctype . " & params & " " & rettype & " .)" + else: + rettype & "(*)" & params proc procPtrTypeUnnamedNimCall(rettype, params: Snippet): Snippet = - rettype & "(N_RAW_NIMCALL*)" & params + when buildNifc: + "(proctype . " & params & " " & rettype & " (pragmas (fastcall)))" + else: + rettype & "(N_RAW_NIMCALL*)" & params proc procPtrTypeUnnamed(callConv: TCallingConvention, rettype, params: Snippet): Snippet = - CallingConvToStr[callConv] & "_PTR(" & rettype & ", )" & params + when buildNifc: + "(proctype . " & params & " " & rettype & " (pragmas " & CallingConvToStr[callConv] & "))" + else: + CallingConvToStr[callConv] & "_PTR(" & rettype & ", )" & params type CppCaptureKind = enum None, ByReference, ByCopy template addCppLambda(builder: var Builder, captures: CppCaptureKind, params: Snippet, body: typed) = - builder.add("[") - case captures - of None: discard - of ByReference: builder.add("&") - of ByCopy: builder.add("=") - builder.add("] ") - builder.add(params) - builder.addLineEndIndent(" {") - body - builder.addLineEndDedent("}") + when buildNifc: + doAssert false, "not implemented" + else: + builder.add("[") + case captures + of None: discard + of ByReference: builder.add("&") + of ByCopy: builder.add("=") + builder.add("] ") + builder.add(params) + builder.addLineEndIndent(" {") + body + builder.addLineEndDedent("}") proc cCast(typ, value: Snippet): Snippet = - "((" & typ & ") " & value & ")" + when buildNifc: + "(cast " & typ & " " & value & ")" + else: + "((" & typ & ") " & value & ")" proc wrapPar(value: Snippet): Snippet = - # used for expression group, no-op on sexp - "(" & value & ")" + when buildNifc: + value # already wrapped + else: + "(" & value & ")" proc removeSinglePar(value: Snippet): Snippet = - # removes a single paren layer expected to exist, to silence Wparentheses-equality - assert value[0] == '(' and value[^1] == ')' - value[1..^2] + when buildNifc: + value + else: + # removes a single paren layer expected to exist, to silence Wparentheses-equality + assert value[0] == '(' and value[^1] == ')' + value[1..^2] template addCast(builder: var Builder, typ: Snippet, valueBody: typed) = ## adds a cast to `typ` with value built by `valueBody` - builder.add "((" - builder.add typ - builder.add ") " + when buildNifc: + builder.add "(cast " + builder.add typ + builder.add " " + else: + builder.add "((" + builder.add typ + builder.add ") " valueBody builder.add ")" proc cAddr(value: Snippet): Snippet = - "(&" & value & ")" + when buildNifc: + "(addr " & value & ")" + else: + "(&" & value & ")" proc cLabelAddr(value: TLabel): Snippet = - "&&" & value + when buildNifc: + doAssert false, "unimplemented" + else: + "&&" & value proc cDeref(value: Snippet): Snippet = - "(*" & value & ")" + when buildNifc: + "(deref " & value & ")" + else: + "(*" & value & ")" proc subscript(a, b: Snippet): Snippet = - a & "[" & b & "]" + when buildNifc: + "(at " & a & " " & b & ")" + else: + a & "[" & b & "]" proc dotField(a, b: Snippet): Snippet = - a & "." & b + when buildNifc: + "(dot " & a & " " & b & " 0)" + else: + a & "." & b proc derefField(a, b: Snippet): Snippet = - a & "->" & b + when buildNifc: + "(dot " & cDeref(a) & " " & b & " 0)" + else: + a & "->" & b type CallBuilder = object needsComma: bool proc initCallBuilder(builder: var Builder, callee: Snippet): CallBuilder = result = CallBuilder(needsComma: false) - builder.add(callee) - builder.add("(") + when buildNifc: + builder.add("(call ") + builder.add(callee) + builder.add(" ") + else: + builder.add(callee) + builder.add("(") -const cArgumentSeparator = ", " +when buildNifc: + const cArgumentSeparator = " " +else: + const cArgumentSeparator = ", " proc addArgumentSeparator(builder: var Builder) = # no-op on NIFC @@ -115,18 +189,28 @@ template addCall(builder: var Builder, call: out CallBuilder, callee: Snippet, b finishCallBuilder(builder, call) proc addCall(builder: var Builder, callee: Snippet, args: varargs[Snippet]) = - builder.add(callee) - builder.add("(") + when buildNifc: + builder.add("(call ") + builder.add(callee) + builder.add(" ") + else: + builder.add(callee) + builder.add("(") if args.len != 0: builder.add(args[0]) for i in 1 ..< args.len: - builder.add(", ") + builder.add(cArgumentSeparator) builder.add(args[i]) builder.add(")") proc cCall(callee: Snippet, args: varargs[Snippet]): Snippet = - result = callee - result.add("(") + when buildNifc: + result = "(call " + result.add(callee) + result.add(" ") + else: + result = callee + result.add("(") if args.len != 0: result.add(args[0]) for i in 1 ..< args.len: @@ -135,125 +219,248 @@ proc cCall(callee: Snippet, args: varargs[Snippet]): Snippet = result.add(")") proc addSizeof(builder: var Builder, val: Snippet) = - builder.add("sizeof(") + when buildNifc: + builder.add("(sizeof ") + else: + builder.add("sizeof(") builder.add(val) builder.add(")") proc addAlignof(builder: var Builder, val: Snippet) = - builder.add("NIM_ALIGNOF(") + when buildNifc: + builder.add("(alignof ") + else: + builder.add("NIM_ALIGNOF(") builder.add(val) builder.add(")") proc addOffsetof(builder: var Builder, val, member: Snippet) = - builder.add("offsetof(") + when buildNifc: + builder.add("(offsetof ") + else: + builder.add("offsetof(") builder.add(val) - builder.add(", ") + builder.add(cArgumentSeparator) builder.add(member) builder.add(")") template cSizeof(val: Snippet): Snippet = - "sizeof(" & val & ")" + when buildNifc: + "(sizeof " & val & ")" + else: + "sizeof(" & val & ")" template cAlignof(val: Snippet): Snippet = - "NIM_ALIGNOF(" & val & ")" + when buildNifc: + "(alignof " & val & ")" + else: + "NIM_ALIGNOF(" & val & ")" template cOffsetof(val, member: Snippet): Snippet = - "offsetof(" & val & ", " & member & ")" + when buildNifc: + "(offsetof " & val & " " & member & ")" + else: + "offsetof(" & val & ", " & member & ")" type TypedBinaryOp = enum Add, Sub, Mul, Div, Mod Shr, Shl, BitAnd, BitOr, BitXor -const typedBinaryOperators: array[TypedBinaryOp, string] = [ - Add: "+", - Sub: "-", - Mul: "*", - Div: "/", - Mod: "%", - Shr: ">>", - Shl: "<<", - BitAnd: "&", - BitOr: "|", - BitXor: "^" -] +when buildNifc: + const typedBinaryOperators: array[TypedBinaryOp, string] = [ + Add: "add", + Sub: "sub", + Mul: "mul", + Div: "div", + Mod: "mod", + Shr: "shr", + Shl: "shl", + BitAnd: "bitand", + BitOr: "bitor", + BitXor: "bitxor" + ] +else: + const typedBinaryOperators: array[TypedBinaryOp, string] = [ + Add: "+", + Sub: "-", + Mul: "*", + Div: "/", + Mod: "%", + Shr: ">>", + Shl: "<<", + BitAnd: "&", + BitOr: "|", + BitXor: "^" + ] type TypedUnaryOp = enum Neg, BitNot -const typedUnaryOperators: array[TypedUnaryOp, string] = [ - Neg: "-", - BitNot: "~", -] +when buildNifc: + const typedUnaryOperators: array[TypedUnaryOp, string] = [ + Neg: "neg", + BitNot: "bitnot", + ] +else: + const typedUnaryOperators: array[TypedUnaryOp, string] = [ + Neg: "-", + BitNot: "~", + ] type UntypedBinaryOp = enum LessEqual, LessThan, GreaterEqual, GreaterThan, Equal, NotEqual And, Or -const untypedBinaryOperators: array[UntypedBinaryOp, string] = [ - LessEqual: "<=", - LessThan: "<", - GreaterEqual: ">=", - GreaterThan: ">", - Equal: "==", - NotEqual: "!=", - And: "&&", - Or: "||" -] +when buildNifc: + const untypedBinaryOperators: array[UntypedBinaryOp, string] = [ + LessEqual: "le", + LessThan: "lt", + GreaterEqual: "", + GreaterThan: "", + Equal: "eq", + NotEqual: "neq", + And: "and", + Or: "or" + ] +else: + const untypedBinaryOperators: array[UntypedBinaryOp, string] = [ + LessEqual: "<=", + LessThan: "<", + GreaterEqual: ">=", + GreaterThan: ">", + Equal: "==", + NotEqual: "!=", + And: "&&", + Or: "||" + ] type UntypedUnaryOp = enum Not -const untypedUnaryOperators: array[UntypedUnaryOp, string] = [ - Not: "!" -] +when buildNifc: + const untypedUnaryOperators: array[UntypedUnaryOp, string] = [ + Not: "not" + ] +else: + const untypedUnaryOperators: array[UntypedUnaryOp, string] = [ + Not: "!" + ] proc addOp(builder: var Builder, binOp: TypedBinaryOp, t: Snippet, a, b: Snippet) = - builder.add('(') - builder.add(a) - builder.add(' ') - builder.add(typedBinaryOperators[binOp]) - builder.add(' ') - builder.add(b) - builder.add(')') + when buildNifc: + builder.add('(') + builder.add(typedBinaryOperators[binOp]) + builder.add(' ') + builder.add(t) + builder.add(' ') + builder.add(a) + builder.add(' ') + builder.add(b) + builder.add(')') + else: + builder.add('(') + builder.add(a) + builder.add(' ') + builder.add(typedBinaryOperators[binOp]) + builder.add(' ') + builder.add(b) + builder.add(')') proc addOp(builder: var Builder, unOp: TypedUnaryOp, t: Snippet, a: Snippet) = - builder.add('(') - builder.add(typedUnaryOperators[unOp]) - builder.add('(') - builder.add(a) - builder.add("))") + when buildNifc: + builder.add('(') + builder.add(typedUnaryOperators[binOp]) + builder.add(' ') + builder.add(t) + builder.add(' ') + builder.add(a) + builder.add(')') + else: + builder.add('(') + builder.add(typedUnaryOperators[unOp]) + builder.add('(') + builder.add(a) + builder.add("))") proc addOp(builder: var Builder, binOp: UntypedBinaryOp, a, b: Snippet) = - builder.add('(') - builder.add(a) - builder.add(' ') - builder.add(untypedBinaryOperators[binOp]) - builder.add(' ') - builder.add(b) - builder.add(')') + when buildNifc: + case binOp + of GreaterEqual: + builder.add("(not ") + builder.addOp(LessThan, a, b) + builder.add(')') + of GreaterThan: + builder.add("(not ") + builder.addOp(LessEqual, a, b) + builder.add(')') + else: + builder.add('(') + builder.add(untypedBinaryOperators[binOp]) + builder.add(' ') + builder.add(a) + builder.add(' ') + builder.add(b) + builder.add(')') + else: + builder.add('(') + builder.add(a) + builder.add(' ') + builder.add(untypedBinaryOperators[binOp]) + builder.add(' ') + builder.add(b) + builder.add(')') proc addOp(builder: var Builder, unOp: UntypedUnaryOp, a: Snippet) = - builder.add('(') - builder.add(untypedUnaryOperators[unOp]) - builder.add('(') - builder.add(a) - builder.add("))") - -template cOp(binOp: TypedBinaryOp, t: Snippet, a, b: Snippet): Snippet = - '(' & a & ' ' & typedBinaryOperators[binOp] & ' ' & b & ')' - -template cOp(binOp: TypedUnaryOp, t: Snippet, a: Snippet): Snippet = - '(' & typedUnaryOperators[binOp] & '(' & a & "))" - -template cOp(binOp: UntypedBinaryOp, a, b: Snippet): Snippet = - '(' & a & ' ' & untypedBinaryOperators[binOp] & ' ' & b & ')' - -template cOp(binOp: UntypedUnaryOp, a: Snippet): Snippet = - '(' & untypedUnaryOperators[binOp] & '(' & a & "))" + when buildNifc: + builder.add('(') + builder.add(untypedUnaryOperators[unOp]) + builder.add(' ') + builder.add(a) + builder.add(')') + else: + builder.add('(') + builder.add(untypedUnaryOperators[unOp]) + builder.add('(') + builder.add(a) + builder.add("))") + +when buildNifc: + template cOp(binOp: TypedBinaryOp, t: Snippet, a, b: Snippet): Snippet = + '(' & typedBinaryOperators[binOp] & ' ' & t & ' ' & a & ' ' & b & ')' + + template cOp(binOp: TypedUnaryOp, t: Snippet, a: Snippet): Snippet = + '(' & typedUnaryOperators[binOp] & ' ' & t & ' ' & a & ')' + + proc cOp(binOp: UntypedBinaryOp, a, b: Snippet): Snippet = + case binOp + of GreaterEqual: + "(not " & cOp(LessThan, a, b) & ')' + of GreaterThan: + "(not " & cOp(LessEqual, a, b) & ')' + else: + '(' & untypedBinaryOperators[binOp] & ' ' & a & ' ' & b & ')' + + template cOp(binOp: UntypedUnaryOp, a: Snippet): Snippet = + '(' & untypedUnaryOperators[binOp] & ' ' & a & ')' +else: + template cOp(binOp: TypedBinaryOp, t: Snippet, a, b: Snippet): Snippet = + '(' & a & ' ' & typedBinaryOperators[binOp] & ' ' & b & ')' + + template cOp(binOp: TypedUnaryOp, t: Snippet, a: Snippet): Snippet = + '(' & typedUnaryOperators[binOp] & '(' & a & "))" + + template cOp(binOp: UntypedBinaryOp, a, b: Snippet): Snippet = + '(' & a & ' ' & untypedBinaryOperators[binOp] & ' ' & b & ')' + + template cOp(binOp: UntypedUnaryOp, a: Snippet): Snippet = + '(' & untypedUnaryOperators[binOp] & '(' & a & "))" template cIfExpr(cond, a, b: Snippet): Snippet = # XXX used for `min` and `max`, maybe add nifc primitives for these "(" & cond & " ? " & a & " : " & b & ")" template cUnlikely(val: Snippet): Snippet = - "NIM_UNLIKELY(" & val & ")" + when buildNifc: + val # not implemented + else: + "NIM_UNLIKELY(" & val & ")" diff --git a/compiler/cbuilderstmts.nim b/compiler/cbuilderstmts.nim index 57872be06846e..f0943172ceca3 100644 --- a/compiler/cbuilderstmts.nim +++ b/compiler/cbuilderstmts.nim @@ -1,14 +1,24 @@ template addAssignmentWithValue(builder: var Builder, lhs: Snippet, valueBody: typed) = - builder.add(lhs) - builder.add(" = ") - valueBody - builder.addLineEnd(";") + when buildNifc: + builder.add("(asgn ") + builder.add(lhs) + builder.add(' ') + valueBody + builder.addLineEnd(")") + else: + builder.add(lhs) + builder.add(" = ") + valueBody + builder.addLineEnd(";") template addFieldAssignmentWithValue(builder: var Builder, lhs: Snippet, name: string, valueBody: typed) = - builder.add(lhs) - builder.add("." & name & " = ") - valueBody - builder.addLineEnd(";") + when buildNifc: + builder.addAssignmentWithValue(dotField(lhs, name), valueBody) + else: + builder.add(lhs) + builder.add("." & name & " = ") + valueBody + builder.addLineEnd(";") template addAssignment(builder: var Builder, lhs, rhs: Snippet) = builder.addAssignmentWithValue(lhs): @@ -20,8 +30,11 @@ template addFieldAssignment(builder: var Builder, lhs: Snippet, name: string, rh template addMutualFieldAssignment(builder: var Builder, lhs, rhs: Snippet, name: string) = builder.addFieldAssignmentWithValue(lhs, name): - builder.add(rhs) - builder.add("." & name) + when buildNifc: + builder.add(dotField(rhs, name)) + else: + builder.add(rhs) + builder.add("." & name) template addAssignment(builder: var Builder, lhs: Snippet, rhs: int | int64 | uint64 | Int128) = builder.addAssignmentWithValue(lhs): @@ -32,48 +45,74 @@ template addFieldAssignment(builder: var Builder, lhs: Snippet, name: string, rh builder.addIntValue(rhs) template addDerefFieldAssignment(builder: var Builder, lhs: Snippet, name: string, rhs: Snippet) = - builder.add(lhs) - builder.add("->" & name & " = ") - builder.add(rhs) - builder.addLineEnd(";") + when buildNifc: + builder.addAssignment(derefField(lhs, name), rhs) + else: + builder.add(lhs) + builder.add("->" & name & " = ") + builder.add(rhs) + builder.addLineEnd(";") template addSubscriptAssignment(builder: var Builder, lhs: Snippet, index: Snippet, rhs: Snippet) = - builder.add(lhs) - builder.add("[" & index & "] = ") - builder.add(rhs) - builder.addLineEnd(";") + when buildNifc: + builder.addAssignment(subscript(lhs, index), rhs) + else: + builder.add(lhs) + builder.add("[" & index & "] = ") + builder.add(rhs) + builder.addLineEnd(";") template addStmt(builder: var Builder, stmtBody: typed) = ## makes an expression built by `stmtBody` into a statement stmtBody - builder.addLineEnd(";") + when buildNifc: + builder.addNewline() + else: + builder.addLineEnd(";") proc addCallStmt(builder: var Builder, callee: Snippet, args: varargs[Snippet]) = builder.addStmt(): builder.addCall(callee, args) -# XXX blocks need indent tracker in `Builder` object - template addSingleIfStmt(builder: var Builder, cond: Snippet, body: typed) = - builder.add("if (") - builder.add(cond) - builder.addLineEndIndent(") {") - body - builder.addLineEndDedent("}") + when buildNifc: + builder.add("(if (elif ") + builder.add(cond) + builder.addLineEndIndent(" (stmts") + body + builder.addLineEndDedent(")))") + else: + builder.add("if (") + builder.add(cond) + builder.addLineEndIndent(") {") + body + builder.addLineEndDedent("}") template addSingleIfStmtWithCond(builder: var Builder, condBody: typed, body: typed) = - builder.add("if (") - condBody - builder.addLineEndIndent(") {") - body - builder.addLineEndDedent("}") + when buildNifc: + builder.add("(if (elif ") + condBody + builder.addLineEndIndent(" (stmts") + body + builder.addLineEndDedent(")))") + else: + builder.add("if (") + condBody + builder.addLineEndIndent(") {") + body + builder.addLineEndDedent("}") proc initIfStmt(builder: var Builder): IfBuilder = + when buildNifc: + builder.add("(if") IfBuilder(state: WaitingIf) proc finishIfStmt(builder: var Builder, stmt: IfBuilder) = assert stmt.state != InBlock - builder.addNewline() + when buildNifc: + builder.addLineEnd(")") + else: + builder.addNewline() template addIfStmt(builder: var Builder, stmt: out IfBuilder, body: typed) = stmt = initIfStmt(builder) @@ -81,23 +120,37 @@ template addIfStmt(builder: var Builder, stmt: out IfBuilder, body: typed) = finishIfStmt(builder, stmt) proc initElifBranch(builder: var Builder, stmt: var IfBuilder, cond: Snippet) = - case stmt.state - of WaitingIf: - builder.add("if (") - of WaitingElseIf: - builder.add(" else if (") - else: assert false, $stmt.state - builder.add(cond) - builder.addLineEndIndent(") {") + when buildNifc: + case stmt.state + of WaitingIf, WaitingElseIf: + builder.add(" (elif ") + else: assert false, $stmt.state + builder.add(cond) + builder.addLineEndIndent(" (stmts") + else: + case stmt.state + of WaitingIf: + builder.add("if (") + of WaitingElseIf: + builder.add(" else if (") + else: assert false, $stmt.state + builder.add(cond) + builder.addLineEndIndent(") {") stmt.state = InBlock proc initElseBranch(builder: var Builder, stmt: var IfBuilder) = assert stmt.state == WaitingElseIf, $stmt.state - builder.addLineEndIndent(" else {") + when buildNifc: + builder.addLineEndIndent(" (else (stmts") + else: + builder.addLineEndIndent(" else {") stmt.state = InBlock proc finishBranch(builder: var Builder, stmt: var IfBuilder) = - builder.addDedent("}") + when buildNifc: + builder.addDedent("))") + else: + builder.addDedent("}") stmt.state = WaitingElseIf template addElifBranch(builder: var Builder, stmt: var IfBuilder, cond: Snippet, body: typed) = @@ -110,66 +163,213 @@ template addElseBranch(builder: var Builder, stmt: var IfBuilder, body: typed) = body finishBranch(builder, stmt) +type WhileBuilder = object + inside: bool + +proc initWhileStmt(builder: var Builder, cond: Snippet): WhileBuilder = + when buildNifc: + builder.add("(while ") + builder.add(cond) + builder.addLineEndIndent(" (stmts") + else: + builder.add("while (") + builder.add(cond) + builder.addLineEndIndent(") {") + result = WhileBuilder(inside: true) + +proc finishWhileStmt(builder: var Builder, stmt: var WhileBuilder) = + assert stmt.inside, "while stmt not inited" + when buildNifc: + builder.addLineEndDedent("))") + else: + builder.addLineEndDedent("}") + stmt.inside = false + +template addWhileStmt(builder: var Builder, cond: Snippet, body: typed) = + when buildNifc: + builder.add("(while ") + builder.add(cond) + builder.addLineEndIndent(" (stmts") + body + builder.addLineEndDedent("))") + else: + builder.add("while (") + builder.add(cond) + builder.addLineEndIndent(") {") + body + builder.addLineEndDedent("}") + +proc addInPlaceOp(builder: var Builder, binOp: TypedBinaryOp, t: Snippet, a, b: Snippet) = + when buildNifc: + builder.addAssignmentWithValue(a): + builder.addOp(binOp, t, a, b) + else: + builder.add(a) + builder.add(' ') + builder.add(typedBinaryOperators[binOp]) + builder.add("= ") + builder.add(b) + builder.addLineEnd(";") + +proc addInPlaceOp(builder: var Builder, binOp: UntypedBinaryOp, a, b: Snippet) = + when buildNifc: + builder.addAssignmentWithValue(a): + builder.addOp(binOp, a, b) + else: + builder.add(a) + builder.add(' ') + builder.add(untypedBinaryOperators[binOp]) + builder.add("= ") + builder.add(b) + builder.addLineEnd(";") + +proc cInPlaceOp(binOp: TypedBinaryOp, t: Snippet, a, b: Snippet): Snippet = + when buildNifc: + result = "(asgn " & a & ' ' & cOp(binOp, t, a, b) & ')' + else: + result = "" + result.add(a) + result.add(' ') + result.add(typedBinaryOperators[binOp]) + result.add("= ") + result.add(b) + result.add(";\n") + +proc cInPlaceOp(binOp: UntypedBinaryOp, a, b: Snippet): Snippet = + when buildNifc: + result = "(asgn " & a & ' ' & cOp(binOp, a, b) & ')' + else: + result = "" + result.add(a) + result.add(' ') + result.add(untypedBinaryOperators[binOp]) + result.add("= ") + result.add(b) + result.add(";\n") + +proc addIncr(builder: var Builder, val, typ: Snippet) = + when buildNifc: + builder.addInPlaceOp(Add, typ, val, cIntValue(1)) + else: + builder.add(val) + builder.addLineEnd("++;") + +proc addDecr(builder: var Builder, val, typ: Snippet) = + when buildNifc: + builder.addInPlaceOp(Sub, typ, val, cIntValue(1)) + else: + builder.add(val) + builder.addLineEnd("--;") + proc initForRange(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.addLineEndIndent("++) {") + when buildNifc: + builder.addAssignment(i, start) + builder.add("(while (") + if inclusive: + builder.add("le ") + else: + builder.add("lt ") + builder.add(i) + builder.add(' ') + builder.add(bound) + builder.addLineEndIndent(") (stmts") + else: + 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.addLineEndIndent("++) {") proc initForStep(builder: var Builder, i, start, bound, step: 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(" += ") - builder.add(step) - builder.addLineEndIndent(") {") - -proc finishFor(builder: var Builder) {.inline.} = - builder.addLineEndDedent("}") - -template addForRangeExclusive(builder: var Builder, i, start, bound: Snippet, body: typed) = + when buildNifc: + builder.addAssignment(i, start) + builder.add("(while (") + if inclusive: + builder.add("le ") + else: + builder.add("lt ") + builder.add(i) + builder.add(' ') + builder.add(bound) + builder.addLineEndIndent(") (stmts") + else: + 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(" += ") + builder.add(step) + builder.addLineEndIndent(") {") + +proc finishForRange(builder: var Builder, i, typ: Snippet) {.inline.} = + when buildNifc: + builder.addIncr(i, typ) + builder.addLineEndDedent("))") + else: + builder.addLineEndDedent("}") + +proc finishForStep(builder: var Builder, i, step, typ: Snippet) {.inline.} = + when buildNifc: + builder.addInPlaceOp(Add, typ, i, step) + builder.addLineEndDedent("))") + else: + builder.addLineEndDedent("}") + +template addForRangeExclusive(builder: var Builder, i, start, bound, typ: Snippet, body: typed) = initForRange(builder, i, start, bound, false) body - finishFor(builder) + finishForRange(builder, i, typ) -template addForRangeInclusive(builder: var Builder, i, start, bound: Snippet, body: typed) = +template addForRangeInclusive(builder: var Builder, i, start, bound, typ: Snippet, body: typed) = initForRange(builder, i, start, bound, true) body - finishFor(builder) + finishForRange(builder, i, typ) template addSwitchStmt(builder: var Builder, val: Snippet, body: typed) = - builder.add("switch (") - builder.add(val) - builder.addLineEnd(") {") # no indent - body - builder.addLineEnd("}") + when buildNifc: + builder.add("(case ") + builder.add(val) + builder.addNewline() # no indent + body + builder.addLineEnd(")") + else: + builder.add("switch (") + builder.add(val) + builder.addLineEnd(") {") # no indent + body + builder.addLineEnd("}") template addSingleSwitchCase(builder: var Builder, val: Snippet, body: typed) = - builder.add("case ") - builder.add(val) - builder.addLineEndIndent(":") - body - builder.addLineEndDedent("") + when buildNifc: + builder.add("(of (ranges ") + builder.add(val) + builder.addLineEndIndent(") (stmts") + body + builder.addLineEndDedent("))") + else: + builder.add("case ") + builder.add(val) + builder.addLineEndIndent(":") + body + builder.addLineEndDedent("") type SwitchCaseState = enum @@ -177,153 +377,165 @@ type SwitchCaseBuilder = object state: SwitchCaseState +template addCaseRanges(builder: var Builder, info: var SwitchCaseBuilder, body: typed) = + if info.state != Of: + assert info.state == None + info.state = Of + when buildNifc: + builder.add("(of (ranges") + body + when buildNifc: + builder.addLineEndIndent(") (stmts") + 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.addLineEndIndent(":") + when buildNifc: + builder.add(" ") + builder.add(val) + else: + builder.add("case ") + builder.add(val) + builder.addLineEndIndent(":") 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.addLineEndIndent(":") + when buildNifc: + builder.add(" (range ") + builder.add(first) + builder.add(" ") + builder.add(last) + builder.add(")") + else: + builder.add("case ") + builder.add(first) + builder.add(" ... ") + builder.add(last) + builder.addLineEndIndent(":") proc addCaseElse(builder: var Builder, info: var SwitchCaseBuilder) = assert info.state == None info.state = Else - builder.addLineEndIndent("default:") + when buildNifc: + builder.addLineEndIndent("(else (stmts") + else: + builder.addLineEndIndent("default:") template addSwitchCase(builder: var Builder, info: out SwitchCaseBuilder, caseBody, body: typed) = info = SwitchCaseBuilder(state: None) caseBody info.state = Finished body - builder.addLineEndDedent("") + when buildNifc: + builder.addLineEndDedent("))") + else: + builder.addLineEndDedent("") template addSwitchElse(builder: var Builder, body: typed) = - builder.addLineEndIndent("default:") - body - builder.addLineEndDedent("") + when buildNifc: + builder.addLineEndIndent("(else (stmts") + body + builder.addLineEndDedent("))") + else: + builder.addLineEndIndent("default:") + body + builder.addLineEndDedent("") proc addBreak(builder: var Builder) = - builder.addLineEnd("break;") + when buildNifc: + builder.addLineEnd("(break)") + else: + builder.addLineEnd("break;") type ScopeBuilder = object inside: bool proc initScope(builder: var Builder): ScopeBuilder = - builder.addLineEndIndent("{") + when buildNifc: + builder.addLineEndIndent("(scope (stmts") + else: + builder.addLineEndIndent("{") result = ScopeBuilder(inside: true) proc finishScope(builder: var Builder, scope: var ScopeBuilder) = assert scope.inside, "scope not inited" - builder.addLineEndDedent("}") + when buildNifc: + builder.addLineEndDedent("))") + else: + builder.addLineEndDedent("}") scope.inside = false template addScope(builder: var Builder, body: typed) = - builder.addLineEndIndent("{") - body - builder.addLineEndDedent("}") - -type WhileBuilder = object - inside: bool - -proc initWhileStmt(builder: var Builder, cond: Snippet): WhileBuilder = - builder.add("while (") - builder.add(cond) - builder.addLineEndIndent(") {") - result = WhileBuilder(inside: true) - -proc finishWhileStmt(builder: var Builder, stmt: var WhileBuilder) = - assert stmt.inside, "while stmt not inited" - builder.addLineEndDedent("}") - stmt.inside = false - -template addWhileStmt(builder: var Builder, cond: Snippet, body: typed) = - builder.add("while (") - builder.add(cond) - builder.addLineEndIndent(") {") - body - builder.addLineEndDedent("}") + when buildNifc: + builder.addLineEndIndent("(scope (stmts") + body + builder.addLineEndDedent("))") + else: + builder.addLineEndIndent("{") + body + builder.addLineEndDedent("}") proc addLabel(builder: var Builder, name: TLabel) = - builder.add(name) - builder.addLineEnd(": ;") + when buildNifc: + builder.add("(lab ") + builder.add(name) + builder.addLineEnd(")") + else: + builder.add(name) + builder.addLineEnd(": ;") proc addReturn(builder: var Builder) = - builder.addLineEnd("return;") + when buildNifc: + builder.addLineEnd("(ret .)") + else: + builder.addLineEnd("return;") proc addReturn(builder: var Builder, value: Snippet) = - builder.add("return ") - builder.add(value) - builder.addLineEnd(";") + when buildNifc: + builder.add("(ret ") + builder.add(value) + builder.addLineEnd(")") + else: + builder.add("return ") + builder.add(value) + builder.addLineEnd(";") proc addGoto(builder: var Builder, label: TLabel) = - builder.add("goto ") - builder.add(label) - builder.addLineEnd(";") + when buildNifc: + builder.add("(jmp ") + builder.add(label) + builder.addLineEnd(")") + else: + builder.add("goto ") + builder.add(label) + builder.addLineEnd(";") proc addComputedGoto(builder: var Builder, value: Snippet) = - builder.add("goto *") - builder.add(value) - builder.addLineEnd(";") - -proc addIncr(builder: var Builder, val: Snippet) = - builder.add(val) - builder.addLineEnd("++;") - -proc addDecr(builder: var Builder, val: Snippet) = - builder.add(val) - builder.addLineEnd("--;") - -proc addInPlaceOp(builder: var Builder, binOp: TypedBinaryOp, t: Snippet, a, b: Snippet) = - builder.add(a) - builder.add(' ') - builder.add(typedBinaryOperators[binOp]) - builder.add("= ") - builder.add(b) - builder.addLineEnd(";") - -proc addInPlaceOp(builder: var Builder, binOp: UntypedBinaryOp, a, b: Snippet) = - builder.add(a) - builder.add(' ') - builder.add(untypedBinaryOperators[binOp]) - builder.add("= ") - builder.add(b) - builder.addLineEnd(";") - -proc cInPlaceOp(binOp: TypedBinaryOp, t: Snippet, a, b: Snippet): Snippet = - result = "" - result.add(a) - result.add(' ') - result.add(typedBinaryOperators[binOp]) - result.add("= ") - result.add(b) - result.add(";\n") - -proc cInPlaceOp(binOp: UntypedBinaryOp, a, b: Snippet): Snippet = - result = "" - result.add(a) - result.add(' ') - result.add(untypedBinaryOperators[binOp]) - result.add("= ") - result.add(b) - result.add(";\n") + when buildNifc: + doAssert false, "not implemented in nifc" + else: + builder.add("goto *") + builder.add(value) + builder.addLineEnd(";") template addCPragma(builder: var Builder, val: Snippet) = - builder.addNewline() - builder.add("#pragma ") - builder.add(val) - builder.addNewline() + when buildNifc: + doAssert false, "not implememented in nifc" + else: + builder.addNewline() + builder.add("#pragma ") + builder.add(val) + builder.addNewline() proc addDiscard(builder: var Builder, val: Snippet) = - builder.add("(void)") - builder.add(val) - builder.addLineEnd(";") + when buildNifc: + builder.add("(discard ") + builder.add(val) + builder.addLineEnd(")") + else: + builder.add("(void)") + builder.add(val) + builder.addLineEnd(";") diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 1aa66cc73eb53..1ce3a336dbeda 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1565,7 +1565,7 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) = var dest = initLoc(locExpr, e[2], OnHeap) var tmpL = getIntTemp(p) p.s(cpsStmts).addAssignment(tmpL.snippet, lenField(p, ra)) - p.s(cpsStmts).addIncr(lenField(p, ra)) + p.s(cpsStmts).addIncr(lenField(p, ra), NimInt) dest.snippet = subscript(dataField(p, ra), tmpL.snippet) genAssignment(p, dest, b, {needToCopy}) gcUsage(p.config, e) @@ -1935,7 +1935,7 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) = genAssignment(p, elem, arr, {needToCopy}) else: var i: TLoc = getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt)) - p.s(cpsStmts).addForRangeExclusive(i.snippet, cIntValue(0), cIntValue(L)): + p.s(cpsStmts).addForRangeExclusive(i.snippet, cIntValue(0), cIntValue(L), NimInt): elem = initLoc(locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), OnHeap) elem.snippet = subscript(dataField(p, rdLoc(d)), rdLoc(i)) elem.storage = OnHeap # we know that sequences are on the heap @@ -2432,7 +2432,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) = let rd = rdLoc(d) let ra = rdLoc(a) let rb = rdLoc(b) - p.s(cpsStmts).addForRangeExclusive(ri, cIntValue(0), cIntValue(size)): + p.s(cpsStmts).addForRangeExclusive(ri, cIntValue(0), cIntValue(size), NimInt): p.s(cpsStmts).addAssignment(rd, cOp(Equal, cOp(BitAnd, NimUint8, subscript(ra, ri), @@ -2466,7 +2466,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) = let rd = rdLoc(d) let ra = rdLoc(a) let rb = rdLoc(b) - p.s(cpsStmts).addForRangeExclusive(ri, cIntValue(0), cIntValue(size)): + p.s(cpsStmts).addForRangeExclusive(ri, cIntValue(0), cIntValue(size), NimInt): p.s(cpsStmts).addAssignmentWithValue(subscript(rd, ri)): let x = subscript(ra, ri) let y = subscript(rb, ri) @@ -3074,7 +3074,7 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) = rdSetElemLoc(p.config, b, e.typ, bb) let ri = rdLoc(idx) let rd = rdLoc(d) - p.s(cpsStmts).addForRangeInclusive(ri, aa, bb): + p.s(cpsStmts).addForRangeInclusive(ri, aa, bb, NimInt): p.s(cpsStmts).addInPlaceOp(BitOr, NimUint8, subscript(rd, cOp(Shr, NimUint, cCast(NimUint, ri), cIntValue(3))), cOp(Shl, NimUint8, cUintValue(1), @@ -3103,7 +3103,7 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) = rdSetElemLoc(p.config, b, e.typ, bb) let ri = rdLoc(idx) let rd = rdLoc(d) - p.s(cpsStmts).addForRangeInclusive(ri, aa, bb): + p.s(cpsStmts).addForRangeInclusive(ri, aa, bb, NimInt): p.s(cpsStmts).addInPlaceOp(BitOr, ts, rd, cOp(Shl, ts, cCast(ts, cIntValue(1)), cOp(Mod, ts, ri, cOp(Mul, ts, cIntValue(size), cIntValue(8))))) diff --git a/compiler/ccgreset.nim b/compiler/ccgreset.nim index 7b0d61926133a..9818a9bbd43c5 100644 --- a/compiler/ccgreset.nim +++ b/compiler/ccgreset.nim @@ -61,7 +61,7 @@ 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)) - p.s(cpsStmts).addForRangeExclusive(i.snippet, cIntValue(0), cIntValue(arraySize)): + p.s(cpsStmts).addForRangeExclusive(i.snippet, cIntValue(0), cIntValue(arraySize), NimInt): specializeResetT(p, subscript(accessor, i.snippet), typ.elementType) of tyObject: var x = typ.baseClass diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 5a4de33b164e1..e5fb1bfd18ecd 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -768,16 +768,21 @@ proc genParForStmt(p: BProc, t: PNode) = stepNode = call[3] p.s(cpsStmts).addCPragma("omp " & call[4].getStr) + let iTyp = getTypeDesc(p.module, forLoopVar.loc.t) + var step: TLoc = default(TLoc) p.breakIdx = startBlockWith(p): if stepNode == nil: initForRange(p.s(cpsStmts), forLoopVar.loc.rdLoc, rangeA.rdLoc, rangeB.rdLoc, true) else: - var step: TLoc = initLocExpr(p, stepNode) + step = initLocExpr(p, stepNode) initForStep(p.s(cpsStmts), forLoopVar.loc.rdLoc, rangeA.rdLoc, rangeB.rdLoc, step.rdLoc, true) p.blocks[p.breakIdx].isLoop = true genStmts(p, t[2]) endBlockWith(p): - finishFor(p.s(cpsStmts)) + if stepNode == nil: + finishForRange(p.s(cpsStmts), forLoopVar.loc.rdLoc, iTyp) + else: + finishForStep(p.s(cpsStmts), forLoopVar.loc.rdLoc, step.rdLoc, iTyp) dec(p.withinLoop) @@ -1037,25 +1042,26 @@ proc ifSwitchSplitPoint(p: BProc, n: PNode): int = result = i proc genCaseRange(p: BProc, branch: PNode, info: var SwitchCaseBuilder) = - for j in 0..