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:
parent
9c46526cfa
commit
58f3e07b1a
9 changed files with 50 additions and 44 deletions
|
|
@ -58,8 +58,8 @@
|
||||||
|
|
||||||
## Language additions
|
## Language additions
|
||||||
|
|
||||||
- `alignas` pragma can now be used similar to the `alignas`
|
- An `align` pragma can now be used for variables and object fields, similar
|
||||||
declaration modifier in C/C++.
|
to the `alignas` declaration modifier in C/C++.
|
||||||
|
|
||||||
## Language changes
|
## Language changes
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -479,8 +479,8 @@ proc localVarDecl(p: BProc; n: PNode): Rope =
|
||||||
if s.loc.k == locNone:
|
if s.loc.k == locNone:
|
||||||
fillLoc(s.loc, locLocalVar, n, mangleLocalName(p, s), OnStack)
|
fillLoc(s.loc, locLocalVar, n, mangleLocalName(p, s), OnStack)
|
||||||
if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy)
|
if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy)
|
||||||
if s.kind in {skLet, skVar} and s.alignment > 0:
|
if s.kind in {skLet, skVar, skField, skForVar} and s.alignment > 0:
|
||||||
result.addf("alignas($1) ", [rope(s.alignment)])
|
result.addf("NIM_ALIGN($1) ", [rope(s.alignment)])
|
||||||
result.add getTypeDesc(p.module, s.typ)
|
result.add getTypeDesc(p.module, s.typ)
|
||||||
if s.constraint.isNil:
|
if s.constraint.isNil:
|
||||||
if sfRegister in s.flags: add(result, " register")
|
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)
|
var td = getTypeDesc(p.module, s.loc.t)
|
||||||
if s.constraint.isNil:
|
if s.constraint.isNil:
|
||||||
if s.kind in {skLet, skVar, skField, skForVar} and s.alignment > 0:
|
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 ")
|
if p.hcrOn: add(decl, "static ")
|
||||||
elif sfImportc in s.flags: add(decl, "extern ")
|
elif sfImportc in s.flags: add(decl, "extern ")
|
||||||
add(decl, td)
|
add(decl, td)
|
||||||
|
|
@ -1195,8 +1195,8 @@ proc genVarPrototype(m: BModule, n: PNode) =
|
||||||
declareThreadVar(m, sym, true)
|
declareThreadVar(m, sym, true)
|
||||||
else:
|
else:
|
||||||
incl(m.declaredThings, sym.id)
|
incl(m.declaredThings, sym.id)
|
||||||
if sym.alignment > 0:
|
if sym.kind in {skLet, skVar, skField, skForVar} and sym.alignment > 0:
|
||||||
m.s[cfsVars].addf "alignas($1) ", [rope(sym.alignment)]
|
m.s[cfsVars].addf "NIM_ALIGN($1) ", [rope(sym.alignment)]
|
||||||
add(m.s[cfsVars], if m.hcrOn: "static " else: "extern ")
|
add(m.s[cfsVars], if m.hcrOn: "static " else: "extern ")
|
||||||
add(m.s[cfsVars], getTypeDesc(m, sym.loc.t))
|
add(m.s[cfsVars], getTypeDesc(m, sym.loc.t))
|
||||||
if m.hcrOn: add(m.s[cfsVars], "*")
|
if m.hcrOn: add(m.s[cfsVars], "*")
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ const
|
||||||
|
|
||||||
const
|
const
|
||||||
declPragmas = {wImportc, wImportObjC, wImportCpp, wImportJs, wExportc, wExportCpp,
|
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
|
## common pragmas for declarations, to a good approximation
|
||||||
procPragmas* = declPragmas + {FirstCallConv..LastCallConv,
|
procPragmas* = declPragmas + {FirstCallConv..LastCallConv,
|
||||||
wMagic, wNoSideEffect, wSideEffect, wNoreturn, wDynlib, wHeader,
|
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)
|
sym.typ.align = floatInt64Align(c.config)
|
||||||
else:
|
else:
|
||||||
localError(c.config, it.info, "size may only be 1, 2, 4 or 8")
|
localError(c.config, it.info, "size may only be 1, 2, 4 or 8")
|
||||||
of wAlignas:
|
of wAlign:
|
||||||
let alignment = expectIntLit(c, it)
|
let alignment = expectIntLit(c, it)
|
||||||
if alignment == 0:
|
if alignment == 0:
|
||||||
discard
|
discard
|
||||||
|
|
|
||||||
|
|
@ -6433,38 +6433,39 @@ generates:
|
||||||
unsigned int flag:1;
|
unsigned int flag:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
Alignas pragma
|
|
||||||
--------------
|
|
||||||
|
|
||||||
The ``alignas`` pragma is for variables and object field members. It
|
Align pragma
|
||||||
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
|
The `align`:idx: pragma is for variables and object field members. It
|
||||||
declaration are ignored. Alignments that are weaker that the
|
modifies the alignment requirement of the entity being declared. The
|
||||||
alignment requirement of the type are ignored. ``alignas(0)`` is
|
argument must be a constant power of 2. Valid non-zero
|
||||||
always ignored.
|
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
|
.. code-block:: Nim
|
||||||
|
|
||||||
type
|
type
|
||||||
sseType = object
|
sseType = object
|
||||||
sseData {.alignas(16).}: array[4,float32]
|
sseData {.align(16).}: array[4,float32]
|
||||||
|
|
||||||
# every object will be aligned to 128-byte boundary
|
# every object will be aligned to 128-byte boundary
|
||||||
Data = object
|
Data = object
|
||||||
x: char
|
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() =
|
proc main() =
|
||||||
echo "sizeof(Data) = ", sizeof(Data), " (1 byte + 127 bytes padding + 128-byte array)"
|
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)
|
# output: sizeof(Data) = 256 (1 byte + 127 bytes padding + 128-byte array)
|
||||||
echo "alignment of sseType is ", alignof(sseType)
|
echo "alignment of sseType is ", alignof(sseType)
|
||||||
# output: alignment of sseType is 16
|
# 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()
|
main()
|
||||||
|
|
||||||
This pragma has no effect on nimvm or the js backend.
|
This pragma has no effect for the JS backend.
|
||||||
|
|
||||||
|
|
||||||
Volatile pragma
|
Volatile pragma
|
||||||
---------------
|
---------------
|
||||||
|
|
|
||||||
|
|
@ -256,7 +256,6 @@ __clang__
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdalign.h>
|
|
||||||
|
|
||||||
/* C99 compiler? */
|
/* C99 compiler? */
|
||||||
#if (defined(__STD_VERSION__) && (__STD_VERSION__ >= 199901))
|
#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
|
# define NIM_EXTERNC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# define NIM_ALIGN(x) __declspec(align(x))
|
||||||
|
#else
|
||||||
|
# define NIM_ALIGN(x) __attribute__((aligned(x)))
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ---------------- platform specific includes ----------------------- */
|
/* ---------------- platform specific includes ----------------------- */
|
||||||
|
|
||||||
/* VxWorks related includes */
|
/* VxWorks related includes */
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
var myglobal1* {.alignas(128).}: int32
|
var myglobal1* {.align(128).}: int32
|
||||||
var myglobal2* {.alignas(128).}: int32
|
var myglobal2* {.align(128).}: int32
|
||||||
var myglobal3* {.alignas(128).}: int32
|
var myglobal3* {.align(128).}: int32
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
discard """
|
discard """
|
||||||
ccodeCheck: "\\i @'alignas(128) NI mylocal1' .*"
|
ccodeCheck: "\\i @'NIM_ALIGN(128) NI mylocal1' .*"
|
||||||
target: "c cpp"
|
target: "c cpp"
|
||||||
output: "alignas ok"
|
output: "align ok"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# This is for Azure. The keyword ``alignof`` only exists in ``c++11``
|
# 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
|
import globalalignas
|
||||||
|
|
||||||
var toplevel1 {.alignas: 32.} : int32
|
var toplevel1 {.align: 32.} : int32
|
||||||
var toplevel2 {.alignas: 32.} : int32
|
var toplevel2 {.align: 32.} : int32
|
||||||
var toplevel3 {.alignas: 32.} : int32
|
var toplevel3 {.align: 32.} : int32
|
||||||
|
|
||||||
proc foobar() =
|
proc foobar() =
|
||||||
var myvar1 {.global, alignas(64).}: int = 123
|
var myvar1 {.global, align(64).}: int = 123
|
||||||
var myvar2 {.global, alignas(64).}: int = 123
|
var myvar2 {.global, align(64).}: int = 123
|
||||||
var myvar3 {.global, alignas(64).}: int = 123
|
var myvar3 {.global, align(64).}: int = 123
|
||||||
|
|
||||||
doAssert (cast[uint](addr(myglobal1)) and 127) == 0
|
doAssert (cast[uint](addr(myglobal1)) and 127) == 0
|
||||||
doAssert (cast[uint](addr(myglobal2)) 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(toplevel2)) and 31) == 0
|
||||||
doAssert (cast[uint](addr(toplevel3)) and 31) == 0
|
doAssert (cast[uint](addr(toplevel3)) and 31) == 0
|
||||||
|
|
||||||
# test multiple alignas expressions
|
# test multiple align expressions
|
||||||
var mylocal1 {.alignas(0), alignas(128), alignas(32).}: int = 123
|
var mylocal1 {.align(0), align(128), align(32).}: int = 123
|
||||||
var mylocal2 {.alignas(128), alignas(0), alignas(32).}: int = 123
|
var mylocal2 {.align(128), align(0), align(32).}: int = 123
|
||||||
var mylocal3 {.alignas(0), alignas(32), alignas(128).}: int = 123
|
var mylocal3 {.align(0), align(32), align(128).}: int = 123
|
||||||
|
|
||||||
doAssert (cast[uint](addr(mylocal1)) and 127) == 0
|
doAssert (cast[uint](addr(mylocal1)) and 127) == 0
|
||||||
doAssert (cast[uint](addr(mylocal2)) and 127) == 0
|
doAssert (cast[uint](addr(mylocal2)) and 127) == 0
|
||||||
doAssert (cast[uint](addr(mylocal3)) and 127) == 0
|
doAssert (cast[uint](addr(mylocal3)) and 127) == 0
|
||||||
|
|
||||||
echo "alignas ok"
|
echo "align ok"
|
||||||
|
|
||||||
foobar()
|
foobar()
|
||||||
|
|
|
||||||
|
|
@ -4,4 +4,4 @@ errormsg: "power of two or 0 expected"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
proc foobar() =
|
proc foobar() =
|
||||||
let something {.alignas(33).} = 123
|
let something {.align(33).} = 123
|
||||||
|
|
|
||||||
|
|
@ -336,10 +336,10 @@ testinstance:
|
||||||
a: int32
|
a: int32
|
||||||
b: T
|
b: T
|
||||||
|
|
||||||
# this type mixes `packed` with `alignas`.
|
# this type mixes `packed` with `align`.
|
||||||
MyCustomAlignPackedObject {.objectconfig.} = object
|
MyCustomAlignPackedObject {.objectconfig.} = object
|
||||||
a: char
|
a: char
|
||||||
b {.alignas: 32.}: int32 # alignas overrides `packed` for this field.
|
b {.align: 32.}: int32 # align overrides `packed` for this field.
|
||||||
c: char
|
c: char
|
||||||
d: int32 # unaligned
|
d: int32 # unaligned
|
||||||
|
|
||||||
|
|
@ -496,11 +496,11 @@ type
|
||||||
|
|
||||||
MyCustomAlignUnion {.union.} = object
|
MyCustomAlignUnion {.union.} = object
|
||||||
c: char
|
c: char
|
||||||
a {.alignas: 32.}: int
|
a {.align: 32.}: int
|
||||||
|
|
||||||
MyCustomAlignObject = object
|
MyCustomAlignObject = object
|
||||||
c: char
|
c: char
|
||||||
a {.alignas: 32.}: int
|
a {.align: 32.}: int
|
||||||
|
|
||||||
doAssert sizeof(MyUnionType) == 4
|
doAssert sizeof(MyUnionType) == 4
|
||||||
doAssert sizeof(MyCustomAlignUnion) == 32
|
doAssert sizeof(MyCustomAlignUnion) == 32
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue