Bladeren bron

basic type unittests pass

Tobias Waldekranz.com 8 jaren geleden
bovenliggende
commit
21292b4bb7
5 gewijzigde bestanden met toevoegingen van 271 en 238 verwijderingen
  1. 6 1
      ply.c
  2. 104 218
      type.c
  3. 9 7
      type.h
  4. 81 12
      type_test.c
  5. 71 0
      unittest.h

+ 6 - 1
ply.c

@@ -63,7 +63,12 @@ struct ctx *ctx_get(void)
63 63
 	/* prog->globals = ctx->globals; */
64 64
 
65 65
 	prog->probe = "k:SyS_read";
66
-	/* { @t[0] = time(); @reads[pid()] = quantize(arg2) } */
66
+
67
+	/* { 
68
+	 * 	@t[0] = time();
69
+	 * 	@reads[pid()] = quantize(arg2)
70
+	 * }
71
+	 */
67 72
 	prog->ast =
68 73
 		node_expr("",
69 74
 			  node_expr("=",

+ 104 - 218
type.c

@@ -57,10 +57,10 @@ void type_dump(struct type *t, FILE *fp)
57 57
 		fputs("struct ", fp);
58 58
 		fputs(t->sou.name, fp);
59 59
 		break;
60
-	case T_UNION:
61
-		fputs("union ", fp);
62
-		fputs(t->sou.name, fp);
63
-		break;
60
+	/* case T_UNION: */
61
+	/* 	fputs("union ", fp); */
62
+	/* 	fputs(t->sou.name, fp); */
63
+	/* 	break; */
64 64
 	case T_FUNC:
65 65
 		type_dump_func(t, fp);
66 66
 		break;
@@ -97,7 +97,7 @@ void type_dump_cdecl(struct type *t, FILE *fp)
97 97
 		break;
98 98
 
99 99
 	case T_STRUCT:
100
-	case T_UNION:
100
+	/* case T_UNION: */
101 101
 		type_dump_cdecl_sou(t, fp);
102 102
 		break;
103 103
 
@@ -124,45 +124,6 @@ void type_dump_cdecl(struct type *t, FILE *fp)
124 124
 /* 	} */
125 125
 /* } */
126 126
 
127
-/* struct type *type_map_of(struct type *ktype, struct type *vtype) */
128
-/* { */
129
-/* 	struct type *t; */
130
-/* 	size_t i; */
131
-
132
-/* 	for (i = 0; i < types.len; i++) { */
133
-/* 		t = types.type[i]; */
134
-/* 		if ((t->ttype == T_MAP) */
135
-/* 		    && (t->map.ktype == ktype) */
136
-/* 		    && (t->map.vtype == vtype)) */
137
-/* 			return t; */
138
-/* 	} */
139
-
140
-/* 	t = calloc(1, sizeof(*t)); */
141
-/* 	t->ttype = T_MAP; */
142
-/* 	t->map.vtype = vtype; */
143
-/* 	t->map.ktype = ktype; */
144
-/* 	type_add(t); */
145
-/* 	return t; */
146
-/* } */
147
-
148
-/* struct type *type_ptr_of(struct type *type) */
149
-/* { */
150
-/* 	struct type *t; */
151
-/* 	size_t i; */
152
-
153
-/* 	for (i = 0; i < types.len; i++) { */
154
-/* 		t = types.type[i]; */
155
-/* 		if ((t->ttype == T_POINTER) */
156
-/* 		    && (t->pointer.type == type)) */
157
-/* 			return t; */
158
-/* 	} */
159
-
160
-/* 	t = calloc(1, sizeof(*t)); */
161
-/* 	t->ttype = T_POINTER; */
162
-/* 	t->pointer.type = type; */
163
-/* 	type_add(t); */
164
-/* 	return t; */
165
-/* } */
166 127
 
167 128
 
168 129
 struct type *type_normalize(struct type *t)
@@ -199,7 +160,7 @@ int type_compatible(struct type *a, struct type *b)
199 160
 
200 161
 		return type_compatible(a->array.type, b->array.type);
201 162
 	case T_STRUCT:
202
-	case T_UNION:
163
+	/* case T_UNION: */
203 164
 		return !strcmp(a->sou.name, b->sou.name);
204 165
 	case T_FUNC:
205 166
 		return type_compatible(a->func.type, b->func.type);
@@ -214,85 +175,22 @@ int type_compatible(struct type *a, struct type *b)
214 175
 	return 0;
215 176
 }
216 177
 
217
-/* void type_size_set_sou(struct type *t) */
218
-/* { */
219
-/* 	struct tfield *f; */
220
-/* 	size_t size = 0; */
221
-
222
-/* 	if (!t->sou.fields) */
223
-/* 		return; */
224
-
225
-/* 	for (f = t->sou.fields; f->name; f++) { */
226
-/* 		/\* size of all members is now known yet, abort *\/ */
227
-/* 		if (!f->type->size) */
228
-/* 			return; */
229
-
230
-/* 		if (!t->sou.packed) */
231
-/* 			size += size % f->type->size; */
232
-
233
-/* 		size += f->type->size; */
234
-/* 		f->offset = size; */
235
-/* 	} */
236
-
237
-/* 	if (!t->sou.packed && size) { */
238
-/* 		/\* align complete struct to requirements of first */
239
-/* 		 * member, if struct keep going downwards *\/ */
240
-/* 		f = t->sou.fields; */
241
-/* 		while (f->type->ttype == T_STRUCT) */
242
-/* 			f = f->type->sou.fields; */
243
-
244
-/* 		size += size % f->type->size; */
245
-/* 	} */
246
-
247
-/* 	t->size = size; */
248
-/* } */
249
-
250
-/* void type_size_set(struct type *t) */
251
-/* { */
252
-/* 	switch (t->ttype) { */
253
-/* 	case T_TYPEDEF: */
254
-/* 		t->size = t->tdef.type->size; */
255
-/* 		break; */
256
-/* 	case T_STRUCT: */
257
-/* 	case T_UNION: */
258
-/* 		type_size_set_sou(t); */
259
-/* 		break; */
260
-/* 	case T_FUNC: */
261
-/* 		t->size = t->func.type->size; */
262
-/* 		assert(t->func.generate_ir); */
263
-/* 		break; */
264
-/* 	case T_SCALAR: */
265
-/* 		break; */
266
-/* 	case T_POINTER: */
267
-/* 		t->size = sizeof(void *); */
268
-/* 		break; */
269
-/* 	case T_ARRAY: */
270
-/* 		t->size = t->array.len * t->array.type->size; */
271
-/* 		break; */
272
-/* 	case T_MAP: */
273
-/* 		/\* map fds are s64:s *\/ */
274
-/* 		t->size = 8; */
275
-/* 		break; */
276
-/* 	} */
277
-/* } */
278
-
279
-static ssize_t type_alignof_union(struct type *t)
178
+static ssize_t type_alignof_struct(struct type *t)
280 179
 {
281
-	ssize_t amax = -EINVAL;
282 180
 	struct tfield *f;
181
+	ssize_t falign, align = -EINVAL;
283 182
 
284
-	for (f = t->sou.fields; f->type != T_VOID; f++) {
285
-		ssize_t a;
183
+	tfields_foreach(f, t->sou.fields) {
184
+		falign = type_alignof(f->type);
286 185
 
287
-		a = type_alignof(f->type);
288
-		if (a < 0)
289
-			return a;
186
+		if (falign < 0)
187
+			return falign;
290 188
 
291
-		if (a > amax)
292
-			amax = a;
189
+		if (falign > align)
190
+			align = falign;
293 191
 	}
294 192
 
295
-	return amax;
193
+	return align;
296 194
 }
297 195
 
298 196
 ssize_t type_alignof(struct type *t)
@@ -309,67 +207,59 @@ ssize_t type_alignof(struct type *t)
309 207
 	case T_ARRAY:
310 208
 		return type_alignof(t->array.type);
311 209
 	case T_STRUCT:
312
-		if (!t->sou.fields)
313
-			return type_alignof(&t_void);
314
-		return type_alignof(t->sou.fields->type);
315
-	case T_UNION:
316
-		if (!t->sou.fields)
317
-			return type_alignof(&t_void);
318
-		return type_alignof_union(t);
210
+		return type_alignof_struct(t);
319 211
 	}
320 212
 
321 213
 	return -EINVAL;
322 214
 }
323 215
 
324
-static ssize_t type_sizeof_struct(struct type *t)
216
+ssize_t type_offset_size_of(struct type *t, const char *field)
325 217
 {
326 218
 	struct tfield *f;
327
-	size_t size = 0;
328
-	ssize_t fsize;
219
+	size_t offset = 0;
220
+	ssize_t fsize, falign;
221
+
222
+	assert(t->ttype == T_STRUCT);
329 223
 
330 224
 	if (!t->sou.fields)
331
-		return 0;
225
+		return -ENOENT;
332 226
 
333
-	for (f = t->sou.fields; f->name; f++) {
334
-		/* size of all members is now known yet, abort */
227
+	tfields_foreach(f, t->sou.fields) {
335 228
 		fsize = type_sizeof(f->type);
336 229
 		if (fsize < 0)
337 230
 			return fsize;
338 231
 
339
-		size += fsize;
232
+		falign = type_alignof(f->type);
233
+		if (falign < 0)
234
+			return falign;
340 235
 
341
-		if (!t->sou.packed)
342
-			size += size % type_alignof(f->type);
343
-	}
236
+		if (!t->sou.packed && (falign > 1))
237
+			offset += falign - (offset % falign);
344 238
 
345
-	if (!t->sou.packed && size)
346
-		size += size % type_alignof(t);
239
+		if (field && !strcmp(f->name, field))
240
+			return offset;
347 241
 
348
-	return size;
349
-}
242
+		offset += fsize;
243
+	}
350 244
 
351
-static ssize_t type_sizeof_union(struct type *t)
352
-{
353
-	struct tfield *f;
354
-	ssize_t size = 0;
245
+	if (field)
246
+		return -ENOENT;
355 247
 
356
-	if (!t->sou.fields)
357
-		return 0;
248
+	if (!t->sou.packed && offset && (falign > 1))
249
+		offset += falign - (offset % falign);
358 250
 
359
-	for (f = t->sou.fields; f->name; f++) {
360
-		ssize_t z, a;
361
-
362
-		z = type_sizeof(f->type);
363
-		a = t->sou.packed ? type_alignof(f->type) : 0;
364
-		if ((z < 0) || (a < 0))
365
-			return -EINVAL;
251
+	return offset;
252
+	
253
+}
366 254
 
367
-		z += z % a;
368
-		if (z > size)
369
-			size = z;
370
-	}
255
+ssize_t type_offsetof(struct type *t, const char *field)
256
+{
257
+	return type_offset_size_of(t, field);
258
+}
371 259
 
372
-	return size;
260
+ssize_t type_sizeof_struct(struct type *t)
261
+{
262
+	return type_offset_size_of(t, NULL);
373 263
 }
374 264
 
375 265
 ssize_t type_sizeof(struct type *t)
@@ -388,8 +278,6 @@ ssize_t type_sizeof(struct type *t)
388 278
 		return t->array.len * type_sizeof(t->array.type);
389 279
 	case T_STRUCT:
390 280
 		return type_sizeof_struct(t);
391
-	case T_UNION:
392
-		return type_sizeof_union(t);
393 281
 	case T_MAP:
394 282
 		return sizeof(int);
395 283
 	}
@@ -397,66 +285,6 @@ ssize_t type_sizeof(struct type *t)
397 285
 	return -EINVAL;
398 286
 }
399 287
 
400
-/* int type_walk_fields(struct tfield *f, twalk_fn pre, twalk_fn post, void *ctx) */
401
-/* { */
402
-/* 	if (!f) */
403
-/* 		return 0; */
404
-
405
-/* 	while (f->type != T_VOID) { */
406
-/* 		if (pre && (err = pre(f->type, ctx))) */
407
-/* 			return err; */
408
-
409
-/* 		err = type_walk(f->type, pre, post, ctx); */
410
-/* 		if (err) */
411
-/* 			return err; */
412
-
413
-/* 		if (post && (err = post(f->type, ctx))) */
414
-/* 			return err; */
415
-/* 	} */
416
-/* } */
417
-
418
-/* int type_walk(struct type *t, twalk_fn pre, twalk_fn post, void *ctx) */
419
-/* { */
420
-/* 	int err; */
421
-
422
-/* 	if (pre && (err = pre(t, ctx))) */
423
-/* 		return err; */
424
-		
425
-/* 	switch (t->ttype){ */
426
-/* 	case T_VOID: */
427
-/* 	case T_SCALAR: */
428
-/* 		break; */
429
-/* 	case T_TYPEDEF: */
430
-/* 		err = type_walk(t->tdef.type, pre, post, ctx); */
431
-/* 		break; */
432
-/* 	case T_POINTER: */
433
-/* 		err = type_walk(t->ptr.type, pre, post, ctx); */
434
-/* 		break; */
435
-/* 	case T_ARRAY: */
436
-/* 		err = type_walk(t->array.type, pre, post, ctx); */
437
-/* 		break; */
438
-/* 	case T_STRUCT: */
439
-/* 	case T_UNION: */
440
-/* 		err = type_walk_fields(t->sou.fields, pre, post, ctx); */
441
-/* 		break; */
442
-/* 	case T_FUNC: */
443
-/* 		err = type_walk_fields(t->func.args, pre, post, ctx); */
444
-/* 		break; */
445
-/* 	case T_MAP: */
446
-/* 		err = type_walk(t->map.ktype, pre, post, ctx); */
447
-/* 		if (err) */
448
-/* 			break; */
449
-
450
-/* 		err = type_walk(t->map.vtype, pre, post, ctx); */
451
-/* 		break; */
452
-/* 	} */
453
-
454
-/* 	if (err) */
455
-/* 		return err; */
456
-	
457
-/* 	if (post && (err = post(t, ctx))) */
458
-/* 		return err; */
459
-/* } */
460 288
 
461 289
 
462 290
 int all_types_cmp(const void *_a, const void *_b)
@@ -472,6 +300,9 @@ struct type_list {
472 300
 	size_t len;
473 301
 } all_types;
474 302
 
303
+#define types_foreach(_t) \
304
+	for ((_t) = all_types.types[0]; (_t) <= all_types.types[all_types.len]; (_t)++)
305
+
475 306
 int type_add(struct type *t)
476 307
 {
477 308
 	if (bsearch(t, all_types.types, all_types.len,
@@ -501,6 +332,61 @@ int type_add_list(struct type **ts)
501 332
 	return 0;
502 333
 }
503 334
 
335
+struct type *type_array_of(struct type *type, size_t len)
336
+{
337
+	struct type *t;
338
+
339
+	types_foreach(t) {
340
+		if ((t->ttype == T_ARRAY)
341
+		    && (t->array.type == type)
342
+		    && (t->array.len == len))
343
+			return t;
344
+	}
345
+
346
+	t = calloc(1, sizeof(*t));
347
+	t->ttype = T_ARRAY;
348
+	t->array.type = type;
349
+	t->array.len = len;
350
+	type_add(t);
351
+	return t;
352
+}
353
+
354
+struct type *type_map_of(struct type *ktype, struct type *vtype)
355
+{
356
+	struct type *t;
357
+
358
+	types_foreach(t) {
359
+		if ((t->ttype == T_MAP)
360
+		    && (t->map.ktype == ktype)
361
+		    && (t->map.vtype == vtype))
362
+			return t;
363
+	}
364
+
365
+	t = calloc(1, sizeof(*t));
366
+	t->ttype = T_MAP;
367
+	t->map.vtype = vtype;
368
+	t->map.ktype = ktype;
369
+	type_add(t);
370
+	return t;
371
+}
372
+
373
+struct type *type_ptr_of(struct type *type)
374
+{
375
+	struct type *t;
376
+
377
+	types_foreach(t) {
378
+		if ((t->ttype == T_POINTER)
379
+		    && (t->ptr.type == type))
380
+			return t;
381
+	}
382
+
383
+	t = calloc(1, sizeof(*t));
384
+	t->ttype = T_POINTER;
385
+	t->ptr.type = type;
386
+	type_add(t);
387
+	return t;
388
+}
389
+
504 390
 #define is_signed(_t) (((_t)(-1)) < 0)
505 391
 
506 392
 #define builtin_scalar(_t) {				\

+ 9 - 7
type.h

@@ -38,6 +38,9 @@ struct tfield {
38 38
 	int optional:1;
39 39
 };
40 40
 
41
+#define tfields_foreach(_f, _fields) \
42
+	for ((_f) = (_fields); (_f)->type->ttype != T_VOID; (_f)++)
43
+
41 44
 struct tstruct {
42 45
 	char *name;
43 46
 
@@ -58,7 +61,7 @@ enum ttype {
58 61
 	T_ARRAY,
59 62
 	T_MAP,
60 63
 	T_STRUCT,
61
-	T_UNION,
64
+	/* T_UNION, TODO */
62 65
 	T_FUNC,
63 66
 };
64 67
 
@@ -75,9 +78,6 @@ struct type {
75 78
 	};
76 79
 };
77 80
 
78
-/* struct type *type_map_of(struct type *ktype, struct type *vtype); */
79
-/* struct type *type_ptr_of(struct type *type); */
80
-
81 81
 int type_equal     (struct type *a, struct type *b);
82 82
 int type_compatible(struct type *a, struct type *b);
83 83
 
@@ -85,15 +85,17 @@ void type_dump      (struct type *t, FILE *fp);
85 85
 void type_dump_cdecl(struct type *t, FILE *fp);
86 86
 
87 87
 ssize_t type_alignof(struct type *t);
88
+ssize_t type_offsetof(struct type *t, const char *field);
88 89
 ssize_t type_sizeof(struct type *t);
89 90
 
90
-/* typedef int (*twalk_fn)(struct type *, void *); */
91
-/* int type_walk(struct type *t, twalk_fn pre, twalk_fn post, void *ctx); */
92
-
93 91
 
94 92
 int type_add(struct type *t);
95 93
 int type_add_list(struct type **ts);
96 94
 
95
+struct type *type_array_of(struct type *type, size_t len);
96
+struct type *type_map_of(struct type *ktype, struct type *vtype);
97
+struct type *type_ptr_of(struct type *type);
98
+
97 99
 
98 100
 /* built-in types */
99 101
 

+ 81 - 12
type_test.c

@@ -1,23 +1,92 @@
1
-#include <assert.h>
2
-
3 1
 #include "type.h"
2
+#include "unittest.h"
3
+
4
+static int sizeof_basic(void *_null)
5
+{
6
+	struct type *voidp, *map;
7
+
8
+	unittest_eq(type_sizeof(&t_void),  sizeof(void));
9
+	unittest_eq(type_sizeof(&t_char),  sizeof(char));
10
+	unittest_eq(type_sizeof(&t_short), sizeof(short));
11
+	unittest_eq(type_sizeof(&t_int),   sizeof(int));
12
+	unittest_eq(type_sizeof(&t_long),  sizeof(long));
13
+	unittest_eq(type_sizeof(&t_llong), sizeof(long long));
14
+
15
+	voidp = type_ptr_of(&t_void);
16
+	unittest_eq(type_sizeof(voidp), sizeof(void *));
17
+
18
+	map = type_map_of(&t_short, &t_short);
19
+	unittest_eq(type_sizeof(map), sizeof(int));
20
+	
21
+	return 0;
22
+}
23
+UNITTEST(sizeof_basic);
24
+
25
+static int alignof_basic(void *_null)
26
+{
27
+	struct type *voidp, *map, *array;
28
+
29
+	unittest_eq(type_alignof(&t_void),  __alignof__(void));
30
+	unittest_eq(type_alignof(&t_char),  __alignof__(char));
31
+	unittest_eq(type_alignof(&t_short), __alignof__(short));
32
+	unittest_eq(type_alignof(&t_int),   __alignof__(int));
33
+	unittest_eq(type_alignof(&t_long),  __alignof__(long));
34
+	unittest_eq(type_alignof(&t_llong), __alignof__(long long));
4 35
 
5
-typedef void (*unittest_fn)(void)
6
-#define unittest __attribute__((section("unittest"))) static void
36
+	voidp = type_ptr_of(&t_void);
37
+	unittest_eq(type_alignof(voidp), __alignof__(void *));
7 38
 
8
-unittest test_sizeof_builtins(void)
39
+	map = type_map_of(&t_short, &t_short);
40
+	unittest_eq(type_alignof(map), __alignof__(int));
41
+
42
+	array = type_array_of(&t_int, 5);
43
+	unittest_eq(type_alignof(array), __alignof__(int[5]));
44
+
45
+	return 0;
46
+}
47
+UNITTEST(alignof_basic);
48
+
49
+struct t1 {
50
+	char  a;
51
+	int   b[5];
52
+	char  c[3];
53
+	short d;
54
+} *t1 = NULL;
55
+
56
+static int struct_basic(void *_null)
9 57
 {
10
-	assert(type_sizeof(&t_void) == sizeof(int));
58
+	struct tfield t1_fields[] = {
59
+		{ .name = "a", .type = &t_char },
60
+		{ .name = "b", .type = type_array_of(&t_int, 5) },
61
+		{ .name = "c", .type = type_array_of(&t_char, 3) },
62
+		{ .name = "d", .type = &t_short },
63
+
64
+		{ .type = &t_void }
65
+	};
66
+	struct type t_t1 = {
67
+		.ttype = T_STRUCT,
68
+		.sou = { .name = "t1", .fields = t1_fields },
69
+	};
70
+
71
+	unittest_eq(type_offsetof(&t_t1, "a"), offsetof(struct t1, a));
72
+	unittest_eq(type_offsetof(&t_t1, "b"), offsetof(struct t1, b));
73
+	unittest_eq(type_offsetof(&t_t1, "c"), offsetof(struct t1, c));
74
+	unittest_eq(type_offsetof(&t_t1, "d"), offsetof(struct t1, d));
75
+
76
+	unittest_eq(type_alignof(&t_t1), __alignof__(struct t1));
77
+	unittest_eq(type_sizeof(&t_t1), sizeof(struct t1));
78
+	return 0;
11 79
 }
80
+UNITTEST(struct_basic);
12 81
 
13 82
 int main(void)
14 83
 {
15
-	unittest_fn test_fn;
16
-	int err;
84
+	struct unittest_ctx ctx = {
85
+		.keep_going = 1,
86
+		.verbose = 1,
17 87
 
18
-	for (test_fn = &__start_unittest; test_fn < &__stop_unittest; testfn++) {
19
-		test_fn();
20
-	}
88
+		.ctx = NULL,
89
+	};
21 90
 
22
-	return 0;
91
+	return unittests_run(&ctx) ? 1 : 0;
23 92
 }

+ 71 - 0
unittest.h

@@ -0,0 +1,71 @@
1
+#ifndef _UNITTEST_H
2
+#define _UNITTEST_H
3
+
4
+#include <stdio.h>
5
+
6
+struct unittest {
7
+	const char *name;
8
+	int (*fn)(void *ctx);
9
+};
10
+
11
+#define UNITTEST(_fn) __attribute__((section("unittests"))) \
12
+	static struct unittest _fn ## _desc = {		    \
13
+		.name = #_fn,				    \
14
+		.fn = _fn,				    \
15
+	}
16
+
17
+extern struct unittest __start_unittests;
18
+extern struct unittest __stop_unittests;
19
+
20
+#define unittest_foreach(_t) \
21
+	for ((_t) = &__start_unittests; (_t) < &__stop_unittests; (_t)++)
22
+
23
+struct unittest_ctx {
24
+	int keep_going:1;
25
+	int verbose:1;
26
+
27
+	void *ctx;
28
+};
29
+
30
+static inline int unittests_run(struct unittest_ctx *ctx)
31
+{
32
+	struct unittest *t;
33
+	int err, ret = 0;
34
+
35
+	unittest_foreach(t) {
36
+		if (ctx->verbose) {
37
+			printf("%-40s\t", t->name);
38
+			fflush(stdout);
39
+		}
40
+
41
+		err = t->fn(ctx->ctx);
42
+
43
+		if (!err) {
44
+			if (ctx->verbose)
45
+				printf("pass\n");
46
+			continue;
47
+		} 
48
+
49
+		if (!ctx->verbose) {
50
+			printf("%-40s\t", t->name);
51
+			fflush(stdout);
52
+		}
53
+
54
+		printf("\n%40s\tFAIL\n", "");
55
+
56
+		if (!ctx->keep_going)
57
+			return err;
58
+		else if (!ret)
59
+			ret = err;
60
+	}
61
+
62
+	return ret;
63
+}
64
+
65
+#define unittest_eq(_a, _b) if ((_a) != (_b)) {				\
66
+		printf("\n\t%s == %s (%lld != %lld)",			\
67
+		       #_a, #_b, (long long)(_a), (long long)(_b));	\
68
+		return -1;						\
69
+	}
70
+
71
+#endif	/* _UNITTEST_H */