Skip to content

Commit 77f4ce1

Browse files
committed
Improve specific argument unpackers
1 parent 9b7dd78 commit 77f4ce1

File tree

131 files changed

+1132
-1878
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

131 files changed

+1132
-1878
lines changed

include/deemon/arg.h

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,166 @@ DFUNDEF WUNUSED ATTR_INS(2, 1) NONNULL((3)) int
7070
(DCALL DeeArg_VUnpack)(size_t argc, /*nonnull_if(argc != 0)*/ DeeObject *const *argv,
7171
char const *__restrict format, va_list args);
7272

73+
#ifdef __OPTIMIZE_SIZE__
74+
#define _DeeArg_Unpack0(err, argc, argv, function_name) \
75+
do { \
76+
if (DeeArg_Unpack(argc, argv, ":" function_name)) \
77+
goto err; \
78+
} __WHILE0
79+
#define _DeeArg_Unpack1(err, argc, argv, function_name, p_arg0) \
80+
do { \
81+
if (DeeArg_Unpack(argc, argv, "o:" function_name, p_arg0)) \
82+
goto err; \
83+
} __WHILE0
84+
#define _DeeArg_Unpack2(err, argc, argv, function_name, p_arg0, p_arg1) \
85+
do { \
86+
if (DeeArg_Unpack(argc, argv, "oo:" function_name, p_arg0, p_arg1)) \
87+
goto err; \
88+
} __WHILE0
89+
#define _DeeArg_Unpack3(err, argc, argv, function_name, p_arg0, p_arg1, p_arg2) \
90+
do { \
91+
if (DeeArg_Unpack(argc, argv, "ooo:" function_name, p_arg0, p_arg1, p_arg2)) \
92+
goto err; \
93+
} __WHILE0
94+
#define _DeeArg_Unpack0Or1(err, argc, argv, function_name, p_arg0) \
95+
do { \
96+
if (DeeArg_Unpack(argc, argv, "|o:" function_name, p_arg0)) \
97+
goto err; \
98+
} __WHILE0
99+
#define _DeeArg_Unpack1Or2(err, argc, argv, function_name, p_arg0, p_arg1) \
100+
do { \
101+
if (DeeArg_Unpack(argc, argv, "o|o:" function_name, p_arg0, p_arg1)) \
102+
goto err; \
103+
} __WHILE0
104+
#define _DeeArg_Unpack0Or1Or2(err, argc, argv, function_name, p_arg0, p_arg1) \
105+
do { \
106+
if (DeeArg_Unpack(argc, argv, "|oo:" function_name, p_arg0, p_arg1)) \
107+
goto err; \
108+
} __WHILE0
109+
#define _DeeArg_Unpack1Or2Or3(err, argc, argv, function_name, p_arg0, p_arg1, p_arg2) \
110+
do { \
111+
if (DeeArg_Unpack(argc, argv, "o|oo:" function_name, p_arg0, p_arg1, p_arg2)) \
112+
goto err; \
113+
} __WHILE0
114+
#else /* __OPTIMIZE_SIZE__ */
115+
#define _DeeArg_Unpack0(err, argc, argv, function_name) \
116+
if unlikely((argc) != 0) { \
117+
DeeArg_BadArgc0(function_name, argc); \
118+
goto err; \
119+
} else \
120+
(void)(argv)
121+
#define _DeeArg_Unpack1(err, argc, argv, function_name, p_arg0) \
122+
if unlikely((argc) != 1) { \
123+
DeeArg_BadArgc1(function_name, argc); \
124+
goto err; \
125+
} else \
126+
(void)(*(DeeObject **)(p_arg0) = (argv)[0], \
127+
__builtin_assume(*(p_arg0) != NULL))
128+
#define _DeeArg_Unpack2(err, argc, argv, function_name, p_arg0, p_arg1) \
129+
if unlikely((argc) != 2) { \
130+
DeeArg_BadArgc(function_name, argc, 2); \
131+
goto err; \
132+
} else \
133+
(void)(*(DeeObject **)(p_arg0) = (argv)[0], \
134+
*(DeeObject **)(p_arg1) = (argv)[1], \
135+
__builtin_assume(*(p_arg0) != NULL), \
136+
__builtin_assume(*(p_arg1) != NULL))
137+
#define _DeeArg_Unpack3(err, argc, argv, function_name, p_arg0, p_arg1, p_arg2) \
138+
if unlikely((argc) != 3) { \
139+
DeeArg_BadArgc(function_name, argc, 3); \
140+
goto err; \
141+
} else \
142+
(void)(*(DeeObject **)(p_arg0) = (argv)[0], \
143+
*(DeeObject **)(p_arg1) = (argv)[1], \
144+
*(DeeObject **)(p_arg2) = (argv)[2], \
145+
__builtin_assume(*(p_arg0) != NULL), \
146+
__builtin_assume(*(p_arg1) != NULL), \
147+
__builtin_assume(*(p_arg2) != NULL))
148+
#define _DeeArg_Unpack0Or1(err, argc, argv, function_name, p_arg0) \
149+
do { \
150+
switch (argc) { \
151+
case 1: \
152+
*(DeeObject **)(p_arg0) = (argv)[0]; \
153+
__builtin_assume(*(p_arg0) != NULL); \
154+
break; \
155+
case 0: \
156+
break; \
157+
default: \
158+
DeeArg_BadArgcEx(function_name, argc, 0, 1); \
159+
goto err; \
160+
} \
161+
} __WHILE0
162+
#define _DeeArg_Unpack1Or2(err, argc, argv, function_name, p_arg0, p_arg1) \
163+
do { \
164+
switch (argc) { \
165+
case 2: \
166+
*(DeeObject **)(p_arg1) = (argv)[1]; \
167+
__builtin_assume(*(p_arg1) != NULL); \
168+
ATTR_FALLTHROUGH \
169+
case 1: \
170+
*(DeeObject **)(p_arg0) = (argv)[0]; \
171+
__builtin_assume(*(p_arg0) != NULL); \
172+
break; \
173+
default: \
174+
DeeArg_BadArgcEx(function_name, argc, 1, 2); \
175+
goto err; \
176+
} \
177+
} __WHILE0
178+
#define _DeeArg_Unpack0Or1Or2(err, argc, argv, function_name, p_arg0, p_arg1) \
179+
do { \
180+
switch (argc) { \
181+
case 2: \
182+
*(DeeObject **)(p_arg1) = (argv)[1]; \
183+
__builtin_assume(*(p_arg1) != NULL); \
184+
ATTR_FALLTHROUGH \
185+
case 1: \
186+
*(DeeObject **)(p_arg0) = (argv)[0]; \
187+
__builtin_assume(*(p_arg0) != NULL); \
188+
break; \
189+
case 0: \
190+
break; \
191+
default: \
192+
DeeArg_BadArgcEx(function_name, argc, 0, 2); \
193+
goto err; \
194+
} \
195+
} __WHILE0
196+
#define _DeeArg_Unpack1Or2Or3(err, argc, argv, function_name, p_arg0, p_arg1, p_arg2) \
197+
do { \
198+
switch (argc) { \
199+
case 3: \
200+
*(DeeObject **)(p_arg2) = (argv)[2]; \
201+
__builtin_assume(*(p_arg2) != NULL); \
202+
ATTR_FALLTHROUGH \
203+
case 2: \
204+
*(DeeObject **)(p_arg1) = (argv)[1]; \
205+
__builtin_assume(*(p_arg1) != NULL); \
206+
ATTR_FALLTHROUGH \
207+
case 1: \
208+
*(DeeObject **)(p_arg0) = (argv)[0]; \
209+
__builtin_assume(*(p_arg0) != NULL); \
210+
break; \
211+
default: \
212+
DeeArg_BadArgcEx(function_name, argc, 1, 3); \
213+
goto err; \
214+
} \
215+
} __WHILE0
216+
#endif /* !__OPTIMIZE_SIZE__ */
217+
218+
/* Helper functions for throwing invalid-argc errors */
219+
DFUNDEF ATTR_COLD int (DCALL DeeArg_BadArgc)(char const *function_name, size_t real_argc, size_t want_argc);
220+
DFUNDEF ATTR_COLD int (DCALL DeeArg_BadArgc0)(char const *function_name, size_t real_argc);
221+
DFUNDEF ATTR_COLD int (DCALL DeeArg_BadArgc1)(char const *function_name, size_t real_argc);
222+
DFUNDEF ATTR_COLD int (DCALL DeeArg_BadArgcEx)(char const *function_name, size_t real_argc, size_t want_argc_min, size_t want_argc_max);
223+
#ifndef Dee_ASSUMED_VALUE_IS_NOOP
224+
#define DeeArg_BadArgc(function_name, real_argc, want_argc) \
225+
Dee_ASSUMED_VALUE((DeeArg_BadArgc)(function_name, real_argc, want_argc), -1)
226+
#define DeeArg_BadArgc0(function_name, real_argc) \
227+
Dee_ASSUMED_VALUE((DeeArg_BadArgc0)(function_name, real_argc), -1)
228+
#define DeeArg_BadArgc1(function_name, real_argc) \
229+
Dee_ASSUMED_VALUE((DeeArg_BadArgc1)(function_name, real_argc), -1)
230+
#define DeeArg_BadArgcEx(function_name, real_argc, want_argc_min, want_argc_max) \
231+
Dee_ASSUMED_VALUE((DeeArg_BadArgcEx)(function_name, real_argc, want_argc_min, want_argc_max), -1)
232+
#endif /* !Dee_ASSUMED_VALUE_IS_NOOP */
73233

74234

75235
struct Dee_keyword {

include/deemon/mapfile.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ DeeMapFile_Fini(struct DeeMapFile *__restrict self);
124124
* this number of bytes has been reached, nul bytes are mapped for its remainder.
125125
* Note that this doesn't include `num_trailing_nulbytes', meaning that (e.g.) when
126126
* an entirely empty file is mapped you get a buffer like:
127-
* >> mf_addr = calloc(min_size + num_trailing_nulbytes);
128-
* >> mf_size = min_size;
127+
* >> mf_addr = calloc(min_bytes + num_trailing_nulbytes);
128+
* >> mf_size = min_bytes;
129129
* This argument essentially acts as if `fd' was at least `min_bytes' bytes large
130130
* by filling the non-present address range with all zeroes.
131131
* @param: max_bytes: The max number of bytes (excluding num_trailing_nulbytes) that should be mapped

include/deemon/notify.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,7 @@ DFUNDEF WUNUSED NONNULL((1)) DREF DeeObject *DCALL Dee_GetEnv(DeeObject *__restr
9090
* >> DREF DeeObject *DCALL
9191
* >> get_my_envint(size_t argc, DeeObject *const *argv) {
9292
* >> int result;
93-
* >> if (DeeArg_Unpack(argc, argv, ":get_my_envint"))
94-
* >> goto err;
93+
* >> _DeeArg_Unpack0(err, argc, argv, "get_my_envint");
9594
* >> if (my_envint_get(&result))
9695
* >> goto err;
9796
* >> return DeeInt_NewInt(result);

lib/rt/gen/unpack.dee

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,7 @@ function print_DeeArg_Unpack(name: string = "",
796796
err: string = "err") {
797797
if (params is string)
798798
params = parseParamSpec(params).cached;
799+
local nameRepr = name ? repr name : "NULL";
799800
if (params) {
800801
print(" struct {");
801802
for (local param: params) {
@@ -810,9 +811,26 @@ function print_DeeArg_Unpack(name: string = "",
810811
if (param.cInit !is none && param.cInit != "?")
811812
print(f" {args}.{param.cName} = {param.cInit};");
812813
}
813-
print(f" if (DeeArg_UnpackStruct({argc}, {argv}, {
814-
getUnpackFormat(name: name, params: params)}, &{args}))");
815-
print(f" goto {err};");
814+
local simpleFormat = getUnpackFormat(params: params);
815+
local argsPointerList = ", ".join(for (local x: params) f"&{args}.{x.cName}");
816+
local dedicatedUnpackFunction: string | none = {
817+
'""': "_DeeArg_Unpack0",
818+
'"o"': "_DeeArg_Unpack1",
819+
'"oo"': "_DeeArg_Unpack2",
820+
'"ooo"': "_DeeArg_Unpack3",
821+
'"|o"': "_DeeArg_Unpack0Or1",
822+
'"o|o"': "_DeeArg_Unpack1Or2",
823+
'"|oo"': "_DeeArg_Unpack0Or1Or2",
824+
'"o|oo"': "_DeeArg_Unpack1Or2Or3",
825+
}.get(simpleFormat);
826+
if (dedicatedUnpackFunction !is none) {
827+
print(f" {dedicatedUnpackFunction}({err}, {argc}, {argv}, {
828+
nameRepr}{argsPointerList ? ", " : ""}{argsPointerList});");
829+
} else {
830+
print(f" if (DeeArg_UnpackStruct({argc}, {argv}, {
831+
getUnpackFormat(name: name, params: params)}, &{args}))");
832+
print(f" goto {err};");
833+
}
816834
for (local param: params) {
817835
if (param.decode !is none) {
818836
param.decode.printCDecodeDecl(
@@ -821,9 +839,7 @@ function print_DeeArg_Unpack(name: string = "",
821839
}
822840
}
823841
} else {
824-
print(f" if (DeeArg_Unpack({argc}, {argv}, {
825-
getUnpackFormat(name: name, params: params)}))");
826-
print(f" goto {err};");
842+
print(f" _DeeArg_Unpack0({err}, {argc}, {argv}, {nameRepr});");
827843
}
828844
}
829845

@@ -1029,7 +1045,7 @@ function print_libMethod(name: string,
10291045
params: string | {UnpackParam...} = (),
10301046
dReturnType: string = "",
10311047
kw: bool | none = none,
1032-
libname: string = none,
1048+
libname: string | none = none,
10331049
visi: string = "PRIVATE",
10341050
isvarying: bool = false,
10351051
ispure: bool = false,

0 commit comments

Comments
 (0)