|
|
1.1 root 1: //
2: // nono
1.1.1.4 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
1.1.1.15! root 7: //
! 8: // 基本ヘッダ
! 9: //
! 10:
1.1 root 11: #pragma once
12:
13: #define NONO_MAJOR_VER (0)
1.1.1.15! root 14: #define NONO_MINOR_VER (3)
! 15: #define NONO_PATCH_VER (0)
! 16: #define NONO_DATE "2022/04/30"
1.1 root 17:
1.1.1.3 root 18: #include "config-nono.h"
1.1 root 19: #include <cassert>
20: #include <cctype>
21: #include <cerrno>
22: #include <cstdarg>
23: #include <cstdio>
24: #include <cstdint>
25: #include <cstdlib>
26: #include <cstring>
1.1.1.3 root 27: #include <memory>
1.1 root 28: #include <string>
29:
30: #include <err.h>
31: #include <inttypes.h>
32: #include <unistd.h>
33: #include <sys/cdefs.h>
34: #include <sys/types.h>
35:
1.1.1.4 root 36: using uint8 = uint8_t;
37: using uint16 = uint16_t;
38: using uint32 = uint32_t;
39: using uint64 = uint64_t;
40: using int8 = int8_t;
41: using int16 = int16_t;
42: using int32 = int32_t;
43: using int64 = int64_t;
1.1 root 44:
45: #if defined(HAVE_BSD_BSD_H)
46: #include <bsd/bsd.h>
47: #endif
48:
1.1.1.15! root 49: #include "myendian.h"
! 50:
1.1 root 51: #if !defined(__printflike)
52: #if defined(HAVE___ATTRIBUTE_FORMAT)
53: # define __printflike(a,b) __attribute__((__format__(__printf__, (a), (b))))
54: #else
55: # define __printflike(a,b)
56: #endif
57: #endif
58:
59: #if !defined(__unreachable)
60: #if defined(HAVE___BUILTIN_UNREACHABLE)
61: # define __unreachable() __builtin_unreachable()
62: #else
63: # define __unreachable() ((void)0)
64: #endif
65: #endif
66:
67: // gcc でコンパイラに最適化の条件を与える。
68: #if defined(HAVE___BUILTIN_ASSUME)
69: #define __assume(cond) __builtin_assume(cond)
70: #else
71: #define __assume(cond) if (!(cond)) __unreachable()
72: #endif
73:
74: #if !defined(__packed)
75: #if defined(HAVE___ATTRIBUTE_PACKED)
76: # define __packed __attribute__((__packed__))
77: #else
78: # error not tested.
79: #endif
80: #endif
81:
82: #if !defined(__predict_true)
83: #if defined(HAVE___BUILTIN_EXPECT)
84: # define __predict_true(exp) __builtin_expect((exp) != 0, 1)
85: # define __predict_false(exp) __builtin_expect((exp) != 0, 0)
86: #else
87: # define __predict_true(exp) (exp)
88: # define __predict_false(exp) (exp)
89: #endif
90: #endif
91:
92: #if !defined(__unused)
93: #if defined(HAVE___ATTRIBUTE_UNUSED)
94: # define __unused __attribute__((__unused__))
95: #else
96: # define __unused
97: #endif
98: #endif
99:
1.1.1.4 root 100: #if defined(__clang__)
101: # define FALLTHROUGH [[clang::fallthrough]]
102: #elif defined(HAVE___ATTRIBUTE_FALLTHROUGH)
1.1 root 103: # define FALLTHROUGH __attribute__((__fallthrough__))
104: #else
105: # define FALLTHROUGH ((void)0)
106: #endif
107:
108: #if defined(HAVE___ATTRIBUTE_NO_SANITIZE)
109: # define NO_SANITIZE(x) __attribute__((no_sanitize(x)))
110: #else
111: # define NO_SANITIZE(x)
112: #endif
113:
1.1.1.5 root 114: // x86_64 では SSE のために16バイト境界に整列させたいが、ほかの
115: // アーキテクチャでは alignas(16) がエラーになる場合がある。この場合の
116: // alignas() は SSE のために必要なので、他アーキテクチャではそもそも
117: // 指定しなくていい。ということで x86_64 の時に限って指定したい時に使う。
118: // うーん、なんだこれ。
119: #if defined(__x86_64__)
120: #define ALIGNAS_IF_X86(n) alignas(n)
121: #else
122: #define ALIGNAS_IF_X86(n) /**/
123: #endif
124:
1.1.1.3 root 125: // 64ビット数と2つの32ビット数を扱う共用体。
126: // 構造はまったく同じだが名前だけ場所に合わせてつけたい。
1.1.1.15! root 127: #if BYTE_ORDER == LITTLE_ENDIAN
1.1.1.3 root 128: #define DEF_UNION64(NAME, Q, H, L) \
129: union NAME { \
130: uint64 Q; \
131: struct { uint32 L, H; }; \
132: }
133: #else
134: #define DEF_UNION64(NAME, Q, H, L) \
135: union NAME { \
136: uint64 Q; \
137: struct { uint32 H, L; }; \
138: }
139: #endif
140:
141: DEF_UNION64(union64, q, h, l);
142:
1.1 root 143: #ifndef countof
144: #define countof(x) (sizeof(x) / sizeof(x[0]))
145: #endif
146:
1.1.1.5 root 147: #ifndef roundup
148: #define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
149: #endif
150:
1.1.1.15! root 151: #ifndef rounddown
! 152: #define rounddown(x, y) (((x)/(y))*(y))
! 153: #endif
! 154:
1.1.1.3 root 155: // メッセージ付きの assert。
1.1.1.5 root 156: // 本当は後ろに足したいのだがそれは無理なので、せめてそれっぽく1行にしてみる。
1.1.1.15! root 157: #if !defined(NDEBUG)
1.1.1.5 root 158: #define assertmsg(expr, ...) do { \
1.1.1.3 root 159: if (__predict_false(!(expr))) { \
1.1.1.5 root 160: fprintf(stderr, __VA_ARGS__); \
161: fprintf(stderr, ": "); \
1.1.1.3 root 162: assert(expr); \
163: } \
164: } while (0)
1.1.1.15! root 165: #else
! 166: #define assertmsg(expr, ...)
! 167: #endif
1.1.1.3 root 168:
1.1 root 169: // atomic_compare_exchange_strong() の短縮マクロ。
170: // ライブラリ実装は第2引数の expected が値ではなくポインタなので一旦代入操作を
171: // 行わないといけないのと、第3引数の newval は型が uint8 だと int 即値が書けず
172: // (int8) でキャストしないといけない。
173: // その上 atomic_compare_exchange_strong() が長い、と、いろいろ微妙なので、
174: // その辺を短くするマクロを用意する。ただしこれでは expected 変数の型が
175: // 自動判別できないので、_8 と _32 を用意するところは妥協。
176: // (static) inline 関数にすることも出来るけどそうするとここで <atomic> ヘッダ
177: // を読み込まなければならなくなるため、マクロで実現する。
178: #define atomic_cas_8(varp, expval, newval) ({ \
179: uint8 expected = (expval); \
180: atomic_compare_exchange_strong((varp), &expected, (uint8)(newval)); \
181: })
182: #define atomic_cas_32(varp, expval, newval) ({ \
183: uint32 expected = (expval); \
184: atomic_compare_exchange_strong((varp), &expected, (uint32)(newval)); \
185: })
186:
1.1.1.15! root 187: // パニック (PC を表示しない)
1.1 root 188: #define PANIC(...) panic(__PRETTY_FUNCTION__, __VA_ARGS__)
189: [[noreturn]] extern void panic(const char *funcname, const char *fmt, ...)
190: __printflike(2, 3);
1.1.1.15! root 191:
! 192: // VM 用パニック (PC を表示する)
! 193: #define VMPANIC(...) vmpanic(__PRETTY_FUNCTION__, __VA_ARGS__)
! 194: [[noreturn]] extern void vmpanic(const char *funcname, const char *fmt, ...)
! 195: __printflike(2, 3);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.