summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim1
-rw-r--r--compiler/ccgtypes.nim2
-rw-r--r--compiler/pragmas.nim7
-rw-r--r--compiler/wordrecg.nim2
-rw-r--r--doc/manual/pragmas.txt18
-rw-r--r--tests/pragmas/tbitsize.nim22
-rw-r--r--web/news.txt2
7 files changed, 53 insertions, 1 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 4001e896e..25958f580 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -784,6 +784,7 @@ type
       tab*: TStrTable         # interface table for modules
     of skLet, skVar, skField, skForVar:
       guard*: PSym
+      bitsize*: int
     else: nil
     magic*: TMagic
     typ*: PType
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index 84d02d1da..1ed9ce113 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -441,6 +441,8 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
       elif fieldType.kind == tySequence:
         # we need to use a weak dependency here for trecursive_table.
         addf(result, "$1 $2;$n", [getTypeDescWeak(m, field.loc.t, check), sname])
+      elif field.bitsize != 0:
+        addf(result, "$1 $2:$3;$n", [getTypeDescAux(m, field.loc.t, check), sname, rope($field.bitsize)])
       else:
         # don't use fieldType here because we need the
         # tyGenericInst for C++ template support
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index 1c51251fe..ba05b2792 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -56,7 +56,7 @@ const
     wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
     wBorrow, wGcSafe}
   fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
-    wImportCpp, wImportObjC, wError, wGuard}
+    wImportCpp, wImportObjC, wError, wGuard, wBitsize}
   varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
     wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern,
     wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal,
@@ -844,6 +844,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
         if sym == nil: pragmaLockStmt(c, it)
         elif sym.typ == nil: invalidPragma(it)
         else: sym.typ.lockLevel = pragmaLocks(c, it)
+      of wBitsize:
+        if sym == nil or sym.kind != skField or it.kind != nkExprColonExpr:
+          invalidPragma(it)
+        else:
+          sym.bitsize = expectIntLit(c, it)
       of wGuard:
         if sym == nil or sym.kind notin {skVar, skLet, skField}:
           invalidPragma(it)
diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim
index 23f012ea5..d1e5438f3 100644
--- a/compiler/wordrecg.nim
+++ b/compiler/wordrecg.nim
@@ -82,6 +82,7 @@ type
     wStdIn, wStdOut, wStdErr,
 
     wInOut, wByCopy, wByRef, wOneWay,
+    wBitsize,
 
   TSpecialWords* = set[TSpecialWord]
 
@@ -168,6 +169,7 @@ const
     "stdin", "stdout", "stderr",
 
     "inout", "bycopy", "byref", "oneway",
+    "bitsize",
     ]
 
 proc findStr*(a: openArray[string], s: string): int =
diff --git a/doc/manual/pragmas.txt b/doc/manual/pragmas.txt
index 68a88f865..f89194c9a 100644
--- a/doc/manual/pragmas.txt
+++ b/doc/manual/pragmas.txt
@@ -531,6 +531,24 @@ Implementation Specific Pragmas
 This section describes additional pragmas that the current Nim implementation
 supports but which should not be seen as part of the language specification.
 
+Bitsize pragma
+--------------
+
+The ``bitsize`` pragma is for object field members. It declares the field as
+a bitfield in C/C++.
+
+.. code-block:: Nim
+  type
+    mybitfield = object
+      flag {.bitsize:1.}: cuint
+
+generates:
+
+.. code-block:: C
+  struct mybitfield {
+    unsigned int flag:1;
+  };
+
 
 Volatile pragma
 ---------------
diff --git a/tests/pragmas/tbitsize.nim b/tests/pragmas/tbitsize.nim
new file mode 100644
index 000000000..7a44944d2
--- /dev/null
+++ b/tests/pragmas/tbitsize.nim
@@ -0,0 +1,22 @@
+discard """
+ccodeCheck: "\\i @'unsigned int flag:1;' .*"
+"""
+
+type
+  bits* = object
+    flag* {.bitsize: 1.}: cuint
+    opts* {.bitsize: 4.}: cint
+
+var
+  b: bits
+
+assert b.flag == 0
+b.flag = 1
+assert b.flag == 1
+b.flag = 2
+assert b.flag == 0
+
+b.opts = 7
+assert b.opts == 7
+b.opts = 9
+assert b.opts == -7
diff --git a/web/news.txt b/web/news.txt
index cfa40c65c..33ceac49e 100644
--- a/web/news.txt
+++ b/web/news.txt
@@ -108,6 +108,8 @@ News
   - The compiler finally considers symbol binding rules in templates and
     generics for overloaded ``[]``, ``[]=``, ``{}``, ``{}=`` operators
     (issue `#2599 <https://github.com/nim-lang/Nim/issues/2599>`_).
+  - The compiler now supports a `bitsize pragma <docs/manual.html#pragmas-bitsize-pragma>`_
+    for constructing bitfields.
 
 
   Language Additions