summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ast.nim1
-rw-r--r--compiler/ccgtypes.nim2
-rw-r--r--compiler/cgen.nim8
-rw-r--r--compiler/pragmas.nim17
-rw-r--r--compiler/sizealignoffsetimpl.nim4
5 files changed, 23 insertions, 9 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 06041eaa7..1ad7249d4 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -824,6 +824,7 @@ type
     of skLet, skVar, skField, skForVar:
       guard*: PSym
       bitsize*: int
+      alignment*: int # for alignas(X) expressions
     else: nil
     magic*: TMagic
     typ*: PType
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index a867c58c1..2e0f13bc5 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -549,6 +549,8 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
     #assert(field.ast == nil)
     let sname = mangleRecFieldName(m, field)
     fillLoc(field.loc, locField, n, sname, OnUnknown)
+    if field.alignment > 0:
+      result.addf "alignas($1) ", [rope(field.alignment)]
     # for importcpp'ed objects, we only need to set field.loc, but don't
     # have to recurse via 'getTypeDescAux'. And not doing so prevents problems
     # with heavily templatized C++ code:
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 71d719814..1e25f44d1 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -478,7 +478,9 @@ proc localVarDecl(p: BProc; n: PNode): Rope =
   if s.loc.k == locNone:
     fillLoc(s.loc, locLocalVar, n, mangleLocalName(p, s), OnStack)
     if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy)
-  result = getTypeDesc(p.module, s.typ)
+  if s.kind in {skLet, skVar} and s.alignment > 0:
+    result.addf("alignas($1) ", [rope(s.alignment)])
+  result.add getTypeDesc(p.module, s.typ)
   if s.constraint.isNil:
     if sfRegister in s.flags: add(result, " register")
     #elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds:
@@ -529,6 +531,8 @@ proc assignGlobalVar(p: BProc, n: PNode) =
       var decl: Rope = nil
       var td = getTypeDesc(p.module, s.loc.t)
       if s.constraint.isNil:
+        if s.alignment > 0:
+          decl.addf "alignas($1) ", [rope(s.alignment)]
         if p.hcrOn: add(decl, "static ")
         elif sfImportc in s.flags: add(decl, "extern ")
         add(decl, td)
@@ -1187,6 +1191,8 @@ proc genVarPrototype(m: BModule, n: PNode) =
       declareThreadVar(m, sym, true)
     else:
       incl(m.declaredThings, sym.id)
+      if sym.alignment > 0:
+        m.s[cfsVars].addf "alignas($1) ", [rope(sym.alignment)]
       add(m.s[cfsVars], if m.hcrOn: "static " else: "extern ")
       add(m.s[cfsVars], getTypeDesc(m, sym.loc.t))
       if m.hcrOn: add(m.s[cfsVars], "*")
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index 205ed4309..24394bf97 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -20,7 +20,7 @@ const
 
 const
   declPragmas = {wImportc, wImportObjC, wImportCpp, wImportJs, wExportc, wExportCpp,
-    wExportNims, wExtern, wDeprecated, wNodecl, wError, wUsed}
+    wExportNims, wExtern, wDeprecated, wNodecl, wError, wUsed, wAlignas}
     ## common pragmas for declarations, to a good approximation
   procPragmas* = declPragmas + {FirstCallConv..LastCallConv,
     wMagic, wNoSideEffect, wSideEffect, wNoreturn, wDynlib, wHeader,
@@ -803,13 +803,6 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
         setExternName(c, sym, name, it.info)
       of wImportObjC:
         processImportObjC(c, sym, getOptionalStr(c, it, "$1"), it.info)
-      of wAlign:
-        if sym.typ == nil: invalidPragma(c, it)
-        var align = expectIntLit(c, it)
-        if (not isPowerOfTwo(align) and align != 0) or align >% high(int16):
-          localError(c.config, it.info, "power of two expected")
-        else:
-          sym.typ.align = align.int16
       of wSize:
         if sym.typ == nil: invalidPragma(c, it)
         var size = expectIntLit(c, it)
@@ -822,6 +815,14 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
           sym.typ.align = floatInt64Align(c.config)
         else:
           localError(c.config, it.info, "size may only be 1, 2, 4 or 8")
+      of wAlignas:
+        let alignment = expectIntLit(c, it)
+        if alignment == 0:
+          discard
+        elif isPowerOfTwo(alignment):
+          sym.alignment = max(sym.alignment, alignment)
+        else:
+          localError(c.config, it.info, "power of two or 0 expected")
       of wNodecl:
         noVal(c, it)
         incl(sym.loc.flags, lfNoDecl)
diff --git a/compiler/sizealignoffsetimpl.nim b/compiler/sizealignoffsetimpl.nim
index f57969712..e6bd1fc7b 100644
--- a/compiler/sizealignoffsetimpl.nim
+++ b/compiler/sizealignoffsetimpl.nim
@@ -156,6 +156,8 @@ proc computeObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, packed: bool, a
       size = n.sym.typ.size.int
       align = if packed: 1 else: n.sym.typ.align.int
     accum.align(align)
+    if n.sym.alignment > 0:
+      accum.align(n.sym.alignment)
     n.sym.offset = accum.offset
     accum.inc(size)
   else:
@@ -183,6 +185,8 @@ proc computeUnionObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode; accum: var
       size = n.sym.typ.size.int
       align = n.sym.typ.align.int
     accum.align(align)
+    if n.sym.alignment > 0:
+      accum.align(n.sym.alignment)
     n.sym.offset = accum.offset
     accum.inc(size)
   else: