implemented alignas pragma (#12643)

* implemented alignas pragma

* fix bootstrap

* generate c++ compatible syntax for alignas

* Make it work.

* Multiple alignof expressions. Implement top level alignof.
This commit is contained in:
Arne Döring 2019-11-13 09:22:41 +01:00 • committed by cooldome
commit 0496a666e2
13 changed files with 153 additions and 19 deletions

View file

@ -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

View file

@ -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:

View file

@ -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], "*")

View file

@ -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)

View file

@ -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: