diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ast.nim | 1 | ||||
-rw-r--r-- | compiler/ccgtypes.nim | 2 | ||||
-rw-r--r-- | compiler/cgen.nim | 8 | ||||
-rw-r--r-- | compiler/pragmas.nim | 17 | ||||
-rw-r--r-- | compiler/sizealignoffsetimpl.nim | 4 |
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: |