From 212febef9071e9c4c20ac16ecba5ddc6f5985205 Mon Sep 17 00:00:00 2001 From: metagn Date: Sat, 12 Apr 2025 17:25:47 +0300 Subject: [PATCH 1/2] allow setting arbitrary size for importc types closes #7674 --- compiler/pragmas.nim | 20 ++++++++++++-------- compiler/types.nim | 11 +++++++++++ doc/manual.md | 4 ++-- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 51e044ce0bf85..8cf547c9bed93 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -947,15 +947,19 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, of wSize: if sym.typ == nil: invalidPragma(c, it) var size = expectIntLit(c, it) - case size - of 1, 2, 4: - sym.typ.size = size - sym.typ.align = int16 size - of 8: - sym.typ.size = 8 - sym.typ.align = floatInt64Align(c.config) + if sfImportc in sym.flags: + # no restrictions on size for imported types + setImportedTypeSize(c.config, sym.typ, size) else: - localError(c.config, it.info, "size may only be 1, 2, 4 or 8") + case size + of 1, 2, 4: + sym.typ.size = size + sym.typ.align = int16 size + of 8: + sym.typ.size = 8 + sym.typ.align = floatInt64Align(c.config) + else: + localError(c.config, it.info, "size may only be 1, 2, 4 or 8") of wAlign: let alignment = expectIntLit(c, it) if isPowerOfTwo(alignment) and alignment > 0: diff --git a/compiler/types.nim b/compiler/types.nim index 9853cf1222410..914f57fc8e10b 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -1515,6 +1515,17 @@ proc getSize*(conf: ConfigRef; typ: PType): BiggestInt = computeSizeAlign(conf, typ) result = typ.size +proc setImportedTypeSize*(conf: ConfigRef, t: PType, size: int) = + t.size = size + if tfPacked in t.flags or size <= 1: + t.align = 1 + elif size <= 2: + t.align = 2 + elif size <= 4: + t.align = 4 + else: + t.align = floatInt64Align(conf) + proc isConcept*(t: PType): bool= case t.kind of tyConcept: true diff --git a/doc/manual.md b/doc/manual.md index 8eab6683d5f51..9abd0e762c8d6 100644 --- a/doc/manual.md +++ b/doc/manual.md @@ -7815,6 +7815,8 @@ The `size pragma` allows specifying the size of the enum type. doAssert sizeof(EventType) == sizeof(uint32) ``` +When used for enum types, the `size pragma` accepts only the values 1, 2, 4 or 8. + The `size pragma` can also specify the size of an `importc` incomplete object type so that one can get the size of it at compile time even if it was declared without fields. @@ -7827,8 +7829,6 @@ so that one can get the size of it at compile time even if it was declared witho echo sizeof(AtomicFlag) ``` -The `size pragma` accepts only the values 1, 2, 4 or 8. - Align pragma ------------ From 81a3223a839dae2694135e6a20840ead7f3abb92 Mon Sep 17 00:00:00 2001 From: metagn Date: Sat, 12 Apr 2025 17:30:53 +0300 Subject: [PATCH 2/2] add not very rigorous test --- tests/c/timportedsize.nim | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/c/timportedsize.nim diff --git a/tests/c/timportedsize.nim b/tests/c/timportedsize.nim new file mode 100644 index 0000000000000..4541ac51d39d9 --- /dev/null +++ b/tests/c/timportedsize.nim @@ -0,0 +1,10 @@ +{.emit: """ +typedef struct Foo { + NI64 a; + NI64 b; +} Foo; +""".} + +type Foo {.importc: "Foo", size: 16.} = object + +var x: Foo