cbuilder.nim 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. type
  2. Snippet = string
  3. Builder = string
  4. template newBuilder(s: string): Builder =
  5. s
  6. proc addField(obj: var Builder; name, typ: Snippet) =
  7. obj.add('\t')
  8. obj.add(typ)
  9. obj.add(" ")
  10. obj.add(name)
  11. obj.add(";\n")
  12. proc addField(obj: var Builder; field: PSym; name, typ: Snippet; isFlexArray: bool; initializer: Snippet) =
  13. obj.add('\t')
  14. if field.alignment > 0:
  15. obj.add("NIM_ALIGN(")
  16. obj.addInt(field.alignment)
  17. obj.add(") ")
  18. obj.add(typ)
  19. if sfNoalias in field.flags:
  20. obj.add(" NIM_NOALIAS")
  21. obj.add(" ")
  22. obj.add(name)
  23. if isFlexArray:
  24. obj.add("[SEQ_DECL_SIZE]")
  25. if field.bitsize != 0:
  26. obj.add(":")
  27. obj.addInt(field.bitsize)
  28. if initializer.len != 0:
  29. obj.add(initializer)
  30. obj.add(";\n")
  31. proc structOrUnion(t: PType): Snippet =
  32. let t = t.skipTypes({tyAlias, tySink})
  33. if tfUnion in t.flags: "union"
  34. else: "struct"
  35. proc ptrType(t: Snippet): Snippet =
  36. t & "*"
  37. template addStruct(obj: var Builder; m: BModule; typ: PType; name: string; baseType: string; body: typed) =
  38. if tfPacked in typ.flags:
  39. if hasAttribute in CC[m.config.cCompiler].props:
  40. obj.add(structOrUnion(typ))
  41. obj.add(" __attribute__((__packed__))")
  42. else:
  43. obj.add("#pragma pack(push, 1)\n")
  44. obj.add(structOrUnion(typ))
  45. else:
  46. obj.add(structOrUnion(typ))
  47. obj.add(" ")
  48. obj.add(name)
  49. type BaseClassKind = enum
  50. bcNone, bcCppInherit, bcSupField, bcNoneRtti, bcNoneTinyRtti
  51. var baseKind = bcNone
  52. if typ.kind == tyObject:
  53. if typ.baseClass == nil:
  54. if lacksMTypeField(typ):
  55. baseKind = bcNone
  56. elif optTinyRtti in m.config.globalOptions:
  57. baseKind = bcNoneTinyRtti
  58. else:
  59. baseKind = bcNoneRtti
  60. elif m.compileToCpp:
  61. baseKind = bcCppInherit
  62. else:
  63. baseKind = bcSupField
  64. if baseKind == bcCppInherit:
  65. obj.add(" : public ")
  66. obj.add(baseType)
  67. obj.add(" ")
  68. obj.add("{\n")
  69. let currLen = obj.len
  70. case baseKind
  71. of bcNone:
  72. # rest of the options add a field or don't need it due to inheritance,
  73. # we need to add the dummy field for uncheckedarray ahead of time
  74. # so that it remains trailing
  75. if typ.itemId notin m.g.graph.memberProcsPerType and
  76. typ.n != nil and typ.n.len == 1 and typ.n[0].kind == nkSym and
  77. typ.n[0].sym.typ.skipTypes(abstractInst).kind == tyUncheckedArray:
  78. # only consists of flexible array field, add *initial* dummy field
  79. obj.addField(name = "dummy", typ = "char")
  80. of bcCppInherit: discard
  81. of bcNoneRtti:
  82. obj.addField(name = "m_type", typ = ptrType(cgsymValue(m, "TNimType")))
  83. of bcNoneTinyRtti:
  84. obj.addField(name = "m_type", typ = ptrType(cgsymValue(m, "TNimTypeV2")))
  85. of bcSupField:
  86. obj.addField(name = "Sup", typ = baseType)
  87. body
  88. if baseKind == bcNone and currLen == obj.len and typ.itemId notin m.g.graph.memberProcsPerType:
  89. # no fields were added, add dummy field
  90. obj.addField(name = "dummy", typ = "char")
  91. obj.add("};\n")
  92. if tfPacked in typ.flags and hasAttribute notin CC[m.config.cCompiler].props:
  93. result.add("#pragma pack(pop)\n")
  94. template addFieldWithStructType(obj: var Builder; m: BModule; parentTyp: PType; fieldName: string, body: typed) =
  95. ## adds a field with a `struct { ... }` type, building it according to `body`
  96. obj.add('\t')
  97. if tfPacked in parentTyp.flags:
  98. if hasAttribute in CC[m.config.cCompiler].props:
  99. obj.add("struct __attribute__((__packed__)) {\n")
  100. else:
  101. obj.add("#pragma pack(push, 1)\nstruct {")
  102. else:
  103. obj.add("struct {\n")
  104. body
  105. obj.add("} ")
  106. obj.add(fieldName)
  107. obj.add(";\n")
  108. if tfPacked in parentTyp.flags and hasAttribute notin CC[m.config.cCompiler].props:
  109. result.add("#pragma pack(pop)\n")
  110. template addAnonUnion(obj: var Builder; body: typed) =
  111. obj.add "union{\n"
  112. body
  113. obj.add("};\n")