+/**
+ * create a builtin function.
+ */
+static entity_t *create_builtin_function(builtin_kind_t kind, const char *name, type_t *function_type)
+{
+ symbol_t *symbol = symbol_table_insert(name);
+ entity_t *entity = allocate_entity_zero(ENTITY_FUNCTION);
+ entity->declaration.storage_class = STORAGE_CLASS_EXTERN;
+ entity->declaration.declared_storage_class = STORAGE_CLASS_EXTERN;
+ entity->declaration.type = function_type;
+ entity->declaration.implicit = true;
+ entity->base.symbol = symbol;
+ entity->base.source_position = builtin_source_position;
+
+ entity->function.btk = kind;
+
+ record_entity(entity, /*is_definition=*/false);
+ return entity;
+}
+
+
+/**
+ * Create predefined gnu builtins.
+ */
+static void create_gnu_builtins(void)
+{
+#define GNU_BUILTIN(a, b) create_builtin_function(bk_gnu_builtin_##a, "__builtin_" #a, b)
+
+ GNU_BUILTIN(alloca, make_function_1_type(type_void_ptr, type_size_t));
+ GNU_BUILTIN(huge_val, make_function_0_type(type_double));
+ GNU_BUILTIN(inf, make_function_0_type(type_double));
+ GNU_BUILTIN(inff, make_function_0_type(type_float));
+ GNU_BUILTIN(infl, make_function_0_type(type_long_double));
+ GNU_BUILTIN(nan, make_function_1_type(type_double, type_char_ptr));
+ GNU_BUILTIN(nanf, make_function_1_type(type_float, type_char_ptr));
+ GNU_BUILTIN(nanl, make_function_1_type(type_long_double, type_char_ptr));
+ GNU_BUILTIN(va_end, make_function_1_type(type_void, type_valist));
+ GNU_BUILTIN(expect, make_function_2_type(type_long, type_long, type_long));
+ GNU_BUILTIN(return_address, make_function_1_type(type_void_ptr, type_unsigned_int));
+ GNU_BUILTIN(frame_address, make_function_1_type(type_void_ptr, type_unsigned_int));
+ GNU_BUILTIN(ffs, make_function_1_type(type_int, type_unsigned_int));
+ GNU_BUILTIN(clz, make_function_1_type(type_int, type_unsigned_int));
+ GNU_BUILTIN(ctz, make_function_1_type(type_int, type_unsigned_int));
+ GNU_BUILTIN(popcount, make_function_1_type(type_int, type_unsigned_int));
+ GNU_BUILTIN(parity, make_function_1_type(type_int, type_unsigned_int));
+ GNU_BUILTIN(prefetch, make_function_1_type_variadic(type_float, type_void_ptr));
+ GNU_BUILTIN(trap, make_function_0_type_noreturn(type_void));
+
+#undef GNU_BUILTIN
+}
+
+/**
+ * Create predefined MS intrinsics.
+ */
+static void create_microsoft_intrinsics(void)
+{
+#define MS_BUILTIN(a, b) create_builtin_function(bk_ms##a, #a, b)
+
+ /* intrinsics for all architectures */
+ MS_BUILTIN(_rotl, make_function_2_type(type_unsigned_int, type_unsigned_int, type_int));
+ MS_BUILTIN(_rotr, make_function_2_type(type_unsigned_int, type_unsigned_int, type_int));
+ MS_BUILTIN(_rotl64, make_function_2_type(type_unsigned_int64, type_unsigned_int64, type_int));
+ MS_BUILTIN(_rotr64, make_function_2_type(type_unsigned_int64, type_unsigned_int64, type_int));
+ MS_BUILTIN(_byteswap_ushort, make_function_1_type(type_unsigned_short, type_unsigned_short));
+ MS_BUILTIN(_byteswap_ulong, make_function_1_type(type_unsigned_long, type_unsigned_long));
+ MS_BUILTIN(_byteswap_uint64, make_function_1_type(type_unsigned_int64, type_unsigned_int64));
+
+ MS_BUILTIN(__debugbreak, make_function_0_type(type_void));
+ MS_BUILTIN(_ReturnAddress, make_function_0_type(type_void_ptr));
+ MS_BUILTIN(_AddressOfReturnAddress, make_function_0_type(type_void_ptr));
+ MS_BUILTIN(__popcount, make_function_1_type(type_unsigned_int, type_unsigned_int));
+
+ /* x86/x64 only */
+ MS_BUILTIN(_enable, make_function_0_type(type_void));
+ MS_BUILTIN(_disable, make_function_0_type(type_void));
+ MS_BUILTIN(__inbyte, make_function_1_type(type_unsigned_char, type_unsigned_short));
+ MS_BUILTIN(__inword, make_function_1_type(type_unsigned_short, type_unsigned_short));
+ MS_BUILTIN(__indword, make_function_1_type(type_unsigned_long, type_unsigned_short));
+ MS_BUILTIN(__outbyte, make_function_2_type(type_void, type_unsigned_short, type_unsigned_char));
+ MS_BUILTIN(__outword, make_function_2_type(type_void, type_unsigned_short, type_unsigned_short));
+ MS_BUILTIN(__outdword, make_function_2_type(type_void, type_unsigned_short, type_unsigned_long));
+ MS_BUILTIN(__ud2, make_function_0_type_noreturn(type_void));
+ MS_BUILTIN(_BitScanForward, make_function_2_type(type_unsigned_char, type_unsigned_long_ptr, type_unsigned_long));
+ MS_BUILTIN(_BitScanReverse, make_function_2_type(type_unsigned_char, type_unsigned_long_ptr, type_unsigned_long));
+ MS_BUILTIN(_InterlockedExchange, make_function_2_type(type_long, type_long_ptr, type_long));
+ MS_BUILTIN(_InterlockedExchange64, make_function_2_type(type_int64, type_int64_ptr, type_int64));
+
+ if (machine_size <= 32) {
+ MS_BUILTIN(__readeflags, make_function_0_type(type_unsigned_int));
+ MS_BUILTIN(__writeeflags, make_function_1_type(type_void, type_unsigned_int));
+ } else {
+ MS_BUILTIN(__readeflags, make_function_0_type(type_unsigned_int64));
+ MS_BUILTIN(__writeeflags, make_function_1_type(type_void, type_unsigned_int64));
+ }
+
+#undef MS_BUILTIN
+}
+