diff --git a/compiler/cbuilderbase.nim b/compiler/cbuilderbase.nim index d0ffbd791eb1..3cb42bbd95c3 100644 --- a/compiler/cbuilderbase.nim +++ b/compiler/cbuilderbase.nim @@ -1,4 +1,6 @@ -import ropes, int128 +import ropes, int128, std/formatfloat + +const buildNifc* = defined(nimCompileToNifc) type Snippet* = string @@ -43,119 +45,237 @@ proc addLineEndDedent*(builder: var Builder, s: string) = builder.addNewline() proc addLineComment*(builder: var Builder, comment: string) = - # probably no-op on nifc - builder.add("// ") - builder.add(comment) - builder.addNewline() + when not buildNifc: + builder.add("// ") + builder.add(comment) + builder.addNewline() proc addIntValue*(builder: var Builder, val: int) = + when buildNifc: + if val >= 0: + builder.buf.add('+') builder.buf.addInt(val) proc addIntValue*(builder: var Builder, val: int64) = + when buildNifc: + if val >= 0: + builder.buf.add('+') builder.buf.addInt(val) proc addIntValue*(builder: var Builder, val: uint64) = + when buildNifc: + builder.buf.add('+') builder.buf.addInt(val) proc addIntValue*(builder: var Builder, val: Int128) = + when buildNifc: + if val >= 0: + builder.buf.add('+') builder.buf.addInt128(val) -template cIntValue*(val: int): Snippet = $val -template cIntValue*(val: int64): Snippet = $val -template cIntValue*(val: uint64): Snippet = $val -template cIntValue*(val: Int128): Snippet = $val - -template cUintValue*(val: uint): Snippet = $val & "U" - -import std/formatfloat - -proc addFloatValue*(builder: var Builder, val: float) = - builder.buf.addFloat(val) - -template cFloatValue*(val: float): Snippet = $val +when not buildNifc: + template cIntValue*(val: int): Snippet = $val + template cIntValue*(val: int64): Snippet = $val + template cIntValue*(val: uint64): Snippet = $val + template cIntValue*(val: Int128): Snippet = $val + + template cUintValue*(val: uint): Snippet = $val & "U" + + proc addFloatValue*(builder: var Builder, val: float) = + builder.buf.addFloat(val) + + template cFloatValue*(val: float): Snippet = $val +else: + proc cIntValue*(val: int): Snippet = + result = if val >= 0: "+" else: "" + result.addInt(val) + proc cIntValue*(val: int64): Snippet = + result = if val >= 0: "+" else: "" + result.addInt(val) + proc cIntValue*(val: uint64): Snippet = + result = "+" + result.addInt(val) + proc cIntValue*(val: Int128): Snippet = + result = if val >= 0: "+" else: "" + result.addInt128(val) + proc cUintValue*(val: uint): Snippet = + result = "+" + result.addInt(val) + result.add('u') + + import std/math + + proc addFloatValue*(builder: var Builder, val: float) = + let kind = classify(val) + case kind + of fcNan: + builder.buf.add("(nan)") + of fcInf: + builder.buf.add("(inf)") + of fcNegInf: + builder.buf.add("(neginf)") + else: + if val >= 0: + builder.buf.add("+") + builder.buf.addFloat(val) + + proc cFloatValue*(val: float): Snippet = + let kind = classify(val) + case kind + of fcNan: + result = "(nan)" + of fcInf: + result = "(inf)" + of fcNegInf: + result = "(neginf)" + else: + result = if val >= 0: "+" else: "-" + result.addFloat(val) proc addInt64Literal*(result: var Builder; i: BiggestInt) = - if i > low(int64): - result.add "IL64($1)" % [rope(i)] + when buildNifc: + result.add("(suf ") + result.addIntValue(i) + result.add(" \"i64\")") else: - result.add "(IL64(-9223372036854775807) - IL64(1))" + if i > low(int64): + result.add "IL64($1)" % [rope(i)] + else: + result.add "(IL64(-9223372036854775807) - IL64(1))" proc addUint64Literal*(result: var Builder; i: uint64) = - result.add rope($i & "ULL") + when buildNifc: + result.add("(suf ") + result.addIntValue(i) + result.add('u') + result.add(" \"u64\")") + else: + result.add rope($i & "ULL") proc addIntLiteral*(result: var Builder; i: BiggestInt) = - if i > low(int32) and i <= high(int32): + when buildNifc: + # nifc handles this result.addIntValue(i) - elif i == low(int32): - # Nim has the same bug for the same reasons :-) - result.add "(-2147483647 -1)" - elif i > low(int64): - result.add "IL64($1)" % [rope(i)] else: - result.add "(IL64(-9223372036854775807) - IL64(1))" + if i > low(int32) and i <= high(int32): + result.addIntValue(i) + elif i == low(int32): + # Nim has the same bug for the same reasons :-) + result.add "(-2147483647 -1)" + elif i > low(int64): + result.add "IL64($1)" % [rope(i)] + else: + result.add "(IL64(-9223372036854775807) - IL64(1))" proc addIntLiteral*(result: var Builder; i: Int128) = addIntLiteral(result, toInt64(i)) proc cInt64Literal*(i: BiggestInt): Snippet = - if i > low(int64): - result = "IL64($1)" % [rope(i)] + when buildNifc: + result = "(suf " & cIntValue(i) & " \"i64\")" else: - result = "(IL64(-9223372036854775807) - IL64(1))" + if i > low(int64): + result = "IL64($1)" % [rope(i)] + else: + result = "(IL64(-9223372036854775807) - IL64(1))" proc cUint64Literal*(i: uint64): Snippet = - result = $i & "ULL" + when buildNifc: + result = "(suf " & cUintValue(i) & " \"u64\")" + else: + result = $i & "ULL" proc cIntLiteral*(i: BiggestInt): Snippet = - if i > low(int32) and i <= high(int32): - result = rope(i) - elif i == low(int32): - # Nim has the same bug for the same reasons :-) - result = "(-2147483647 -1)" - elif i > low(int64): - result = "IL64($1)" % [rope(i)] + when buildNifc: + result = cIntValue(i) else: - result = "(IL64(-9223372036854775807) - IL64(1))" + if i > low(int32) and i <= high(int32): + result = rope(i) + elif i == low(int32): + # Nim has the same bug for the same reasons :-) + result = "(-2147483647 -1)" + elif i > low(int64): + result = "IL64($1)" % [rope(i)] + else: + result = "(IL64(-9223372036854775807) - IL64(1))" proc cIntLiteral*(i: Int128): Snippet = result = cIntLiteral(toInt64(i)) -const - NimInt* = "NI" - NimInt8* = "NI8" - NimInt16* = "NI16" - NimInt32* = "NI32" - NimInt64* = "NI64" - CInt* = "int" - NimUint* = "NU" - NimUint8* = "NU8" - NimUint16* = "NU16" - NimUint32* = "NU32" - NimUint64* = "NU64" - NimFloat* = "NF" - NimFloat32* = "NF32" - NimFloat64* = "NF64" - NimFloat128* = "NF128" # not actually defined - NimNan* = "NAN" - NimInf* = "INF" - NimBool* = "NIM_BOOL" - NimTrue* = "NIM_TRUE" - NimFalse* = "NIM_FALSE" - NimChar* = "NIM_CHAR" - CChar* = "char" - NimCstring* = "NCSTRING" - NimNil* = "NIM_NIL" - CNil* = "NULL" - NimStrlitFlag* = "NIM_STRLIT_FLAG" - CVoid* = "void" - CPointer* = "void*" - CConstPointer* = "NIM_CONST void*" +when buildNifc: + const + NimInt* = "(i -1)" + NimInt8* = "(i +8)" + NimInt16* = "(i +16)" + NimInt32* = "(i +32)" + NimInt64* = "(i +64)" + CInt* = "(i +32)" # int.c + NimUint* = "(u -1)" + NimUint8* = "(u +8)" + NimUint16* = "(u +16)" + NimUint32* = "(u +32)" + NimUint64* = "(u +64)" + NimFloat* = "(f +64)" + NimFloat32* = "(f +32)" + NimFloat64* = "(f +64)" + NimFloat128* = "(f +128)" + NimNan* = "(nan)" + NimInf* = "(inf)" + NimBool* = "(bool)" + NimTrue* = "(true)" + NimFalse* = "(false)" + NimChar* = "(c +8)" + CChar* = "(c +8)" # char.c + NimCstring* = "(ptr (c +8))" + NimNil* = "(nil)" + CNil* = "(nil)" # NULL.c + NimStrlitFlag* = "NIM_STRLIT_FLAG" # XXX + CVoid* = "(void)" + CPointer* = "(ptr (void))" + CConstPointer* = "(ptr (void))" # (void (ro)) illegal +else: + const + NimInt* = "NI" + NimInt8* = "NI8" + NimInt16* = "NI16" + NimInt32* = "NI32" + NimInt64* = "NI64" + CInt* = "int" + NimUint* = "NU" + NimUint8* = "NU8" + NimUint16* = "NU16" + NimUint32* = "NU32" + NimUint64* = "NU64" + NimFloat* = "NF" + NimFloat32* = "NF32" + NimFloat64* = "NF64" + NimFloat128* = "NF128" # not actually defined + NimNan* = "NAN" + NimInf* = "INF" + NimBool* = "NIM_BOOL" + NimTrue* = "NIM_TRUE" + NimFalse* = "NIM_FALSE" + NimChar* = "NIM_CHAR" + CChar* = "char" + NimCstring* = "NCSTRING" + NimNil* = "NIM_NIL" + CNil* = "NULL" + NimStrlitFlag* = "NIM_STRLIT_FLAG" + CVoid* = "void" + CPointer* = "void*" + CConstPointer* = "NIM_CONST void*" proc cIntType*(bits: BiggestInt): Snippet = - "NI" & $bits + when buildNifc: + "(i +" & $bits & ")" + else: + "NI" & $bits proc cUintType*(bits: BiggestInt): Snippet = - "NU" & $bits + when buildNifc: + "(u +" & $bits & ")" + else: + "NU" & $bits type IfBuilderState* = enum diff --git a/compiler/cbuilderdecls.nim b/compiler/cbuilderdecls.nim index 0b170c71838a..8e977f4ae37e 100644 --- a/compiler/cbuilderdecls.nim +++ b/compiler/cbuilderdecls.nim @@ -13,115 +13,203 @@ proc addVarHeader(builder: var Builder, kind: VarKind) = ## AlwaysConst has `static const` modifier (NIM_CONST is no-op on C++) ## Threadvar is unimplemented case kind - of Local: discard + of Local: + when buildNifc: + builder.add("var ") of Global: - builder.add("static ") + when buildNifc: + builder.add("gvar ") + else: + builder.add("static ") of Const: - builder.add("static NIM_CONST ") + when buildNifc: + builder.add("const ") + else: + builder.add("static NIM_CONST ") of AlwaysConst: - builder.add("static const ") + when buildNifc: + builder.add("const ") + else: + builder.add("static const ") of Threadvar: - doAssert false, "unimplemented" + when buildNifc: + builder.add("tvar ") + else: + doAssert false, "unimplemented" proc addVar(builder: var Builder, kind: VarKind = Local, name: string, typ: Snippet, initializer: Snippet = "") = ## adds a variable declaration to the builder - builder.addVarHeader(kind) - builder.add(typ) - builder.add(" ") - builder.add(name) - if initializer.len != 0: - builder.add(" = ") - builder.add(initializer) - builder.addLineEnd(";") - -template addVarWithType(builder: var Builder, kind: VarKind = Local, name: string, body: typed) = - ## adds a variable declaration to the builder, with the `body` building the type - builder.addVarHeader(kind) - body - builder.add(" ") - builder.add(name) - builder.addLineEnd(";") + when buildNifc: + builder.add("(") + builder.addVarHeader(kind) + builder.add(":") + builder.add(name) + builder.add(" . ") # pragmas + builder.add(typ) + builder.add(" ") + if initializer.len != 0: + builder.add(initializer) + else: + builder.add(".") + builder.addLineEnd(")") + else: + builder.addVarHeader(kind) + builder.add(typ) + builder.add(" ") + builder.add(name) + if initializer.len != 0: + builder.add(" = ") + builder.add(initializer) + builder.addLineEnd(";") template addVarWithInitializer(builder: var Builder, kind: VarKind = Local, name: string, typ: Snippet, initializerBody: typed) = ## adds a variable declaration to the builder, with ## `initializerBody` building the initializer. initializer must be provided - builder.addVarHeader(kind) - builder.add(typ) - builder.add(" ") - builder.add(name) - builder.add(" = ") - initializerBody - builder.addLineEnd(";") - -template addVarWithTypeAndInitializer(builder: var Builder, kind: VarKind = Local, name: string, - typeBody, initializerBody: typed) = - ## adds a variable declaration to the builder, with `typeBody` building the type, and - ## `initializerBody` building the initializer. initializer must be provided - builder.addVarHeader(kind) - typeBody - builder.add(" ") - builder.add(name) - builder.add(" = ") - initializerBody - builder.addLineEnd(";") - -proc addArrayVar(builder: var Builder, kind: VarKind = Local, name: string, elementType: Snippet, len: int, initializer: Snippet = "") = - ## adds an array variable declaration to the builder - builder.addVarHeader(kind) - builder.add(elementType) - builder.add(" ") - builder.add(name) - builder.add("[") - builder.addIntValue(len) - builder.add("]") - if initializer.len != 0: + when buildNifc: + builder.add("(") + builder.addVarHeader(kind) + builder.add(":") + builder.add(name) + builder.add(" . ") # pragmas + builder.add(typ) + builder.add(" ") + initializerBody + builder.addLineEnd(")") + else: + builder.addVarHeader(kind) + builder.add(typ) + builder.add(" ") + builder.add(name) builder.add(" = ") - builder.add(initializer) - builder.addLineEnd(";") + initializerBody + builder.addLineEnd(";") + +when buildNifc: + proc getArrayType(m: BModule, elementType: Snippet, len: int): Snippet = + let key = (elementType, len) + if key in m.arrayTypes: + result = m.arrayTypes[key] + else: + result = elementType & "_Arr_" & $len + m.s[cfsTypes].add("(type :") + m.s[cfsTypes].add(result) + m.s[cfsTypes].add(" (array ") + m.s[cfsTypes].add(elementType) + m.s[cfsTypes].add(" ") + m.s[cfsTypes].add(cIntValue(len)) + m.s[cfsTypes].addLineEnd("))") + m.arrayTypes[key] = result + +proc addArrayVar(builder: var Builder, m: BModule, kind: VarKind = Local, name: string, elementType: Snippet, len: int, initializer: Snippet = "") = + ## adds an array variable declaration to the builder + when buildNifc: + builder.add("(") + builder.addVarHeader(kind) + builder.add(":") + builder.add(name) + builder.add(" . ") # pragmas + builder.add(getArrayType(m, elementType, len)) + builder.add(" ") + if initializer.len != 0: + builder.add(initializer) + else: + builder.add(".") + builder.addLineEnd(")") + else: + builder.addVarHeader(kind) + builder.add(elementType) + builder.add(" ") + builder.add(name) + builder.add("[") + builder.addIntValue(len) + builder.add("]") + if initializer.len != 0: + builder.add(" = ") + builder.add(initializer) + builder.addLineEnd(";") -template addArrayVarWithInitializer(builder: var Builder, kind: VarKind = Local, name: string, elementType: Snippet, len: int, body: typed) = +template addArrayVarWithInitializer(builder: var Builder, m: BModule, kind: VarKind = Local, name: string, elementType: Snippet, len: int, body: typed) = ## adds an array variable declaration to the builder with the initializer built according to `body` - builder.addVarHeader(kind) - builder.add(elementType) - builder.add(" ") - builder.add(name) - builder.add("[") - builder.addIntValue(len) - builder.add("] = ") - body - builder.addLineEnd(";") + when buildNifc: + builder.add("(") + builder.addVarHeader(kind) + builder.add(":") + builder.add(name) + builder.add(" . ") # pragmas + builder.add(getArrayType(m, elementType, len)) + builder.add(" ") + body + builder.addLineEnd(")") + else: + builder.addVarHeader(kind) + builder.add(elementType) + builder.add(" ") + builder.add(name) + builder.add("[") + builder.addIntValue(len) + builder.add("] = ") + body + builder.addLineEnd(";") template addTypedef(builder: var Builder, name: string, typeBody: typed) = ## adds a typedef declaration to the builder with name `name` and type as ## built in `typeBody` - builder.add("typedef ") - typeBody - builder.add(" ") - builder.add(name) - builder.addLineEnd(";") + when buildNifc: + builder.add("(type :") + builder.add(name) + builder.add(" ") + typeBody + builder.addLineEnd(")") + else: + builder.add("typedef ") + typeBody + builder.add(" ") + builder.add(name) + builder.addLineEnd(";") proc addProcTypedef(builder: var Builder, callConv: TCallingConvention, name: string, rettype, params: Snippet) = - builder.add("typedef ") - builder.add(CallingConvToStr[callConv]) - builder.add("_PTR(") - builder.add(rettype) - builder.add(", ") - builder.add(name) - builder.add(")") - builder.add(params) - builder.addLineEnd(";") + when buildNifc: + builder.add("(type :") + builder.add(name) + builder.add(" (proctype . ") + builder.add(params) + builder.add(" ") + builder.add(rettype) + builder.add(" (pragmas ") + # XXX varargs goes here + builder.add(CallingConvToStr[callConv]) + builder.addLineEnd(")))") + else: + builder.add("typedef ") + builder.add(CallingConvToStr[callConv]) + builder.add("_PTR(") + builder.add(rettype) + builder.add(", ") + builder.add(name) + builder.add(")") + builder.add(params) + builder.addLineEnd(";") template addArrayTypedef(builder: var Builder, name: string, len: BiggestInt, typeBody: typed) = ## adds an array typedef declaration to the builder with name `name`, ## length `len`, and element type as built in `typeBody` - builder.add("typedef ") - typeBody - builder.add(" ") - builder.add(name) - builder.add("[") - builder.addIntValue(len) - builder.addLineEnd("];") + when buildNifc: + builder.add("(type :") + builder.add(name) + builder.add(" (array ") + typeBody + builder.add(" ") + builder.addIntValue(len) + builder.addLineEnd("))") + else: + builder.add("typedef ") + typeBody + builder.add(" ") + builder.add(name) + builder.add("[") + builder.addIntValue(len) + builder.addLineEnd("];") type StructInitializerKind = enum @@ -139,14 +227,23 @@ type proc initStructInitializer(builder: var Builder, kind: StructInitializerKind): StructInitializer = ## starts building a struct initializer, i.e. braced initializer list result = StructInitializer(kind: kind, needsComma: false) - if kind != siWrapper: - builder.add("{") + when buildNifc: + case kind + of siOrderedStruct, siNamedStruct: + builder.add("(oconstr ") + of siArray: + builder.add("(aconstr ") + of siWrapper: discard + else: + if kind != siWrapper: + builder.add("{") template addField(builder: var Builder, constr: var StructInitializer, name: string, valueBody: typed) = ## adds a field to a struct initializer, with the value built in `valueBody` if constr.needsComma: assert constr.kind != siWrapper, "wrapper constructor cannot have multiple fields" - builder.add(", ") + when not buildNifc: + builder.add(", ") else: constr.needsComma = true case constr.kind @@ -156,18 +253,34 @@ template addField(builder: var Builder, constr: var StructInitializer, name: str of siOrderedStruct: # no name, can just add value on C assert name.len != 0, "name has to be given for struct initializer field" + when buildNifc: + builder.add("(kv ") + builder.add(name) + builder.add(" ") valueBody + when buildNifc: + builder.add(")") of siNamedStruct: assert name.len != 0, "name has to be given for struct initializer field" - builder.add(".") - builder.add(name) - builder.add(" = ") + when buildNifc: + builder.add("(kv ") + builder.add(name) + builder.add(" ") + else: + builder.add(".") + builder.add(name) + builder.add(" = ") valueBody + when buildNifc: + builder.add(")") proc finishStructInitializer(builder: var Builder, constr: StructInitializer) = ## finishes building a struct initializer if constr.kind != siWrapper: - builder.add("}") + when buildNifc: + builder.add(")") + else: + builder.add("}") template addStructInitializer(builder: var Builder, constr: out StructInitializer, kind: StructInitializerKind, body: typed) = ## builds a struct initializer, i.e. `{ field1, field2 }` @@ -177,61 +290,119 @@ template addStructInitializer(builder: var Builder, constr: out StructInitialize body builder.finishStructInitializer(constr) -proc addField(obj: var Builder; name, typ: Snippet; isFlexArray: bool = false; initializer: Snippet = "") = +proc addField(obj: var Builder; name, typ: Snippet; isFlexArray: bool = false) = ## adds a field inside a struct/union type - obj.add('\t') - obj.add(typ) - obj.add(" ") - obj.add(name) - if isFlexArray: - obj.add("[SEQ_DECL_SIZE]") - if initializer.len != 0: - obj.add(initializer) - obj.add(";\n") - -proc addArrayField(obj: var Builder; name, elementType: Snippet; len: int; initializer: Snippet = "") = + when buildNifc: + obj.add("\n\t(fld :") + obj.add(name) + obj.add(" . ") # pragmas + if isFlexArray: + obj.add("(flexarray ") + obj.add(typ) + obj.add(")") + else: + obj.add(typ) + obj.add(")") + else: + obj.add('\t') + obj.add(typ) + obj.add(" ") + obj.add(name) + if isFlexArray: + obj.add("[SEQ_DECL_SIZE]") + obj.add(";\n") + +proc addArrayField(obj: var Builder; m: BModule, name, elementType: Snippet; len: int) = ## adds an array field inside a struct/union type - obj.add('\t') - obj.add(elementType) - obj.add(" ") - obj.add(name) - obj.add("[") - obj.addIntValue(len) - obj.add("]") - if initializer.len != 0: - obj.add(initializer) - obj.add(";\n") - -proc addField(obj: var Builder; field: PSym; name, typ: Snippet; isFlexArray: bool = false; initializer: Snippet = "") = + when buildNifc: + obj.add("\n\t(fld :") + obj.add(name) + obj.add(" . ") # pragmas + obj.add(getArrayType(elementType, len)) + obj.add(")") + else: + obj.add('\t') + obj.add(elementType) + obj.add(" ") + obj.add(name) + obj.add("[") + obj.addIntValue(len) + obj.add("];\n") + +proc addField(obj: var Builder; field: PSym; name, typ: Snippet; isFlexArray: bool = false; cppInitializer: Snippet = "") = ## adds an field inside a struct/union type, based on an `skField` symbol - obj.add('\t') - if field.alignment > 0: - obj.add("NIM_ALIGN(") - obj.addIntValue(field.alignment) - obj.add(") ") - obj.add(typ) - if sfNoalias in field.flags: - obj.add(" NIM_NOALIAS") - obj.add(" ") - obj.add(name) - if isFlexArray: - obj.add("[SEQ_DECL_SIZE]") - if field.bitsize != 0: - obj.add(":") - obj.addIntValue(field.bitsize) - if initializer.len != 0: - obj.add(initializer) - obj.add(";\n") + when buildNifc: + obj.add("\n\t(fld :") + obj.add(name) + var pragmasInner = "" + if field.alignment > 0: + pragmasInner.add("(align ") + pragmasInner.addIntValue(field.alignment) + pragmasInner.add(")") + if field.bitsize != 0: + if pragmasInner.len != 0: pragmasInner.add(" ") + pragmasInner.add("(bits ") + pragmasInner.addIntValue(field.bitsize) + pragmasInner.add(")") + if sfNoalias in field.flags: + when false: # XXX not implemented in NIFC + if pragmasInner.len != 0: pragmasInner.add(" ") + pragmasInner.add("(restrict)") + if pragmasInner.len != 0: + obj.add(" (") + obj.add(pragmasInner) + obj.add(") ") + else: + obj.add(" . ") + if isFlexArray: + obj.add("(flexarray ") + obj.add(typ) + obj.add("))") + else: + obj.add(typ) + obj.add(")") + doAssert cppInitializer.len == 0, "cpp initializer unsupported in nifc" + else: + obj.add('\t') + if field.alignment > 0: + obj.add("NIM_ALIGN(") + obj.addIntValue(field.alignment) + obj.add(") ") + obj.add(typ) + if sfNoalias in field.flags: + obj.add(" NIM_NOALIAS") + obj.add(" ") + obj.add(name) + if isFlexArray: + obj.add("[SEQ_DECL_SIZE]") + if field.bitsize != 0: + obj.add(":") + obj.addIntValue(field.bitsize) + if cppInitializer.len != 0: + obj.add(cppInitializer) + obj.add(";\n") proc addProcField(obj: var Builder, callConv: TCallingConvention, name: string, rettype, params: Snippet) = - obj.add(CallingConvToStr[callConv]) - obj.add("_PTR(") - obj.add(rettype) - obj.add(", ") - obj.add(name) - obj.add(")") - obj.add(params) - obj.add(";\n") + when buildNifc: + obj.add("(fld :") + obj.add(name) + obj.add(" . (proctype . ") + obj.add(params) + obj.add(" ") + obj.add(rettype) + obj.add(" (pragmas ") + # XXX varargs goes here + obj.add(CallingConvToStr[callConv]) + obj.addLineEnd(")))") + else: + obj.add(CallingConvToStr[callConv]) + obj.add("_PTR(") + obj.add(rettype) + obj.add(", ") + obj.add(name) + obj.add(")") + obj.add(params) + obj.add(";\n") type BaseClassKind = enum @@ -246,24 +417,43 @@ type proc structOrUnion(t: PType): Snippet = let t = t.skipTypes({tyAlias, tySink}) if tfUnion in t.flags: "union" - else: "struct" + else: + when buildNifc: + "object" + else: + "struct" proc startSimpleStruct(obj: var Builder; m: BModule; name: string; baseType: Snippet): StructBuilderInfo = result = StructBuilderInfo(baseKind: bcNone, named: name.len != 0) - obj.add("struct") - if result.named: + when buildNifc: + if result.named: + obj.add("(type :") + obj.add(name) + obj.add(" (object ") + if baseType.len != 0: + if m.compileToCpp: + result.baseKind = bcCppInherit + else: + result.baseKind = bcSupField + obj.add(baseType) + obj.add(" ") + else: + obj.add(". ") + else: + obj.add("struct") + if result.named: + obj.add(" ") + obj.add(name) + if baseType.len != 0: + if m.compileToCpp: + result.baseKind = bcCppInherit + else: + result.baseKind = bcSupField + if result.baseKind == bcCppInherit: + obj.add(" : public ") + obj.add(baseType) obj.add(" ") - obj.add(name) - if baseType.len != 0: - if m.compileToCpp: - result.baseKind = bcCppInherit - else: - result.baseKind = bcSupField - if result.baseKind == bcCppInherit: - obj.add(" : public ") - obj.add(baseType) - obj.add(" ") - obj.add("{\n") + obj.add("{\n") result.preFieldsLen = obj.buf.len if result.baseKind == bcSupField: obj.addField(name = "Sup", typ = baseType) @@ -273,9 +463,15 @@ proc finishSimpleStruct(obj: var Builder; m: BModule; info: StructBuilderInfo) = # no fields were added, add dummy field obj.addField(name = "dummy", typ = CChar) if info.named: - obj.add("};\n") + when buildNifc: + obj.add("))\n") + else: + obj.add("};\n") else: - obj.add("}") + when buildNifc: + obj.add(")") + else: + obj.add("}") template addSimpleStruct(obj: var Builder; m: BModule; name: string; baseType: Snippet; body: typed) = ## builds a struct type not based on a Nim type with fields according to `body`, @@ -286,18 +482,31 @@ template addSimpleStruct(obj: var Builder; m: BModule; name: string; baseType: S proc startStruct(obj: var Builder; m: BModule; t: PType; name: string; baseType: Snippet): StructBuilderInfo = result = StructBuilderInfo(baseKind: bcNone, named: name.len != 0) - if tfPacked in t.flags: - if hasAttribute in CC[m.config.cCompiler].props: + when buildNifc: + # XXX no attributes for object types in NIFC + if result.named: + obj.add("(type :") + obj.add(name) + obj.add(" (") obj.add(structOrUnion(t)) - obj.add(" __attribute__((__packed__))") + obj.add(" ") else: - obj.add("#pragma pack(push, 1)\n") + obj.add("(") obj.add(structOrUnion(t)) + obj.add(" ") else: - obj.add(structOrUnion(t)) - if result.named: - obj.add(" ") - obj.add(name) + if tfPacked in t.flags: + if hasAttribute in CC[m.config.cCompiler].props: + obj.add(structOrUnion(t)) + obj.add(" __attribute__((__packed__))") + else: + obj.add("#pragma pack(push, 1)\n") + obj.add(structOrUnion(t)) + else: + obj.add(structOrUnion(t)) + if result.named: + obj.add(" ") + obj.add(name) if t.kind == tyObject: if t.baseClass == nil: if lacksMTypeField(t): @@ -315,11 +524,18 @@ proc startStruct(obj: var Builder; m: BModule; t: PType; name: string; baseType: result.baseKind = bcCppInherit else: result.baseKind = bcSupField - if result.baseKind == bcCppInherit: - obj.add(" : public ") - obj.add(baseType) - obj.add(" ") - obj.add("{\n") + when buildNifc: + if baseType.len != 0: + obj.add(baseType) + obj.add(" ") + else: + obj.add(". ") + else: + if result.baseKind == bcCppInherit: + obj.add(" : public ") + obj.add(baseType) + obj.add(" ") + obj.add("{\n") result.preFieldsLen = obj.buf.len case result.baseKind of bcNone: @@ -345,11 +561,18 @@ proc finishStruct(obj: var Builder; m: BModule; t: PType; info: StructBuilderInf # no fields were added, add dummy field obj.addField(name = "dummy", typ = CChar) if info.named: - obj.add("};\n") + when buildNifc: + obj.add("))\n") + else: + obj.add("};\n") else: - obj.add("}") - if tfPacked in t.flags and hasAttribute notin CC[m.config.cCompiler].props: - obj.add("#pragma pack(pop)\n") + when buildNifc: + obj.add(")") + else: + obj.add("}") + when not buildNifc: + if tfPacked in t.flags and hasAttribute notin CC[m.config.cCompiler].props: + obj.add("#pragma pack(pop)\n") template addStruct(obj: var Builder; m: BModule; typ: PType; name: string; baseType: Snippet; body: typed) = ## builds a struct type directly based on `typ` with fields according to `body`, @@ -358,34 +581,60 @@ template addStruct(obj: var Builder; m: BModule; typ: PType; name: string; baseT body finishStruct(obj, m, typ, info) -template addFieldWithStructType(obj: var Builder; m: BModule; parentTyp: PType; fieldName: string, body: typed) = - ## adds a field with a `struct { ... }` type, building the fields according to `body` - obj.add('\t') - if tfPacked in parentTyp.flags: - if hasAttribute in CC[m.config.cCompiler].props: - obj.add("struct __attribute__((__packed__)) {\n") - else: - obj.add("#pragma pack(push, 1)\nstruct {") +proc addFieldStruct(obj: var Builder; m: BModule; parentTyp: PType; name: string, fields: Snippet) = + ## see `genRecordFieldsAux` for use + when buildNifc: + # XXX packed not implemented in nifc + obj.addTypedef(name): + obj.addSimpleStruct(m, "", ""): + obj.add(fields) else: - obj.add("struct {\n") - body - obj.add("} ") - obj.add(fieldName) - obj.add(";\n") - if tfPacked in parentTyp.flags and hasAttribute notin CC[m.config.cCompiler].props: - obj.add("#pragma pack(pop)\n") - -template addAnonUnion(obj: var Builder; body: typed) = - ## adds an anonymous union i.e. `union { ... };` with fields according to `body` - obj.add "union{\n" - body - obj.add("};\n") + obj.add('\t') + if tfPacked in parentTyp.flags: + if hasAttribute in CC[m.config.cCompiler].props: + obj.add("typedef struct __attribute__((__packed__)) ") + else: + obj.add("#pragma pack(push, 1)\ntypedef struct ") + else: + obj.add("typedef struct ") + obj.add(name) + obj.add(" {\n") + obj.add(fields) + obj.add("} ") + obj.add(name) + obj.add(";\n") + if tfPacked in parentTyp.flags and hasAttribute notin CC[m.config.cCompiler].props: + obj.add("#pragma pack(pop)\n") -template addUnionType(obj: var Builder; body: typed) = - ## adds a union type i.e. `union { ... }` with fields according to `body` - obj.add "union{\n" +template addUnion(obj: var Builder; name: string; body: typed) = + let named = name.len != 0 + when buildNifc: + if named: + obj.add("(type :") + obj.add(name) + obj.add(" (union . ") + else: + obj.add("(union . ") + else: + if named: + obj.add("typedef union ") + obj.add(name) + obj.add(" {\n") + else: + obj.add("union {\n") body - obj.add("}") + when buildNifc: + if named: + obj.add("))\n") + else: + obj.add(")\n") + else: + if named: + obj.add("} ") + obj.add(name) + obj.add(";\n") + else: + obj.add("}") type DeclVisibility = enum None @@ -399,95 +648,176 @@ type DeclVisibility = enum proc addVisibilityPrefix(builder: var Builder, visibility: DeclVisibility) = # internal proc - case visibility - of None: discard - of Extern: - builder.add("extern ") - of ExternC: - builder.add("NIM_EXTERNC ") - of ImportLib: - builder.add("N_LIB_IMPORT ") - of ExportLib: - builder.add("N_LIB_EXPORT ") - of ExportLibVar: - builder.add("N_LIB_EXPORT_VAR ") - of Private: - builder.add("N_LIB_PRIVATE ") - of StaticProc: - builder.add("static ") + when buildNifc: + case visibility + of None: discard + of Extern: + builder.add("(imp ") + of ExternC, ImportLib, ExportLib, ExportLibVar: + doAssert false, "visibility " & $visibility & " not supported in NIFC" + of Private, StaticProc: + # also not supported but can just be ignored + discard + else: + case visibility + of None: discard + of Extern: + builder.add("extern ") + of ExternC: + builder.add("NIM_EXTERNC ") + of ImportLib: + builder.add("N_LIB_IMPORT ") + of ExportLib: + builder.add("N_LIB_EXPORT ") + of ExportLibVar: + builder.add("N_LIB_EXPORT_VAR ") + of Private: + builder.add("N_LIB_PRIVATE ") + of StaticProc: + builder.add("static ") + +proc addVisibilitySuffix(builder: var Builder, visibility: DeclVisibility) = + when buildNifc: + case visibility + of None: discard + of Extern: + builder.addLineEnd(")") + of ExternC, ImportLib, ExportLib, ExportLibVar: + doAssert false, "visibility " & $visibility & " not supported in NIFC" + of Private, StaticProc: + # also not supported but can just be ignored + discard template addDeclWithVisibility(builder: var Builder, visibility: DeclVisibility, declBody: typed) = ## adds a declaration as in `declBody` with the given visibility builder.addVisibilityPrefix(visibility) declBody + builder.addVisibilitySuffix(visibility) type ProcParamBuilder = object needsComma: bool proc initProcParamBuilder(builder: var Builder): ProcParamBuilder = result = ProcParamBuilder(needsComma: false) - builder.add("(") + when buildNifc: + builder.add("(params ") + else: + builder.add("(") proc finishProcParamBuilder(builder: var Builder, params: ProcParamBuilder) = - if params.needsComma: + when buildNifc: builder.add(")") else: - builder.add("void)") + if params.needsComma: + builder.add(")") + else: + builder.add("void)") template cgDeclFrmt*(s: PSym): string = s.constraint.strVal proc addParam(builder: var Builder, params: var ProcParamBuilder, name: string, typ: Snippet) = if params.needsComma: - builder.add(", ") + when buildNifc: + builder.add(" ") + else: + builder.add(", ") else: params.needsComma = true - builder.add(typ) - builder.add(" ") - builder.add(name) + when buildNifc: + builder.add("(param :") + builder.add(name) + builder.add(" . ") + builder.add(typ) + builder.add(")") + else: + builder.add(typ) + builder.add(" ") + builder.add(name) proc addParam(builder: var Builder, params: var ProcParamBuilder, param: PSym, typ: Snippet) = if params.needsComma: - builder.add(", ") + when buildNifc: + builder.add(" ") + else: + builder.add(", ") else: params.needsComma = true - var modifiedTyp = typ - if sfNoalias in param.flags: - modifiedTyp.add(" NIM_NOALIAS") - if sfCodegenDecl notin param.flags: - builder.add(modifiedTyp) - builder.add(" ") - builder.add(param.loc.snippet) + when buildNifc: + # XXX noalias not implemented in nifc + if sfCodegenDecl notin param.flags: + builder.add("(param :") + builder.add(param.loc.snippet) + builder.add(" . ") + builder.add(typ) + builder.add(")") + else: + doAssert false, "codegendecl not supported on NIFC" else: - builder.add runtimeFormat(param.cgDeclFrmt, [modifiedTyp, param.loc.snippet]) + var modifiedTyp = typ + if sfNoalias in param.flags: + modifiedTyp.add(" NIM_NOALIAS") + if sfCodegenDecl notin param.flags: + builder.add(modifiedTyp) + builder.add(" ") + builder.add(param.loc.snippet) + else: + builder.add runtimeFormat(param.cgDeclFrmt, [modifiedTyp, param.loc.snippet]) proc addUnnamedParam(builder: var Builder, params: var ProcParamBuilder, typ: Snippet) = if params.needsComma: - builder.add(", ") + when buildNifc: + builder.add(" ") + else: + builder.add(", ") else: params.needsComma = true - builder.add(typ) + when buildNifc: + builder.add("(param . . ") + builder.add(typ) + builder.add(")") + else: + builder.add(typ) proc addProcTypedParam(builder: var Builder, paramBuilder: var ProcParamBuilder, callConv: TCallingConvention, name: string, rettype, params: Snippet) = if paramBuilder.needsComma: - builder.add(", ") + when buildNifc: + builder.add(" ") + else: + builder.add(", ") else: paramBuilder.needsComma = true - builder.add(CallingConvToStr[callConv]) - builder.add("_PTR(") - builder.add(rettype) - builder.add(", ") - builder.add(name) - builder.add(")") - builder.add(params) + when buildNifc: + builder.add("(param :") + builder.add(name) + builder.add(" . (proctype . ") + builder.add(params) + builder.add(" ") + builder.add(rettype) + # XXX varargs goes here + builder.add(" (pragmas ") + builder.add(CallingConvToStr[callConv]) + builder.add(")))") + else: + builder.add(CallingConvToStr[callConv]) + builder.add("_PTR(") + builder.add(rettype) + builder.add(", ") + builder.add(name) + builder.add(")") + builder.add(params) proc addVarargsParam(builder: var Builder, params: var ProcParamBuilder) = # does not exist in NIFC, needs to be proc pragma - if params.needsComma: - builder.add(", ") + when buildNifc: + # XXX not implemented + discard else: - params.needsComma = true - builder.add("...") + if params.needsComma: + builder.add(", ") + else: + params.needsComma = true + builder.add("...") template addProcParams(builder: var Builder, params: out ProcParamBuilder, body: typed) = params = initProcParamBuilder(builder) @@ -498,171 +828,300 @@ type SimpleProcParam = tuple name, typ: string proc cProcParams(params: varargs[SimpleProcParam]): Snippet = - if params.len == 0: return "(void)" - result = "(" - for i in 0 ..< params.len: - if i != 0: result.add(", ") - result.add(params[i].typ) - if params[i].name.len != 0: - result.add(" ") - result.add(params[i].name) - result.add(")") + when buildNifc: + result = "(params" + for i in 0 ..< params.len: + result.add(" (param ") + if params[i].name.len != 0: + result.add(":") + result.add(params[i].name) + else: + result.add(".") + result.add(" . ") + result.add(params[i].typ) + result.add(")") + result.add(")") + else: + if params.len == 0: return "(void)" + result = "(" + for i in 0 ..< params.len: + if i != 0: result.add(", ") + result.add(params[i].typ) + if params[i].name.len != 0: + result.add(" ") + result.add(params[i].name) + result.add(")") 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(")") + when buildNifc: + builder.add("(proc :") + builder.add(name) + builder.add(" ") + else: + builder.add(CallingConvToStr[callConv]) + builder.add("(") + builder.add(rettype) + builder.add(", ") + builder.add(name) + builder.add(")") paramBuilder + when buildNifc: + builder.add(" ") + builder.add(rettype) + builder.add(" (pragmas ") + # XXX varargs goes here + builder.add(CallingConvToStr[callConv]) + builder.add(") ") 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, name: string, rettype, params: Snippet, isConstructor = false) = # no callconv - builder.add(rettype) - builder.add(" ") - if isConstructor: - builder.add("__attribute__((constructor)) ") - builder.add(name) - builder.add(params) + when buildNifc: + builder.add("(proc :") + builder.add(name) + builder.add(" ") + builder.add(params) + builder.add(" ") + builder.add(rettype) + if isConstructor: + builder.add(" (pragmas (attr \"constructor\")) ") + else: + builder.add(" . ") + else: + builder.add(rettype) + builder.add(" ") + if isConstructor: + builder.add("__attribute__((constructor)) ") + builder.add(name) + 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) ") - if noreturn and hasDeclspec in extccomp.CC[m.config.cCompiler].props: - builder.add("__declspec(noreturn) ") - builder.add(CallingConvToStr[prc.typ.callConv]) - builder.add("(") - builder.add(rettype) - builder.add(", ") - builder.add(name) - builder.add(")") - builder.add(params) - if addAttributes: - if sfPure in prc.flags and hasAttribute in extccomp.CC[m.config.cCompiler].props: - builder.add(" __attribute__((naked))") - if noreturn and hasAttribute in extccomp.CC[m.config.cCompiler].props: - builder.add(" __attribute__((noreturn))") + when buildNifc: + # XXX no declspec on nifc + builder.add("(proc :") + builder.add(name) + builder.add(" ") + builder.add(params) + builder.add(" ") + builder.add(rettype) + builder.add(" (pragmas ") + builder.add(CallingConvToStr[prc.typ.callConv]) + if addAttributes: + if sfPure in prc.flags and hasAttribute in extccomp.CC[m.config.cCompiler].props: + builder.add(" (attr \"naked\")") + if noreturn and hasAttribute in extccomp.CC[m.config.cCompiler].props: + builder.add(" (attr \"noreturn\")") + builder.add(") ") + else: + if sfPure in prc.flags and hasDeclspec in extccomp.CC[m.config.cCompiler].props: + builder.add("__declspec(naked) ") + if noreturn and hasDeclspec in extccomp.CC[m.config.cCompiler].props: + builder.add("__declspec(noreturn) ") + builder.add(CallingConvToStr[prc.typ.callConv]) + builder.add("(") + builder.add(rettype) + builder.add(", ") + builder.add(name) + builder.add(")") + builder.add(params) + if addAttributes: + if sfPure in prc.flags and hasAttribute in extccomp.CC[m.config.cCompiler].props: + builder.add(" __attribute__((naked))") + if noreturn and hasAttribute in extccomp.CC[m.config.cCompiler].props: + builder.add(" __attribute__((noreturn))") proc finishProcHeaderAsProto(builder: var Builder) = - builder.addLineEnd(";") + when buildNifc: + builder.addLineEnd(".)") + else: + builder.addLineEnd(";") template finishProcHeaderWithBody(builder: var Builder, body: typed) = - builder.addLineEndIndent(" {") - body - builder.addLineEndDedent("}") - builder.addNewline + when buildNifc: + builder.addLineEndIndent(" (stmts") + body + builder.addLineEndDedent("))") + else: + builder.addLineEndIndent(" {") + body + builder.addLineEndDedent("}") + builder.addNewline() proc addProcVar(builder: var Builder, m: BModule, prc: PSym, name: string, params, rettype: Snippet, isStatic = false, ignoreAttributes = false) = - # on nifc, builds full variable - if isStatic: - builder.add("static ") let noreturn = isNoReturn(m, prc) - if not ignoreAttributes: - if sfPure in prc.flags and hasDeclspec in extccomp.CC[m.config.cCompiler].props: - builder.add("__declspec(naked) ") - if noreturn and hasDeclspec in extccomp.CC[m.config.cCompiler].props: - builder.add("__declspec(noreturn) ") - builder.add(CallingConvToStr[prc.typ.callConv]) - builder.add("_PTR(") - builder.add(rettype) - builder.add(", ") - builder.add(name) - builder.add(")") - builder.add(params) - if not ignoreAttributes: - if sfPure in prc.flags and hasAttribute in extccomp.CC[m.config.cCompiler].props: - builder.add(" __attribute__((naked))") - if noreturn and hasAttribute in extccomp.CC[m.config.cCompiler].props: - builder.add(" __attribute__((noreturn))") - # ensure we are just adding a variable: - builder.addLineEnd(";") + when buildNifc: + # XXX declspec not supported in NIFC + builder.add("(") + builder.addVarHeader(if isStatic: Global else: Local) + builder.add(" :") + builder.add(name) + builder.add(" . (proctype . ") + builder.add(params) + builder.add(" ") + builder.add(rettype) + builder.add(" (pragmas ") + builder.add(CallingConvToStr[prc.typ.callConv]) + if not ignoreAttributes: + if sfPure in prc.flags and hasAttribute in extccomp.CC[m.config.cCompiler].props: + builder.add(" (attr \"naked\")") + if noreturn and hasAttribute in extccomp.CC[m.config.cCompiler].props: + builder.add(" (attr \"noreturn\")") + # ensure we are just adding a variable: + builder.addLineEnd(")) .)") + else: + if isStatic: + builder.add("static ") + if not ignoreAttributes: + if sfPure in prc.flags and hasDeclspec in extccomp.CC[m.config.cCompiler].props: + builder.add("__declspec(naked) ") + if noreturn and hasDeclspec in extccomp.CC[m.config.cCompiler].props: + builder.add("__declspec(noreturn) ") + builder.add(CallingConvToStr[prc.typ.callConv]) + builder.add("_PTR(") + builder.add(rettype) + builder.add(", ") + builder.add(name) + builder.add(")") + builder.add(params) + if not ignoreAttributes: + if sfPure in prc.flags and hasAttribute in extccomp.CC[m.config.cCompiler].props: + builder.add(" __attribute__((naked))") + if noreturn and hasAttribute in extccomp.CC[m.config.cCompiler].props: + builder.add(" __attribute__((noreturn))") + # ensure we are just adding a variable: + builder.addLineEnd(";") proc addProcVar(builder: var Builder, callConv: TCallingConvention, name: string, params, rettype: Snippet, isStatic = false, isVolatile = false) = - # on nifc, builds full variable - if isStatic: - builder.add("static ") - builder.add(CallingConvToStr[callConv]) - builder.add("_PTR(") - builder.add(rettype) - builder.add(", ") - if isVolatile: - builder.add("volatile ") - builder.add(name) - builder.add(")") - builder.add(params) - # ensure we are just adding a variable: - builder.addLineEnd(";") + when buildNifc: + # XXX volatile not supported in nifc + builder.add("(") + builder.addVarHeader(if isStatic: Global else: Local) + builder.add(" :") + builder.add(name) + builder.add(" . (proctype . ") + builder.add(params) + builder.add(" ") + builder.add(rettype) + builder.add(" (pragmas ") + builder.add(CallingConvToStr[callConv]) + # ensure we are just adding a variable: + builder.addLineEnd(")) .)") + else: + if isStatic: + builder.add("static ") + builder.add(CallingConvToStr[callConv]) + builder.add("_PTR(") + builder.add(rettype) + builder.add(", ") + if isVolatile: + builder.add("volatile ") + builder.add(name) + builder.add(")") + builder.add(params) + # ensure we are just adding a variable: + builder.addLineEnd(";") proc addProcVar(builder: var Builder, name: string, params, rettype: Snippet, isStatic = false, isVolatile = false) = # no callconv - if isStatic: - builder.add("static ") - builder.add(rettype) - builder.add(" (*") - if isVolatile: - builder.add("volatile ") - builder.add(name) - builder.add(")") - builder.add(params) - # ensure we are just adding a variable: - builder.addLineEnd(";") + when buildNifc: + # XXX volatile not supported in nifc + builder.add("(") + builder.addVarHeader(if isStatic: Global else: Local) + builder.add(" :") + builder.add(name) + builder.add(" . (proctype . ") + builder.add(params) + builder.add(" ") + builder.add(rettype) + builder.add(" .) .)") + else: + if isStatic: + builder.add("static ") + builder.add(rettype) + builder.add(" (*") + if isVolatile: + builder.add("volatile ") + builder.add(name) + builder.add(")") + builder.add(params) + # ensure we are just adding a variable: + builder.addLineEnd(";") type VarInitializerKind = enum Assignment, CppConstructor proc addVar(builder: var Builder, m: BModule, s: PSym, name: string, typ: Snippet, kind = Local, visibility: DeclVisibility = None, initializer: Snippet = "", initializerKind: VarInitializerKind = Assignment) = if sfCodegenDecl in s.flags: - builder.add(runtimeFormat(s.cgDeclFrmt, [typ, name])) + when buildNifc: + doAssert false, "codegendecl not supported in nifc" + else: + builder.add(runtimeFormat(s.cgDeclFrmt, [typ, name])) + if initializer.len != 0: + if initializerKind == Assignment: + builder.add(" = ") + builder.add(initializer) + builder.addLineEnd(";") + return + when buildNifc: + builder.addDeclWithVisibility(visibility): + builder.add("(") + builder.addVarHeader(kind) + builder.add(" :") + builder.add(name) + # XXX register, volatile, noalias not implemented in nifc + if s.kind in {skLet, skVar, skField, skForVar} and s.alignment > 0: + builder.add(" (pragmas (align ") + builder.addIntValue(s.alignment) + builder.add(")) ") + else: + builder.add(" . ") + builder.add(typ) + if initializer.len != 0: + # XXX c++ initializers not supported? + builder.add(" ") + builder.add(initializer) + builder.addLineEnd(")") + else: + builder.addLineEnd(" .)") + else: + if s.kind in {skLet, skVar, skField, skForVar} and s.alignment > 0: + builder.add("NIM_ALIGN(" & $s.alignment & ") ") + builder.addVisibilityPrefix(visibility) + if kind == Threadvar: + if optThreads in m.config.globalOptions: + let sym = s.typ.sym + if sym != nil and sfCppNonPod in sym.flags: + builder.add("NIM_THREAD_LOCAL ") + else: builder.add("NIM_THREADVAR ") + else: + builder.addVarHeader(kind) + builder.add(typ) + if sfRegister in s.flags: builder.add(" register") + if sfVolatile in s.flags: builder.add(" volatile") + if sfNoalias in s.flags: builder.add(" NIM_NOALIAS") + builder.add(" ") + builder.add(name) if initializer.len != 0: if initializerKind == Assignment: builder.add(" = ") builder.add(initializer) builder.addLineEnd(";") - return - if s.kind in {skLet, skVar, skField, skForVar} and s.alignment > 0: - builder.add("NIM_ALIGN(" & $s.alignment & ") ") - builder.addVisibilityPrefix(visibility) - if kind == Threadvar: - if optThreads in m.config.globalOptions: - let sym = s.typ.sym - if sym != nil and sfCppNonPod in sym.flags: - builder.add("NIM_THREAD_LOCAL ") - else: builder.add("NIM_THREADVAR ") - else: - builder.addVarHeader(kind) - builder.add(typ) - if sfRegister in s.flags: builder.add(" register") - if sfVolatile in s.flags: builder.add(" volatile") - if sfNoalias in s.flags: builder.add(" NIM_NOALIAS") - builder.add(" ") - builder.add(name) - if initializer.len != 0: - if initializerKind == Assignment: - builder.add(" = ") - builder.add(initializer) - builder.addLineEnd(";") proc addInclude(builder: var Builder, value: Snippet) = - builder.addLineEnd("#include " & value) + when buildNifc: + builder.add("(incl ") + builder.add(makeCString(value)) + builder.addLineEnd(")") + else: + builder.addLineEnd("#include " & value) diff --git a/compiler/cbuilderexprs.nim b/compiler/cbuilderexprs.nim index dce8c65214d9..01cf2b616799 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 57872be06846..f0943172ceca 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/ccgcalls.nim b/compiler/ccgcalls.nim index b18ea017ed37..a2b3a01e8888 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -239,10 +239,13 @@ proc genOpenArraySlice(p: BProc; q: PNode; formalType, destType: PType; prepareF val = cDeref(ra) else: val = ra + var data = getTempName(p.module) + p.s(cpsLocals).addVar(Local, name = data, typ = ptrType(dest), initializer = NimNil) + p.s(cpsStmts).addSingleIfStmt(cOp(NotEqual, dataFieldAccessor(p, val), NimNil)): + p.s(cpsStmts).addAssignment(data, cCast(ptrType(dest), + cOp(Add, NimInt, dataField(p, val), rb))) result = ( - cIfExpr(dataFieldAccessor(p, val), - cCast(ptrType(dest), cOp(Add, NimInt, dataField(p, val), rb)), - NimNil), + data, lengthExpr) else: result = ("", "") @@ -268,7 +271,8 @@ proc openArrayLoc(p: BProc, formalType: PType, n: PNode; result: var Builder) = result.add(y) else: var a = initLocExpr(p, if n.kind == nkHiddenStdConv: n[1] else: n) - case skipTypes(a.t, abstractVar+{tyStatic}).kind + let et = skipTypes(a.t, abstractVar+{tyStatic}) + case et.kind of tyOpenArray, tyVarargs: let ra = rdLoc(a) if reifiedOpenArray(n): @@ -295,13 +299,27 @@ proc openArrayLoc(p: BProc, formalType: PType, n: PNode; result: var Builder) = let ra = a.rdLoc var t = TLoc(snippet: cDeref(ra)) let lt = lenExpr(p, t) - result.add(cIfExpr(dataFieldAccessor(p, t.snippet), dataField(p, t.snippet), NimNil)) + var data = getTempName(p.module) + let payloadTyp = + if et.kind == tyString: ptrType(NimChar) + else: getSeqDataPtrType(p.module, et) + p.s(cpsLocals).addVar(Local, name = data, typ = payloadTyp, initializer = NimNil) + p.s(cpsStmts).addSingleIfStmt(cOp(NotEqual, dataFieldAccessor(p, t.snippet), NimNil)): + p.s(cpsStmts).addAssignment(data, dataField(p, t.snippet)) + result.add(data) result.addArgumentSeparator() result.add(lt) else: let ra = a.rdLoc let la = lenExpr(p, a) - result.add(cIfExpr(dataFieldAccessor(p, ra), dataField(p, ra), NimNil)) + var data = getTempName(p.module) + let payloadTyp = + if et.kind == tyString: ptrType(NimChar) + else: getSeqDataPtrType(p.module, et) + p.s(cpsLocals).addVar(Local, name = data, typ = payloadTyp, initializer = NimNil) + p.s(cpsStmts).addSingleIfStmt(cOp(NotEqual, dataFieldAccessor(p, ra), NimNil)): + p.s(cpsStmts).addAssignment(data, dataField(p, ra)) + result.add(data) result.addArgumentSeparator() result.add(la) of tyArray: @@ -310,12 +328,20 @@ proc openArrayLoc(p: BProc, formalType: PType, n: PNode; result: var Builder) = result.addArgumentSeparator() result.addIntValue(lengthOrd(p.config, a.t)) of tyPtr, tyRef: - case elementType(a.t).kind + let et = elementType(a.t) + case et.kind of tyString, tySequence: let ra = a.rdLoc var t = TLoc(snippet: cDeref(ra)) let lt = lenExpr(p, t) - result.add(cIfExpr(dataFieldAccessor(p, t.snippet), dataField(p, t.snippet), NimNil)) + var data = getTempName(p.module) + let payloadTyp = + if et.kind == tyString: ptrType(NimChar) + else: getSeqDataPtrType(p.module, et) + p.s(cpsLocals).addVar(Local, name = data, typ = payloadTyp, initializer = NimNil) + p.s(cpsStmts).addSingleIfStmt(cOp(NotEqual, dataFieldAccessor(p, t.snippet), NimNil)): + p.s(cpsStmts).addAssignment(data, dataField(p, t.snippet)) + result.add(data) result.addArgumentSeparator() result.add(lt) of tyArray: @@ -517,7 +543,7 @@ proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) = proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) = - template callProc(rp, params, pTyp: Snippet): Snippet = + template withCallProc(builder: var Builder, rp, params, pTyp: Snippet, body: untyped) = let e = dotField(rp, "ClE_0") let p = dotField(rp, "ClP_0") let eCall = @@ -526,9 +552,16 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) = cCall(p, e) else: cCall(p, params, e) - cIfExpr(e, - eCall, - cCall(cCast(pTyp, p), params)) + var ifStmt: IfBuilder + builder.addIfStmt(ifStmt): + builder.addElifBranch(ifStmt, e): + block: + let it {.inject.} = eCall + body + builder.addElseBranch(ifStmt): + block: + let it {.inject.} = cCall(cCast(pTyp, p), params) + body template callIter(rp, params: Snippet): Snippet = # we know the env exists @@ -540,6 +573,26 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) = else: cCall(p, params, e) + template addCallProc(builder: var Builder, rp, params, pTyp: Snippet) = + let e = dotField(rp, "ClE_0") + let p = dotField(rp, "ClP_0") + let eCall = + # note `params` here is actually multiple params + if params.len == 0: + cCall(p, e) + else: + cCall(p, params, e) + var ifStmt: IfBuilder + builder.addIfStmt(ifStmt): + builder.addElifBranch(ifStmt, e): + builder.addStmt(): + builder.add(eCall) + builder.addElseBranch(ifStmt): + builder.addCallStmt(cCast(pTyp, p), params) + + template addCallIter(builder: var Builder, rp, params: Snippet) = + builder.add(callIter(rp, params)) + var op = initLocExpr(p, ri[0]) # getUniqueType() is too expensive here: @@ -555,9 +608,9 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) = let pars = extract(params) p.s(cpsStmts).addStmt(): if tfIterator in typ.flags: - p.s(cpsStmts).add(callIter(rp, pars)) + p.s(cpsStmts).addCallIter(rp, pars) else: - p.s(cpsStmts).add(callProc(rp, pars, rawProc)) + p.s(cpsStmts).addCallProc(rp, pars, rawProc) let rawProc = getClosureType(p.module, typ, clHalf) let canRaise = p.config.exc == excGoto and canRaiseDisp(p, ri[0]) @@ -590,9 +643,11 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) = let pars = extract(params) if tfIterator in typ.flags: list.snippet = callIter(rp, pars) + genAssignment(p, d, list, {}) # no need for deep copying else: - list.snippet = callProc(rp, pars, rawProc) - genAssignment(p, d, list, {}) # no need for deep copying + p.s(cpsStmts).withCallProc(rp, pars, rawProc): + list.snippet = it + genAssignment(p, d, list, {}) # no need for deep copying if canRaise: raiseExit(p) else: var tmp: TLoc = getTemp(p, typ.returnType) @@ -602,9 +657,11 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) = let pars = extract(params) if tfIterator in typ.flags: list.snippet = callIter(rp, pars) + genAssignment(p, tmp, list, {}) else: - list.snippet = callProc(rp, pars, rawProc) - genAssignment(p, tmp, list, {}) + p.s(cpsStmts).withCallProc(rp, pars, rawProc): + list.snippet = it + genAssignment(p, tmp, list, {}) if canRaise: raiseExit(p) genAssignment(p, d, tmp, {}) else: diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 5600f6842dd5..1a9b4cf9583b 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -278,7 +278,8 @@ proc genOpenArrayConv(p: BProc; d: TLoc; a: TLoc; flags: TAssignmentFlags) = assert d.k != locNone # getTemp(p, d.t, d) - case a.t.skipTypes(abstractVar).kind + let et = a.t.skipTypes(abstractVar) + case et.kind of tyOpenArray, tyVarargs: if reifiedOpenArray(a.lode): if needTempForOpenArray in flags: @@ -303,8 +304,12 @@ proc genOpenArrayConv(p: BProc; d: TLoc; a: TLoc; flags: TAssignmentFlags) = let rd = d.rdLoc let ra = a.rdLoc let la = lenExpr(p, a) - p.s(cpsStmts).addFieldAssignment(rd, "Field0", - cIfExpr(dataFieldAccessor(p, ra), dataField(p, ra), NimNil)) + var data = getTempName(p.module) + let payloadTyp = getSeqDataPtrType(p.module, et) + p.s(cpsLocals).addVar(Local, name = data, typ = payloadTyp, initializer = NimNil) + p.s(cpsStmts).addSingleIfStmt(cOp(NotEqual, dataFieldAccessor(p, ra), NimNil)): + p.s(cpsStmts).addAssignment(data, dataField(p, ra)) + p.s(cpsStmts).addFieldAssignment(rd, "Field0", data) p.s(cpsStmts).addFieldAssignment(rd, "Field1", la) of tyArray: let rd = d.rdLoc @@ -321,8 +326,11 @@ proc genOpenArrayConv(p: BProc; d: TLoc; a: TLoc; flags: TAssignmentFlags) = let rd = d.rdLoc let ra = a.rdLoc - p.s(cpsStmts).addFieldAssignment(rd, "Field0", - cIfExpr(dataFieldAccessor(p, ra), dataField(p, ra), NimNil)) + var data = getTempName(p.module) + p.s(cpsLocals).addVar(Local, name = data, typ = ptrType(NimChar), initializer = NimNil) + p.s(cpsStmts).addSingleIfStmt(cOp(NotEqual, dataFieldAccessor(p, ra), NimNil)): + p.s(cpsStmts).addAssignment(data, dataField(p, ra)) + p.s(cpsStmts).addFieldAssignment(rd, "Field0", data) let la = lenExpr(p, a) p.s(cpsStmts).addFieldAssignment(rd, "Field1", la) else: @@ -708,10 +716,16 @@ proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) = of mUnaryMinusI64: putIntoDest(p, d, e, cOp(Neg, getTypeDesc(p.module, t), ra)) of mAbsI: - putIntoDest(p, d, e, - cIfExpr(cOp(GreaterThan, ra, cIntValue(0)), - wrapPar(ra), - cOp(Neg, getTypeDesc(p.module, t), ra))) + let rt = getTypeDesc(p.module, t) + let tmp = getTempName(p.module) + p.s(cpsLocals).addVar(name = tmp, typ = rt) + var ifStmt: IfBuilder + p.s(cpsStmts).addIfStmt(ifStmt): + p.s(cpsStmts).addElifBranch(ifStmt, cOp(GreaterThan, ra, cIntValue(0))): + p.s(cpsStmts).addAssignment(tmp, ra) + p.s(cpsStmts).addElseBranch(ifStmt): + p.s(cpsStmts).addAssignment(tmp, cOp(Neg, rt, ra)) + putIntoDest(p, d, e, tmp) else: assert(false, $m) @@ -769,9 +783,27 @@ proc binaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) = let t = getType() res = cCast(t, cOp(BitXor, t, ra, rb)) of mMinI: - res = cIfExpr(cOp(LessEqual, ra, rb), ra, rb) + let t = getType() + let tmp = getTempName(p.module) + p.s(cpsLocals).addVar(name = tmp, typ = t) + var ifStmt: IfBuilder + p.s(cpsStmts).addIfStmt(ifStmt): + p.s(cpsStmts).addElifBranch(ifStmt, cOp(LessEqual, ra, rb)): + p.s(cpsStmts).addAssignment(tmp, ra) + p.s(cpsStmts).addElseBranch(ifStmt): + p.s(cpsStmts).addAssignment(tmp, rb) + res = tmp of mMaxI: - res = cIfExpr(cOp(GreaterEqual, ra, rb), ra, rb) + let t = getType() + let tmp = getTempName(p.module) + p.s(cpsLocals).addVar(name = tmp, typ = t) + var ifStmt: IfBuilder + p.s(cpsStmts).addIfStmt(ifStmt): + p.s(cpsStmts).addElifBranch(ifStmt, cOp(GreaterEqual, ra, rb)): + p.s(cpsStmts).addAssignment(tmp, ra) + p.s(cpsStmts).addElseBranch(ifStmt): + p.s(cpsStmts).addAssignment(tmp, rb) + res = tmp of mAddU: let t = getType() let ot = cUintType(s) @@ -1565,7 +1597,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 +1967,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 @@ -1982,7 +2014,8 @@ proc genOfHelper(p: BProc; dest: PType; a: Rope; info: TLineInfo; result: var Bu cgsym(p.module, "TNimType") inc p.module.labels let cache = "Nim_OfCheck_CACHE" & p.module.labels.rope - p.module.s[cfsVars].addArrayVar(kind = Global, + p.module.s[cfsVars].addArrayVar(p.module, + kind = Global, name = cache, elementType = ptrType("TNimType"), len = 2) @@ -2055,15 +2088,23 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) = putIntoDest(p, d, e, cgCall("reprSet", raa, rti), a.storage) of tyOpenArray, tyVarargs: var b: TLoc = default(TLoc) - case skipTypes(a.t, abstractVarRange).kind + let et = skipTypes(a.t, abstractVarRange) + case et.kind of tyOpenArray, tyVarargs: let ra = rdLoc(a) putIntoDest(p, b, e, ra & cArgumentSeparator & ra & "Len_0", a.storage) of tyString, tySequence: let ra = rdLoc(a) let la = lenExpr(p, a) + var data = getTempName(p.module) + let payloadTyp = + if et.kind == tyString: ptrType(NimChar) + else: getSeqDataPtrType(p.module, et) + p.s(cpsLocals).addVar(Local, name = data, typ = payloadTyp, initializer = NimNil) + p.s(cpsStmts).addSingleIfStmt(cOp(NotEqual, dataFieldAccessor(p, ra), NimNil)): + p.s(cpsStmts).addAssignment(data, dataField(p, ra)) putIntoDest(p, b, e, - cIfExpr(dataFieldAccessor(p, ra), dataField(p, ra), NimNil) & + data & cArgumentSeparator & la, a.storage) of tyArray: @@ -2217,7 +2258,12 @@ proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) = let rti = genTypeInfoV1(p.module, t.skipTypes(abstractInst), e.info) var pExpr: Snippet if not p.module.compileToCpp: - pExpr = cIfExpr(ra, cAddr(derefField(ra, "Sup")), NimNil) + var data = getTempName(p.module) + let payloadTyp = ptrType(cgsymValue(p.module, "TGenericSeq")) + p.s(cpsLocals).addVar(Local, name = data, typ = payloadTyp, initializer = NimNil) + p.s(cpsStmts).addSingleIfStmt(cOp(NotEqual, ra, NimNil)): + p.s(cpsStmts).addAssignment(data, cAddr(derefField(ra, "Sup"))) + pExpr = data else: pExpr = ra call.snippet = cCast(rt, cgCall(p, "setLengthSeqV2", pExpr, rti, rb)) @@ -2431,7 +2477,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), @@ -2465,7 +2511,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) @@ -2546,19 +2592,20 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) = let srcTyp = getTypeDesc(p.module, e[1].typ) let destTyp = getTypeDesc(p.module, e.typ) + let unionTyp = getTempName(p.module) & "_Cast" if destsize > srcsize: - p.s(cpsLocals).addVarWithType(kind = Local, name = "LOC" & lbl): - p.s(cpsLocals).addUnionType(): - p.s(cpsLocals).addField(name = "dest", typ = destTyp) - p.s(cpsLocals).addField(name = "source", typ = srcTyp) + p.module.s[cfsTypes].addUnion(name = unionTyp): + p.module.s[cfsTypes].addField(name = "dest", typ = destTyp) + p.module.s[cfsTypes].addField(name = "source", typ = srcTyp) + p.s(cpsLocals).addVar(kind = Local, name = "LOC" & lbl, typ = unionTyp) p.s(cpsLocals).addCallStmt(cgsymValue(p.module, "nimZeroMem"), cAddr("LOC" & lbl), cSizeof("LOC" & lbl)) else: - p.s(cpsLocals).addVarWithType(kind = Local, name = "LOC" & lbl): - p.s(cpsLocals).addUnionType(): - p.s(cpsLocals).addField(name = "source", typ = srcTyp) - p.s(cpsLocals).addField(name = "dest", typ = destTyp) + p.module.s[cfsTypes].addUnion(name = unionTyp): + p.module.s[cfsTypes].addField(name = "source", typ = srcTyp) + p.module.s[cfsTypes].addField(name = "dest", typ = destTyp) + p.s(cpsLocals).addVar(kind = Local, name = "LOC" & lbl, typ = unionTyp) tmp.k = locExpr tmp.lode = lodeTyp srct tmp.storage = OnStack @@ -3072,7 +3119,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), @@ -3101,7 +3148,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))))) @@ -3770,10 +3817,10 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode, # designated initilization is the only way to init non first element of unions # branches are allowed to have no members (b.len == 0), in this case they don't need initializer var fieldName: string = "" + let fieldNameBase = "_" & mangleRecFieldName(p.module, obj[0].sym) if b.kind == nkRecList and not isEmptyCaseObjectBranch(b): - fieldName = "_" & mangleRecFieldName(p.module, obj[0].sym) & "_" & $selectedBranch - result.addField(init, name = ""): - # XXX figure out name for the union, see use of `addAnonUnion` + fieldName = fieldNameBase & "_" & $selectedBranch + result.addField(init, name = fieldNameBase & "_union"): var branchInit: StructInitializer result.addStructInitializer(branchInit, kind = siNamedStruct): result.addField(branchInit, name = fieldName): @@ -3782,8 +3829,7 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode, getNullValueAux(p, t, b, constOrNil, result, branchObjInit, isConst, info) elif b.kind == nkSym: fieldName = mangleRecFieldName(p.module, b.sym) - result.addField(init, name = ""): - # XXX figure out name for the union, see use of `addAnonUnion` + result.addField(init, name = fieldNameBase & "_union"): var branchInit: StructInitializer result.addStructInitializer(branchInit, kind = siNamedStruct): result.addField(branchInit, name = fieldName): @@ -3885,15 +3931,19 @@ proc genConstSeq(p: BProc, n: PNode, t: PType; isConst: bool; result: var Builde let base = t.skipTypes(abstractInst)[0] let tmpName = getTempName(p.module) + let typ = tmpName & "_SeqLit" + var typBuilder = newBuilder("") + typBuilder.addTypedef(name = typ): + typBuilder.addSimpleStruct(p.module, name = "", baseType = ""): + typBuilder.addField(name = "sup", typ = cgsymValue(p.module, "TGenericSeq")) + typBuilder.addArrayField(p.module, name = "data", elementType = getTypeDesc(p.module, base), len = n.len) + p.module.s[cfsTypes].add(extract(typBuilder)) # genBracedInit can modify cfsStrData, we need an intermediate builder: var def = newBuilder("") - def.addVarWithTypeAndInitializer( + def.addVarWithInitializer( if isConst: Const else: Global, - name = tmpName): - def.addSimpleStruct(p.module, name = "", baseType = ""): - def.addField(name = "sup", typ = cgsymValue(p.module, "TGenericSeq")) - def.addArrayField(name = "data", elementType = getTypeDesc(p.module, base), len = n.len) - do: + name = tmpName, + typ = typ): var structInit: StructInitializer def.addStructInitializer(structInit, kind = siOrderedStruct): def.addField(structInit, name = "sup"): @@ -3918,15 +3968,19 @@ proc genConstSeqV2(p: BProc, n: PNode, t: PType; isConst: bool; result: var Buil let base = t.skipTypes(abstractInst)[0] let payload = getTempName(p.module) + let typ = payload & "_SeqLit" + var typBuilder = newBuilder("") + typBuilder.addTypedef(name = typ): + typBuilder.addSimpleStruct(p.module, name = "", baseType = ""): + typBuilder.addField(name = "cap", typ = NimInt) + typBuilder.addArrayField(p.module, name = "data", elementType = getTypeDesc(p.module, base), len = n.len) + p.module.s[cfsTypes].add(extract(typBuilder)) # genBracedInit can modify cfsStrData, we need an intermediate builder: var def = newBuilder("") - def.addVarWithTypeAndInitializer( + def.addVarWithInitializer( if isConst: AlwaysConst else: Global, - name = payload): - def.addSimpleStruct(p.module, name = "", baseType = ""): - def.addField(name = "cap", typ = NimInt) - def.addArrayField(name = "data", elementType = getTypeDesc(p.module, base), len = n.len) - do: + name = payload, + typ = typ): var structInit: StructInitializer def.addStructInitializer(structInit, kind = siOrderedStruct): def.addField(structInit, name = "cap"): @@ -4008,7 +4062,7 @@ proc genBracedInit(p: BProc, n: PNode; isConst: bool; optionalType: PType; resul let arrLen = n.len # genConstSimpleList can modify cfsStrData, we need an intermediate builder: var data = newBuilder("") - data.addArrayVarWithInitializer( + data.addArrayVarWithInitializer(p.module, kind = if isConst: AlwaysConst else: Global, name = payload, elementType = ctype, len = arrLen): genConstSimpleList(p, n, isConst, data) diff --git a/compiler/ccgliterals.nim b/compiler/ccgliterals.nim index 84f72017cf7e..446743020fc0 100644 --- a/compiler/ccgliterals.nim +++ b/compiler/ccgliterals.nim @@ -36,12 +36,15 @@ proc genStringLiteralDataOnlyV1(m: BModule, s: string; result: var Rope) = cgsym(m, "TGenericSeq") let tmp = getTempName(m) result.add tmp + let typ = tmp & "_StrLit" + var typBuilder = newBuilder("") + typBuilder.addTypedef(name = typ): + typBuilder.addSimpleStruct(m, name = "", baseType = ""): + typBuilder.addField(name = "Sup", typ = "TGenericSeq") + typBuilder.addArrayField(m, name = "data", elementType = NimChar, len = s.len + 1) + m.s[cfsTypes].add(extract(typBuilder)) var res = newBuilder("") - res.addVarWithTypeAndInitializer(AlwaysConst, name = tmp): - res.addSimpleStruct(m, name = "", baseType = ""): - res.addField(name = "Sup", typ = "TGenericSeq") - res.addArrayField(name = "data", elementType = NimChar, len = s.len + 1) - do: + res.addVarWithInitializer(AlwaysConst, name = tmp, typ = typ): var strInit: StructInitializer res.addStructInitializer(strInit, kind = siOrderedStruct): res.addField(strInit, name = "Sup"): @@ -71,14 +74,18 @@ proc genStringLiteralV1(m: BModule; n: PNode; result: var Builder) = # ------ Version 2: destructor based strings and seqs ----------------------- proc genStringLiteralDataOnlyV2(m: BModule, s: string; result: Rope; isConst: bool) = + let typ = getTempName(m) & "_StrLit" + var typBuilder = newBuilder("") + typBuilder.addTypedef(name = typ): + typBuilder.addSimpleStruct(m, name = "", baseType = ""): + typBuilder.addField(name = "cap", typ = NimInt) + typBuilder.addArrayField(m, name = "data", elementType = NimChar, len = s.len + 1) + m.s[cfsTypes].add(extract(typBuilder)) var res = newBuilder("") - res.addVarWithTypeAndInitializer( + res.addVarWithInitializer( if isConst: AlwaysConst else: Global, - name = result): - res.addSimpleStruct(m, name = "", baseType = ""): - res.addField(name = "cap", typ = NimInt) - res.addArrayField(name = "data", elementType = NimChar, len = s.len + 1) - do: + name = result, + typ = typ): var structInit: StructInitializer res.addStructInitializer(structInit, kind = siOrderedStruct): res.addField(structInit, name = "cap"): diff --git a/compiler/ccgreset.nim b/compiler/ccgreset.nim index 7b0d61926133..9818a9bbd43c 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 ed840a97a8fa..e5fb1bfd18ec 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -621,7 +621,8 @@ proc genComputedGoto(p: BProc; n: PNode) = var id = p.labels+1 inc p.labels, arraySize+1 let tmp = "TMP$1_" % [id.rope] - p.s(cpsStmts).addArrayVarWithInitializer(kind = Global, + p.s(cpsStmts).addArrayVarWithInitializer(p.module, + kind = Global, name = tmp, elementType = CPointer, len = arraySize): @@ -767,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) @@ -1036,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..= 0: let objDisplayStore = getTempName(m) - m.s[cfsVars].addArrayVarWithInitializer(kind = Global, + m.s[cfsVars].addArrayVarWithInitializer(m, + kind = Global, name = objDisplayStore, elementType = getTypeDesc(m, getSysType(m.g.graph, unknownLineInfo, tyUInt32), dkVar), len = objDepth + 1): @@ -1765,7 +1799,8 @@ proc genTypeInfoV2OldImpl(m: BModule; t, origType: PType, name: Rope; info: TLin let dispatchMethods = toSeq(getMethodsPerType(m.g.graph, t)) if dispatchMethods.len > 0: let vTablePointerName = getTempName(m) - m.s[cfsVars].addArrayVarWithInitializer(kind = Global, + m.s[cfsVars].addArrayVarWithInitializer(m, + kind = Global, name = vTablePointerName, elementType = CPointer, len = dispatchMethods.len): @@ -1813,7 +1848,8 @@ proc genTypeInfoV2Impl(m: BModule; t, origType: PType, name: Rope; info: TLineIn if objDepth >= 0: let objDisplayStore = getTempName(m) - m.s[cfsVars].addArrayVarWithInitializer(kind = Const, + m.s[cfsVars].addArrayVarWithInitializer(m, + kind = Const, name = objDisplayStore, elementType = getTypeDesc(m, getSysType(m.g.graph, unknownLineInfo, tyUInt32), dkVar), len = objDepth + 1): diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 2d4e70420b9e..adb564c1f869 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -379,7 +379,11 @@ proc lenExpr(p: BProc; a: TLoc): Rope = result = dotField(rdLoc(a), "len") else: let ra = rdLoc(a) - result = cIfExpr(ra, lenField(p, ra), cIntValue(0)) + let len = getTempName(p.module) + p.s(cpsLocals).addVar(name = len, typ = NimInt, initializer = cIntValue(0)) + p.s(cpsStmts).addSingleIfStmt(cOp(NotEqual, ra, NimNil)): + p.s(cpsStmts).addAssignment(len, lenField(p, ra)) + result = len proc dataFieldAccessor(p: BProc, sym: Rope): Rope = if optSeqDestructors in p.config.globalOptions: @@ -1918,7 +1922,8 @@ proc registerModuleToMain(g: BModuleList; m: BModule) = let systemModulePath = getModuleDllPath(m, g.modules[g.graph.config.m.systemFileIdx.int].module) let mainModulePath = getModuleDllPath(m, m.module) hcrModuleMeta.addDeclWithVisibility(Private): - hcrModuleMeta.addArrayVarWithInitializer(kind = Local, + hcrModuleMeta.addArrayVarWithInitializer(m, + kind = Local, name = "hcr_module_list", elementType = ptrConstType(CChar), len = g.graph.importDeps.getOrDefault(FileIndex(m.module.position)).len + @@ -2097,10 +2102,12 @@ proc genInitCode(m: BModule) = CNil, cCast(ptrType(CPointer), cAddr(m.typeNodesName))) else: - m.s[cfsTypeInit1].addArrayVar(Global, name = m.typeNodesName, + m.s[cfsTypeInit1].addArrayVar(m, + Global, name = m.typeNodesName, elementType = cgsymValue(m, "TNimNode"), len = m.typeNodes) if m.nimTypes > 0: - m.s[cfsTypeInit1].addArrayVar(Global, name = m.nimTypesName, + m.s[cfsTypeInit1].addArrayVar(m, + Global, name = m.nimTypesName, elementType = cgsymValue(m, "TNimType"), len = m.nimTypes) if m.hcrOn: diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim index f9ed9c6fdae9..67523e7d2df7 100644 --- a/compiler/cgendata.nim +++ b/compiler/cgendata.nim @@ -173,6 +173,8 @@ type # OpenGL wrapper sigConflicts*: CountTable[SigHash] g*: BModuleList + when buildNifc: + arrayTypes*: Table[(Snippet, int), Snippet] template config*(m: BModule): ConfigRef = m.g.config template config*(p: BProc): ConfigRef = p.module.g.config