fixes and changes the recently introduced 'alignas' to be 'align' (#12666)

* fixes and changes the recently introduced 'alignas' to be 'align'

* more improvements
This commit is contained in:
Andreas Rumpf
2019-11-15 20:24:14 +01:00
committed by GitHub
parent 9c46526cfa
commit 58f3e07b1a
9 changed files with 50 additions and 44 deletions

View File

@@ -58,8 +58,8 @@
## Language additions
- `alignas` pragma can now be used similar to the `alignas`
declaration modifier in C/C++.
- An `align` pragma can now be used for variables and object fields, similar
to the `alignas` declaration modifier in C/C++.
## Language changes

View File

@@ -479,8 +479,8 @@ 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)
if s.kind in {skLet, skVar} and s.alignment > 0:
result.addf("alignas($1) ", [rope(s.alignment)])
if s.kind in {skLet, skVar, skField, skForVar} and s.alignment > 0:
result.addf("NIM_ALIGN($1) ", [rope(s.alignment)])
result.add getTypeDesc(p.module, s.typ)
if s.constraint.isNil:
if sfRegister in s.flags: add(result, " register")
@@ -533,7 +533,7 @@ proc assignGlobalVar(p: BProc, n: PNode) =
var td = getTypeDesc(p.module, s.loc.t)
if s.constraint.isNil:
if s.kind in {skLet, skVar, skField, skForVar} and s.alignment > 0:
decl.addf "alignas($1) ", [rope(s.alignment)]
decl.addf "NIM_ALIGN($1) ", [rope(s.alignment)]
if p.hcrOn: add(decl, "static ")
elif sfImportc in s.flags: add(decl, "extern ")
add(decl, td)
@@ -1195,8 +1195,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)]
if sym.kind in {skLet, skVar, skField, skForVar} and sym.alignment > 0:
m.s[cfsVars].addf "NIM_ALIGN($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], "*")

View File

@@ -20,7 +20,7 @@ const
const
declPragmas = {wImportc, wImportObjC, wImportCpp, wImportJs, wExportc, wExportCpp,
wExportNims, wExtern, wDeprecated, wNodecl, wError, wUsed, wAlignas}
wExportNims, wExtern, wDeprecated, wNodecl, wError, wUsed, wAlign}
## common pragmas for declarations, to a good approximation
procPragmas* = declPragmas + {FirstCallConv..LastCallConv,
wMagic, wNoSideEffect, wSideEffect, wNoreturn, wDynlib, wHeader,
@@ -815,7 +815,7 @@ 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:
of wAlign:
let alignment = expectIntLit(c, it)
if alignment == 0:
discard

View File

@@ -6433,38 +6433,39 @@ generates:
unsigned int flag:1;
};
Alignas pragma
--------------
The ``alignas`` pragma is for variables and object field members. It
modifies the alignment requirement of the thing being declared. The
argument must be a constant power of 2 or 0. Valid non-zero
alignments that are weaker than another alignas pragmas on the same
declaration are ignored. Alignments that are weaker that the
alignment requirement of the type are ignored. ``alignas(0)`` is
always ignored.
Align pragma
------------
The `align`:idx: pragma is for variables and object field members. It
modifies the alignment requirement of the entity being declared. The
argument must be a constant power of 2. Valid non-zero
alignments that are weaker than nother align pragmas on the same
declaration are ignored. Alignments that are weaker that the
alignment requirement of the type are ignored.
.. code-block:: Nim
type
sseType = object
sseData {.alignas(16).}: array[4,float32]
sseData {.align(16).}: array[4,float32]
# every object will be aligned to 128-byte boundary
Data = object
x: char
cacheline {.alignas(128).}: array[128, char] # over-aligned array of char,
cacheline {.align(128).}: array[128, char] # over-aligned array of char,
proc main() =
echo "sizeof(Data) = ", sizeof(Data), " (1 byte + 127 bytes padding + 128-byte array)"
# output: sizeof(Data) = 256 (1 byte + 127 bytes padding + 128-byte array)
echo "alignment of sseType is ", alignof(sseType)
# output: alignment of sseType is 16
var d {.alignas(2048).}: Data # this instance of data is aligned even stricter
var d {.align(2048).}: Data # this instance of data is aligned even stricter
main()
This pragma has no effect on nimvm or the js backend.
This pragma has no effect for the JS backend.
Volatile pragma
---------------

View File

@@ -256,7 +256,6 @@ __clang__
#include <limits.h>
#include <stddef.h>
#include <stdalign.h>
/* C99 compiler? */
#if (defined(__STD_VERSION__) && (__STD_VERSION__ >= 199901))
@@ -467,6 +466,12 @@ typedef int Nim_and_C_compiler_disagree_on_target_architecture[sizeof(NI) == siz
# define NIM_EXTERNC
#endif
#if defined(_MSC_VER)
# define NIM_ALIGN(x) __declspec(align(x))
#else
# define NIM_ALIGN(x) __attribute__((aligned(x)))
#endif
/* ---------------- platform specific includes ----------------------- */
/* VxWorks related includes */

View File

@@ -1,3 +1,3 @@
var myglobal1* {.alignas(128).}: int32
var myglobal2* {.alignas(128).}: int32
var myglobal3* {.alignas(128).}: int32
var myglobal1* {.align(128).}: int32
var myglobal2* {.align(128).}: int32
var myglobal3* {.align(128).}: int32

View File

@@ -1,7 +1,7 @@
discard """
ccodeCheck: "\\i @'alignas(128) NI mylocal1' .*"
ccodeCheck: "\\i @'NIM_ALIGN(128) NI mylocal1' .*"
target: "c cpp"
output: "alignas ok"
output: "align ok"
"""
# This is for Azure. The keyword ``alignof`` only exists in ``c++11``
@@ -11,14 +11,14 @@ when defined(cpp) and not defined(windows):
import globalalignas
var toplevel1 {.alignas: 32.} : int32
var toplevel2 {.alignas: 32.} : int32
var toplevel3 {.alignas: 32.} : int32
var toplevel1 {.align: 32.} : int32
var toplevel2 {.align: 32.} : int32
var toplevel3 {.align: 32.} : int32
proc foobar() =
var myvar1 {.global, alignas(64).}: int = 123
var myvar2 {.global, alignas(64).}: int = 123
var myvar3 {.global, alignas(64).}: int = 123
var myvar1 {.global, align(64).}: int = 123
var myvar2 {.global, align(64).}: int = 123
var myvar3 {.global, align(64).}: int = 123
doAssert (cast[uint](addr(myglobal1)) and 127) == 0
doAssert (cast[uint](addr(myglobal2)) and 127) == 0
@@ -32,15 +32,15 @@ proc foobar() =
doAssert (cast[uint](addr(toplevel2)) and 31) == 0
doAssert (cast[uint](addr(toplevel3)) and 31) == 0
# test multiple alignas expressions
var mylocal1 {.alignas(0), alignas(128), alignas(32).}: int = 123
var mylocal2 {.alignas(128), alignas(0), alignas(32).}: int = 123
var mylocal3 {.alignas(0), alignas(32), alignas(128).}: int = 123
# test multiple align expressions
var mylocal1 {.align(0), align(128), align(32).}: int = 123
var mylocal2 {.align(128), align(0), align(32).}: int = 123
var mylocal3 {.align(0), align(32), align(128).}: int = 123
doAssert (cast[uint](addr(mylocal1)) and 127) == 0
doAssert (cast[uint](addr(mylocal2)) and 127) == 0
doAssert (cast[uint](addr(mylocal3)) and 127) == 0
echo "alignas ok"
echo "align ok"
foobar()

View File

@@ -4,4 +4,4 @@ errormsg: "power of two or 0 expected"
"""
proc foobar() =
let something {.alignas(33).} = 123
let something {.align(33).} = 123

View File

@@ -336,10 +336,10 @@ testinstance:
a: int32
b: T
# this type mixes `packed` with `alignas`.
# this type mixes `packed` with `align`.
MyCustomAlignPackedObject {.objectconfig.} = object
a: char
b {.alignas: 32.}: int32 # alignas overrides `packed` for this field.
b {.align: 32.}: int32 # align overrides `packed` for this field.
c: char
d: int32 # unaligned
@@ -496,11 +496,11 @@ type
MyCustomAlignUnion {.union.} = object
c: char
a {.alignas: 32.}: int
a {.align: 32.}: int
MyCustomAlignObject = object
c: char
a {.alignas: 32.}: int
a {.align: 32.}: int
doAssert sizeof(MyUnionType) == 4
doAssert sizeof(MyCustomAlignUnion) == 32