Skip to content

Commit 1ef9a65

Browse files
authored
allow setting arbitrary size for importc types (#24868)
split from #24204, closes #7674 The `{.size.}` pragma no longer restricts the given size to 1, 2, 4 or 8 if it is used for an imported type. This is not tested very thoroughly but there's no obvious reason to disallow it.
1 parent 334f96c commit 1ef9a65

File tree

4 files changed

+35
-10
lines changed

4 files changed

+35
-10
lines changed

compiler/pragmas.nim

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -947,15 +947,19 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
947947
of wSize:
948948
if sym.typ == nil: invalidPragma(c, it)
949949
var size = expectIntLit(c, it)
950-
case size
951-
of 1, 2, 4:
952-
sym.typ.size = size
953-
sym.typ.align = int16 size
954-
of 8:
955-
sym.typ.size = 8
956-
sym.typ.align = floatInt64Align(c.config)
950+
if sfImportc in sym.flags:
951+
# no restrictions on size for imported types
952+
setImportedTypeSize(c.config, sym.typ, size)
957953
else:
958-
localError(c.config, it.info, "size may only be 1, 2, 4 or 8")
954+
case size
955+
of 1, 2, 4:
956+
sym.typ.size = size
957+
sym.typ.align = int16 size
958+
of 8:
959+
sym.typ.size = 8
960+
sym.typ.align = floatInt64Align(c.config)
961+
else:
962+
localError(c.config, it.info, "size may only be 1, 2, 4 or 8")
959963
of wAlign:
960964
let alignment = expectIntLit(c, it)
961965
if isPowerOfTwo(alignment) and alignment > 0:

compiler/types.nim

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,6 +1515,17 @@ proc getSize*(conf: ConfigRef; typ: PType): BiggestInt =
15151515
computeSizeAlign(conf, typ)
15161516
result = typ.size
15171517

1518+
proc setImportedTypeSize*(conf: ConfigRef, t: PType, size: int) =
1519+
t.size = size
1520+
if tfPacked in t.flags or size <= 1:
1521+
t.align = 1
1522+
elif size <= 2:
1523+
t.align = 2
1524+
elif size <= 4:
1525+
t.align = 4
1526+
else:
1527+
t.align = floatInt64Align(conf)
1528+
15181529
proc isConcept*(t: PType): bool=
15191530
case t.kind
15201531
of tyConcept: true

doc/manual.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7815,6 +7815,8 @@ The `size pragma` allows specifying the size of the enum type.
78157815
doAssert sizeof(EventType) == sizeof(uint32)
78167816
```
78177817

7818+
When used for enum types, the `size pragma` accepts only the values 1, 2, 4 or 8.
7819+
78187820
The `size pragma` can also specify the size of an `importc` incomplete object type
78197821
so that one can get the size of it at compile time even if it was declared without fields.
78207822

@@ -7827,8 +7829,6 @@ so that one can get the size of it at compile time even if it was declared witho
78277829
echo sizeof(AtomicFlag)
78287830
```
78297831

7830-
The `size pragma` accepts only the values 1, 2, 4 or 8.
7831-
78327832

78337833
Align pragma
78347834
------------

tests/c/timportedsize.nim

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{.emit: """
2+
typedef struct Foo {
3+
NI64 a;
4+
NI64 b;
5+
} Foo;
6+
""".}
7+
8+
type Foo {.importc: "Foo", size: 16.} = object
9+
10+
var x: Foo

0 commit comments

Comments
 (0)