Skip to content

Commit 3eb04e3

Browse files
authored
cgen,checker: add $if sizeof(T) == int_literal { support (#24831)
1 parent 35af6a8 commit 3eb04e3

4 files changed

Lines changed: 225 additions & 0 deletions

File tree

‎vlib/v/checker/comptime.v‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,7 @@ fn (mut c Checker) comptime_if_cond(mut cond ast.Expr, pos token.Pos) ComptimeBr
891891
ComptimeBranchSkipState.skip
892892
}
893893
}
894+
} else if cond.left is ast.SizeOf {
894895
} else {
895896
c.error('invalid `\$if` condition: ${cond.left.type_name()}',
896897
cond.pos)
@@ -920,6 +921,8 @@ fn (mut c Checker) comptime_if_cond(mut cond ast.Expr, pos token.Pos) ComptimeBr
920921
if cond.left is ast.SelectorExpr && cond.right is ast.IntegerLiteral
921922
&& c.comptime.is_comptime_selector_field_name(cond.left, 'indirections') {
922923
return .unknown
924+
} else if cond.left is ast.SizeOf {
925+
return .unknown
923926
}
924927
c.error('invalid `\$if` condition', cond.pos)
925928
}

‎vlib/v/checker/if.v‎

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,61 @@ fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
349349
}
350350
else {}
351351
}
352+
} else if left is ast.SizeOf && right is ast.IntegerLiteral {
353+
// TODO: support struct.fieldname
354+
typ := c.unwrap_generic(left.typ)
355+
if typ == 0 {
356+
c.error('invalid `\$if` condition: expected a type', branch.cond.left.pos())
357+
} else {
358+
s, _ := c.table.type_size(c.unwrap_generic(typ))
359+
skip_state = match branch.cond.op {
360+
.gt {
361+
if s > right.val.i64() {
362+
ComptimeBranchSkipState.eval
363+
} else {
364+
ComptimeBranchSkipState.skip
365+
}
366+
}
367+
.lt {
368+
if s < right.val.i64() {
369+
ComptimeBranchSkipState.eval
370+
} else {
371+
ComptimeBranchSkipState.skip
372+
}
373+
}
374+
.ge {
375+
if s >= right.val.i64() {
376+
ComptimeBranchSkipState.eval
377+
} else {
378+
ComptimeBranchSkipState.skip
379+
}
380+
}
381+
.le {
382+
if s <= right.val.i64() {
383+
ComptimeBranchSkipState.eval
384+
} else {
385+
ComptimeBranchSkipState.skip
386+
}
387+
}
388+
.ne {
389+
if s != right.val.i64() {
390+
ComptimeBranchSkipState.eval
391+
} else {
392+
ComptimeBranchSkipState.skip
393+
}
394+
}
395+
.eq {
396+
if s == right.val.i64() {
397+
ComptimeBranchSkipState.eval
398+
} else {
399+
ComptimeBranchSkipState.skip
400+
}
401+
}
402+
else {
403+
ComptimeBranchSkipState.skip
404+
}
405+
}
406+
}
352407
}
353408
}
354409
}

‎vlib/v/gen/c/comptime.v‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,23 @@ fn (mut g Gen) comptime_if_cond(cond ast.Expr, pkg_exist bool) (bool, bool) {
685685
g.write(' ${cond.op} ')
686686
r, d2 := g.comptime_if_cond(cond.right, pkg_exist)
687687
return if cond.op == .eq { l == r } else { l != r }, d1 && d1 == d2
688+
}
689+
if cond.left is ast.SizeOf && cond.left.typ != 0
690+
&& cond.right is ast.IntegerLiteral {
691+
// TODO: support struct.fieldname
692+
s, _ := g.table.type_size(g.unwrap_generic(cond.left.typ))
693+
right := cond.right as ast.IntegerLiteral
694+
is_true := match cond.op {
695+
.eq { s == right.val.i64() }
696+
.ne { s != right.val.i64() }
697+
else { false }
698+
}
699+
if is_true {
700+
g.write('1')
701+
} else {
702+
g.write('0')
703+
}
704+
return is_true, true
688705
} else {
689706
g.write('1')
690707
return true, true
@@ -748,6 +765,25 @@ fn (mut g Gen) comptime_if_cond(cond ast.Expr, pkg_exist bool) (bool, bool) {
748765
g.write('0')
749766
}
750767
return is_true, true
768+
}
769+
if cond.left is ast.SizeOf && cond.left.typ != 0
770+
&& cond.right is ast.IntegerLiteral {
771+
// TODO: support struct.fieldname
772+
s, _ := g.table.type_size(g.unwrap_generic(cond.left.typ))
773+
right := cond.right as ast.IntegerLiteral
774+
is_true := match cond.op {
775+
.gt { s > right.val.i64() }
776+
.lt { s < right.val.i64() }
777+
.ge { s >= right.val.i64() }
778+
.le { s <= right.val.i64() }
779+
else { false }
780+
}
781+
if is_true {
782+
g.write('1')
783+
} else {
784+
g.write('0')
785+
}
786+
return is_true, true
751787
} else {
752788
return true, false
753789
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
struct MyStruct {
2+
a u16
3+
b u8
4+
c u32
5+
d u64
6+
}
7+
8+
fn test_comptime_if_sizeof() {
9+
f[u16]()
10+
g[MyStruct]()
11+
12+
x := MyStruct{}
13+
// TODO: support struct.fieldname
14+
//$if sizeof(x.a) == 2 {
15+
// assert true
16+
//} $else {
17+
// assert false
18+
//}
19+
//
20+
//$if sizeof(x.d) != 2 {
21+
// assert false
22+
//} $else {
23+
// assert true
24+
//}
25+
}
26+
27+
fn f[T]() {
28+
$if sizeof(T) == 2 {
29+
assert true
30+
} $else {
31+
assert false
32+
}
33+
$if sizeof(T) != 2 {
34+
assert false
35+
} $else {
36+
assert true
37+
}
38+
$if sizeof(T) < 1 {
39+
assert false
40+
} $else {
41+
assert true
42+
}
43+
$if sizeof(T) < 3 {
44+
assert true
45+
} $else {
46+
assert false
47+
}
48+
$if sizeof(T) > 1 {
49+
assert true
50+
} $else {
51+
assert false
52+
}
53+
$if sizeof(T) > 2 {
54+
assert false
55+
} $else {
56+
assert true
57+
}
58+
$if sizeof(T) <= 2 {
59+
assert true
60+
} $else {
61+
assert false
62+
}
63+
$if sizeof(T) <= 1 {
64+
assert false
65+
} $else {
66+
assert true
67+
}
68+
$if sizeof(T) >= 2 {
69+
assert true
70+
} $else {
71+
assert false
72+
}
73+
$if sizeof(T) >= 3 {
74+
assert false
75+
} $else {
76+
assert true
77+
}
78+
}
79+
80+
fn g[T]() {
81+
$if sizeof(T) == 16 {
82+
assert true
83+
} $else {
84+
assert false
85+
}
86+
$if sizeof(T) != 16 {
87+
assert false
88+
} $else {
89+
assert true
90+
}
91+
$if sizeof(T) < 17 {
92+
assert true
93+
} $else {
94+
assert false
95+
}
96+
$if sizeof(T) < 15 {
97+
assert false
98+
} $else {
99+
assert true
100+
}
101+
$if sizeof(T) > 15 {
102+
assert true
103+
} $else {
104+
assert false
105+
}
106+
$if sizeof(T) > 16 {
107+
assert false
108+
} $else {
109+
assert true
110+
}
111+
$if sizeof(T) <= 16 {
112+
assert true
113+
} $else {
114+
assert false
115+
}
116+
$if sizeof(T) <= 15 {
117+
assert false
118+
} $else {
119+
assert true
120+
}
121+
$if sizeof(T) >= 16 {
122+
assert true
123+
} $else {
124+
assert false
125+
}
126+
$if sizeof(T) >= 17 {
127+
assert false
128+
} $else {
129+
assert true
130+
}
131+
}

0 commit comments

Comments
 (0)