mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-19 14:00:35 +00:00
sizeof alignof offsetof macros api (#10855)
This commit is contained in:
committed by
Andreas Rumpf
parent
16fcbee1bc
commit
188870648a
@@ -662,7 +662,7 @@ type
|
||||
|
||||
mNIntVal, mNFloatVal, mNSymbol, mNIdent, mNGetType, mNStrVal, mNSetIntVal,
|
||||
mNSetFloatVal, mNSetSymbol, mNSetIdent, mNSetType, mNSetStrVal, mNLineInfo,
|
||||
mNNewNimNode, mNCopyNimNode, mNCopyNimTree, mStrToIdent, mNSigHash,
|
||||
mNNewNimNode, mNCopyNimNode, mNCopyNimTree, mStrToIdent, mNSigHash, mNSizeOf,
|
||||
mNBindSym, mLocals, mNCallSite,
|
||||
mEqIdent, mEqNimrodNode, mSameNodeType, mGetImpl, mNGenSym,
|
||||
mNHint, mNWarning, mNError,
|
||||
|
||||
@@ -86,6 +86,7 @@ proc initDefines*(symbols: StringTableRef) =
|
||||
defineSymbol("nimHasNilSeqs")
|
||||
defineSymbol("nimHasSignatureHashInMacro")
|
||||
defineSymbol("nimHasDefault")
|
||||
defineSymbol("nimMacrosSizealignof")
|
||||
for f in low(Feature)..high(Feature):
|
||||
defineSymbol("nimHas" & $f)
|
||||
|
||||
|
||||
@@ -1477,6 +1477,27 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
regs[ra].node = opMapTypeImplToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc])
|
||||
else:
|
||||
stackTrace(c, tos, pc, "node has no type")
|
||||
of opcNGetSize:
|
||||
decodeBImm(rkInt)
|
||||
let n = regs[rb].node
|
||||
case imm
|
||||
of 0: # size
|
||||
if n.typ == nil:
|
||||
stackTrace(c, tos, pc, "node has no type")
|
||||
else:
|
||||
regs[ra].intVal = getSize(c.config, n.typ)
|
||||
of 1: # align
|
||||
if n.typ == nil:
|
||||
stackTrace(c, tos, pc, "node has no type")
|
||||
else:
|
||||
regs[ra].intVal = getAlign(c.config, n.typ)
|
||||
else: # offset
|
||||
if n.kind != nkSym:
|
||||
stackTrace(c, tos, pc, "node is not a symbol")
|
||||
elif n.sym.kind != skField:
|
||||
stackTrace(c, tos, pc, "symbol is not a field (nskField)")
|
||||
else:
|
||||
regs[ra].intVal = n.sym.offset
|
||||
of opcNStrVal:
|
||||
decodeB(rkNode)
|
||||
createStr regs[ra]
|
||||
|
||||
@@ -93,6 +93,7 @@ type
|
||||
opcNGetType,
|
||||
opcNStrVal,
|
||||
opcNSigHash,
|
||||
opcNGetSize,
|
||||
|
||||
opcNSetIntVal,
|
||||
opcNSetFloatVal, opcNSetSymbol, opcNSetIdent, opcNSetType, opcNSetStrVal,
|
||||
|
||||
@@ -1236,6 +1236,12 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||
c.gABC(n, opcNGetType, dest, tmp, rc)
|
||||
c.freeTemp(tmp)
|
||||
#genUnaryABC(c, n, dest, opcNGetType)
|
||||
of mNSizeOf:
|
||||
let imm = case n[0].sym.name.s:
|
||||
of "getSize": 0
|
||||
of "getAlign": 1
|
||||
else: 2 # "getOffset"
|
||||
c.genUnaryABI(n, dest, opcNGetSize, imm)
|
||||
of mNStrVal: genUnaryABC(c, n, dest, opcNStrVal)
|
||||
of mNSigHash: genUnaryABC(c, n , dest, opcNSigHash)
|
||||
of mNSetIntVal:
|
||||
|
||||
@@ -1582,3 +1582,15 @@ proc getProjectPath*(): string = discard
|
||||
## Returns the path to the currently compiling project, not to
|
||||
## be confused with ``system.currentSourcePath`` which returns
|
||||
## the path of the current module.
|
||||
|
||||
when defined(nimMacrosSizealignof):
|
||||
proc getSize*(arg: NimNode): int {.magic: "NSizeOf", noSideEffect.} =
|
||||
## Returns the same result as ``system.sizeof``, but it works on
|
||||
## ``NimNode`` for use in macro context.
|
||||
proc getAlign*(arg: NimNode): int {.magic: "NSizeOf", noSideEffect.} =
|
||||
## Returns the same result as ``system.alignof``, but it works on
|
||||
## ``NimNode`` for use in macro context.
|
||||
proc getOffset*(arg: NimNode): int {.magic: "NSizeOf", noSideEffect.} =
|
||||
## Returns the same result as ``system.offsetof``, but it expects
|
||||
## a resolved symbol node from a field of a type. Therefore it
|
||||
## only requires one argument instead of two.
|
||||
|
||||
@@ -3,6 +3,7 @@ discard """
|
||||
body executed
|
||||
body executed
|
||||
OK
|
||||
macros api OK
|
||||
'''
|
||||
"""
|
||||
|
||||
@@ -485,3 +486,53 @@ if failed:
|
||||
quit("FAIL")
|
||||
else:
|
||||
echo "OK"
|
||||
|
||||
##########################################
|
||||
# sizeof macros API
|
||||
##########################################
|
||||
|
||||
import macros
|
||||
|
||||
type
|
||||
Vec2f = object
|
||||
x,y: float32
|
||||
|
||||
Vec4f = object
|
||||
x,y,z,w: float32
|
||||
|
||||
# this type is constructed to have no platform depended alignment.
|
||||
ParticleDataA = object
|
||||
pos, vel: Vec2f
|
||||
birthday: float32
|
||||
padding: float32
|
||||
moreStuff: Vec4f
|
||||
|
||||
const expected = [
|
||||
# name size align offset
|
||||
("pos", 8, 4, 0),
|
||||
("vel", 8, 4, 8),
|
||||
("birthday", 4, 4, 16),
|
||||
("padding", 4, 4, 20),
|
||||
("moreStuff", 16, 4, 24)
|
||||
]
|
||||
|
||||
macro typeProcessing(arg: typed): untyped =
|
||||
let recList = arg.getTypeImpl[2]
|
||||
recList.expectKind nnkRecList
|
||||
for i, identDefs in recList:
|
||||
identDefs.expectKind nnkIdentDefs
|
||||
identDefs.expectLen 3
|
||||
let sym = identDefs[0]
|
||||
sym.expectKind nnkSym
|
||||
doAssert expected[i][0] == sym.strVal
|
||||
doAssert expected[i][1] == getSize(sym)
|
||||
doAssert expected[i][2] == getAlign(sym)
|
||||
doAssert expected[i][3] == getOffset(sym)
|
||||
|
||||
result = newCall(bindSym"echo", newLit("macros api OK"))
|
||||
|
||||
proc main() =
|
||||
var mylocal: ParticleDataA
|
||||
typeProcessing(mylocal)
|
||||
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user