feat: multi-user system, bug fixes, security & performance fixes, and more
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
# Makefile for standalone MontaukOS app (template)
|
||||
# Usage:
|
||||
# make Build the app
|
||||
# make clean Remove build artifacts
|
||||
# make install Copy ELF to MontaukOS ramdisk bin directory
|
||||
#
|
||||
# Copy this entire directory, rename it, and edit APP_NAME/SRCS below.
|
||||
|
||||
MAKEFLAGS += -rR
|
||||
.SUFFIXES:
|
||||
|
||||
# ---- App configuration ----
|
||||
# Change these for your app:
|
||||
|
||||
APP_NAME := myapp
|
||||
SRCS := src/main.cpp src/stb_truetype_impl.cpp src/cxxrt.cpp
|
||||
|
||||
# Optional features — set to 1 to enable:
|
||||
# USE_TLS=1 HTTPS/TLS support (libtls + libbearssl)
|
||||
# USE_JPEG=1 JPEG image decoding (libjpeg / stb_image)
|
||||
USE_TLS ?= 0
|
||||
USE_JPEG ?= 0
|
||||
|
||||
# ---- Toolchain ----
|
||||
# Looks for the cross-compiler via MONTAUKOS, then falls back to system g++.
|
||||
|
||||
MONTAUKOS ?= $(HOME)/dev/MontaukOS
|
||||
TOOLCHAIN := $(MONTAUKOS)/toolchain/local/bin/x86_64-elf-
|
||||
ifneq ($(wildcard $(TOOLCHAIN)gcc),)
|
||||
CXX := $(TOOLCHAIN)g++
|
||||
else
|
||||
CXX := g++
|
||||
endif
|
||||
|
||||
# ---- Paths ----
|
||||
|
||||
SYSROOT := sysroot
|
||||
OBJDIR := obj
|
||||
BINDIR := bin
|
||||
LINK_LD := link.ld
|
||||
|
||||
# ---- Compiler flags ----
|
||||
|
||||
CXXFLAGS := \
|
||||
-std=gnu++20 \
|
||||
-g -O2 -pipe \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-Wno-unused-parameter \
|
||||
-Wno-unused-function \
|
||||
-nostdinc \
|
||||
-ffreestanding \
|
||||
-fno-stack-protector \
|
||||
-fno-stack-check \
|
||||
-fno-PIC \
|
||||
-fno-rtti \
|
||||
-fno-exceptions \
|
||||
-ffunction-sections \
|
||||
-fdata-sections \
|
||||
-m64 \
|
||||
-march=x86-64 \
|
||||
-msse \
|
||||
-msse2 \
|
||||
-mno-red-zone \
|
||||
-mcmodel=small \
|
||||
-I $(SYSROOT)/include \
|
||||
-I src \
|
||||
-isystem $(SYSROOT)/include/libc
|
||||
|
||||
# ---- Linker flags ----
|
||||
|
||||
LDFLAGS := \
|
||||
-nostdlib \
|
||||
-static \
|
||||
-Wl,--build-id=none \
|
||||
-Wl,--gc-sections \
|
||||
-Wl,-m,elf_x86_64 \
|
||||
-z max-page-size=0x1000 \
|
||||
-T $(LINK_LD)
|
||||
|
||||
# ---- Libraries ----
|
||||
# Order matters: libtls depends on libbearssl, everything depends on liblibc.
|
||||
|
||||
LIBS :=
|
||||
ifeq ($(USE_TLS),1)
|
||||
LIBS += $(SYSROOT)/lib/libtls.a $(SYSROOT)/lib/libbearssl.a
|
||||
endif
|
||||
ifeq ($(USE_JPEG),1)
|
||||
LIBS += $(SYSROOT)/lib/libjpeg.a
|
||||
endif
|
||||
LIBS += $(SYSROOT)/lib/liblibc.a
|
||||
|
||||
# ---- Build rules ----
|
||||
|
||||
OBJS := $(addprefix $(OBJDIR)/,$(SRCS:.cpp=.o))
|
||||
TARGET := $(BINDIR)/$(APP_NAME).elf
|
||||
|
||||
.PHONY: all clean install
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile
|
||||
@mkdir -p $(BINDIR)
|
||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
|
||||
@echo "Built: $@"
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp Makefile
|
||||
@mkdir -p $(dir $@)
|
||||
$(CXX) $(CXXFLAGS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJDIR) $(BINDIR)
|
||||
|
||||
# Copy the built ELF into the MontaukOS ramdisk tree for testing.
|
||||
install: $(TARGET)
|
||||
@mkdir -p $(MONTAUKOS)/programs/bin/apps/$(APP_NAME)
|
||||
cp $(TARGET) $(MONTAUKOS)/programs/bin/apps/$(APP_NAME)/$(APP_NAME).elf
|
||||
@echo "Installed to $(MONTAUKOS)/programs/bin/apps/$(APP_NAME)/"
|
||||
@@ -0,0 +1,69 @@
|
||||
# MontaukOS App Template
|
||||
|
||||
Self-contained development environment for building standalone MontaukOS GUI apps. Copy this entire directory anywhere and start building.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
cp -r template/ ~/dev/myapp/
|
||||
cd ~/dev/myapp/
|
||||
# Edit APP_NAME and SRCS in Makefile
|
||||
make
|
||||
make install # copy ELF to MontaukOS ramdisk
|
||||
```
|
||||
|
||||
## Build Commands
|
||||
|
||||
```bash
|
||||
make # GUI-only app
|
||||
make USE_TLS=1 # With HTTPS/TLS (libtls + libbearssl)
|
||||
make USE_JPEG=1 # With JPEG decoding (libjpeg)
|
||||
make USE_TLS=1 USE_JPEG=1 # Both
|
||||
make clean # Remove build artifacts
|
||||
make install # Copy ELF to MontaukOS ramdisk
|
||||
```
|
||||
|
||||
If the MontaukOS tree is not at `~/dev/MontaukOS/`, pass the path to the cross-compiler:
|
||||
|
||||
```bash
|
||||
make MONTAUKOS=/path/to/MontaukOS
|
||||
```
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
myapp/
|
||||
├── Makefile Edit APP_NAME and SRCS here
|
||||
├── link.ld Linker script (load at 0x400000)
|
||||
├── src/
|
||||
│ ├── main.cpp Your app (template with window, rendering, input)
|
||||
│ ├── stb_truetype_impl.cpp TrueType font support (keep this)
|
||||
│ └── cxxrt.cpp C++ new/delete runtime (keep this)
|
||||
├── sysroot/
|
||||
│ ├── include/
|
||||
│ │ ├── montauk/ syscall.h, heap.h, string.h, config.h, toml.h, user.h
|
||||
│ │ ├── gui/ gui.hpp, canvas.hpp, truetype.hpp, widgets.hpp, svg.hpp, ...
|
||||
│ │ ├── http/ http.hpp (HTTP GET/POST/etc. wrapper)
|
||||
│ │ ├── tls/ tls.hpp (HTTPS/TLS, for USE_TLS=1)
|
||||
│ │ ├── Api/ Syscall.hpp (low-level syscall numbers)
|
||||
│ │ ├── libc/ stdio.h, stdlib.h, string.h, ...
|
||||
│ │ ├── bearssl*.h BearSSL headers (for USE_TLS=1)
|
||||
│ │ └── (freestanding C/C++ standard headers)
|
||||
│ └── lib/
|
||||
│ ├── liblibc.a C library (always linked)
|
||||
│ ├── libtls.a TLS helper library
|
||||
│ ├── libbearssl.a BearSSL crypto
|
||||
│ └── libjpeg.a JPEG decoding (stb_image)
|
||||
└── docs/
|
||||
├── gui-apps.md GUI programming guide
|
||||
└── syscalls.md Syscall and API reference
|
||||
```
|
||||
|
||||
## Key Points
|
||||
|
||||
- Entry point: `extern "C" void _start()` (not `main`)
|
||||
- Memory: `montauk::malloc()` / `montauk::mfree()` (no standard libc)
|
||||
- Window: `win_create()` / `win_poll()` / `win_present()` / `win_destroy()`
|
||||
- Fonts: `TrueTypeFont::init("0:/fonts/Roboto-Medium.ttf")`
|
||||
- HTTP: `#include <http/http.hpp>` with `USE_TLS=1` (see docs/)
|
||||
- No exceptions, no RTTI, 32 KiB user stack
|
||||
@@ -0,0 +1,916 @@
|
||||
# Writing GUI Applications for MontaukOS
|
||||
|
||||
This guide covers how to build graphical applications for MontaukOS, from standalone Window Server clients to desktop-integrated apps.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [App Types](#app-types)
|
||||
- [Standalone Window Server Apps](#standalone-window-server-apps)
|
||||
- [Desktop-Integrated Apps](#desktop-integrated-apps)
|
||||
- [Drawing and Rendering](#drawing-and-rendering)
|
||||
- [Text and Fonts](#text-and-fonts)
|
||||
- [Input Handling](#input-handling)
|
||||
- [Widgets](#widgets)
|
||||
- [Colors and Theming](#colors-and-theming)
|
||||
- [Memory Management](#memory-management)
|
||||
- [Networking and HTTPS](#networking-and-https)
|
||||
- [App Manifests](#app-manifests)
|
||||
- [Build System](#build-system)
|
||||
|
||||
---
|
||||
|
||||
## App Types
|
||||
|
||||
MontaukOS supports two kinds of GUI applications:
|
||||
|
||||
| | Standalone Apps | Desktop Apps |
|
||||
|---|---|---|
|
||||
| **Location** | `programs/src/<appname>/` | `programs/src/desktop/apps/` |
|
||||
| **Window** | Own process, shared-memory pixel buffer | Embedded in desktop compositor |
|
||||
| **Event loop** | `win_poll()` syscall | Callback-driven (`on_draw`, `on_mouse`, `on_key`) |
|
||||
| **Drawing** | Direct pixel buffer writes | `Canvas` abstraction |
|
||||
| **Examples** | Spreadsheet, Music, Wikipedia | Calculator, File Manager, Terminal |
|
||||
|
||||
**Choose standalone** when you need a separate process (e.g., networking, heavy computation, isolation). **Choose desktop-integrated** for lightweight tools that benefit from tight compositor integration.
|
||||
|
||||
---
|
||||
|
||||
## Standalone Window Server Apps
|
||||
|
||||
Standalone apps are separate ELF binaries that communicate with the Window Server through syscalls. They get a shared-memory pixel buffer and manage their own event loop.
|
||||
|
||||
### Minimal Example
|
||||
|
||||
```cpp
|
||||
#include <montauk/syscall.h>
|
||||
#include <montauk/heap.h>
|
||||
#include <montauk/string.h>
|
||||
#include <gui/gui.hpp>
|
||||
#include <gui/truetype.hpp>
|
||||
|
||||
static TrueTypeFont* g_font;
|
||||
static int g_win_w, g_win_h;
|
||||
|
||||
static void render(uint32_t* pixels) {
|
||||
// Clear background
|
||||
for (int i = 0; i < g_win_w * g_win_h; i++)
|
||||
pixels[i] = Color::from_rgb(0xFF, 0xFF, 0xFF).to_pixel();
|
||||
|
||||
// Draw text
|
||||
if (g_font)
|
||||
g_font->draw_to_buffer(pixels, g_win_w, g_win_h,
|
||||
20, 30, "Hello, MontaukOS!",
|
||||
Color::from_rgb(0x33, 0x33, 0x33), 18);
|
||||
}
|
||||
|
||||
extern "C" void _start() {
|
||||
// Load font
|
||||
g_font = new TrueTypeFont();
|
||||
g_font->init("0:/fonts/Roboto-Medium.ttf");
|
||||
|
||||
// Create window
|
||||
g_win_w = 400;
|
||||
g_win_h = 300;
|
||||
Montauk::WinCreateResult wres;
|
||||
montauk::win_create("My App", g_win_w, g_win_h, &wres);
|
||||
int win_id = wres.id;
|
||||
uint32_t* pixels = (uint32_t*)(uintptr_t)wres.pixelVa;
|
||||
|
||||
// Initial render
|
||||
render(pixels);
|
||||
montauk::win_present(win_id);
|
||||
|
||||
// Event loop
|
||||
while (true) {
|
||||
Montauk::WinEvent ev;
|
||||
int r = montauk::win_poll(win_id, &ev);
|
||||
|
||||
if (r < 0) break; // Window destroyed externally
|
||||
if (r == 0) {
|
||||
montauk::sleep_ms(16); // ~60 FPS idle
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ev.type == 3) break; // Close event
|
||||
|
||||
if (ev.type == 2) { // Resize
|
||||
g_win_w = ev.resize.w;
|
||||
g_win_h = ev.resize.h;
|
||||
pixels = (uint32_t*)(uintptr_t)montauk::win_resize(win_id, g_win_w, g_win_h);
|
||||
}
|
||||
|
||||
if (ev.type == 0) { // Keyboard
|
||||
// ev.key.ascii, ev.key.scancode, ev.key.pressed
|
||||
}
|
||||
|
||||
if (ev.type == 1) { // Mouse
|
||||
// ev.mouse.x, ev.mouse.y, ev.mouse.buttons
|
||||
}
|
||||
|
||||
render(pixels);
|
||||
montauk::win_present(win_id);
|
||||
}
|
||||
|
||||
montauk::win_destroy(win_id);
|
||||
montauk::exit(0);
|
||||
}
|
||||
```
|
||||
|
||||
### Window Lifecycle
|
||||
|
||||
```
|
||||
win_create() Create window, get pixel buffer pointer
|
||||
|
|
||||
v
|
||||
win_present() Push current pixel buffer to screen
|
||||
|
|
||||
v
|
||||
win_poll() Receive events (returns 0 if none, <0 if closed)
|
||||
|
|
||||
v
|
||||
win_resize() Handle resize, get new pixel buffer pointer
|
||||
|
|
||||
v
|
||||
win_destroy() Clean up window
|
||||
```
|
||||
|
||||
### Event Types
|
||||
|
||||
Events are delivered via `win_poll()` into a `WinEvent` struct:
|
||||
|
||||
| `ev.type` | Event | Fields |
|
||||
|---|---|---|
|
||||
| 0 | Keyboard | `ev.key.scancode`, `ev.key.ascii`, `ev.key.pressed`, `ev.key.shift`, `ev.key.ctrl`, `ev.key.alt` |
|
||||
| 1 | Mouse | `ev.mouse.x`, `ev.mouse.y`, `ev.mouse.buttons`, `ev.mouse.prev_buttons`, `ev.mouse.scroll` |
|
||||
| 2 | Resize | `ev.resize.w`, `ev.resize.h` |
|
||||
| 3 | Close | (none) |
|
||||
|
||||
### Drawing Helpers
|
||||
|
||||
Standalone apps typically define local pixel-drawing helpers since they work with raw `uint32_t*` buffers:
|
||||
|
||||
```cpp
|
||||
static void px_fill(uint32_t* px, int bw, int bh,
|
||||
int x, int y, int w, int h, uint32_t color) {
|
||||
for (int row = y; row < y + h && row < bh; row++)
|
||||
for (int col = x; col < x + w && col < bw; col++)
|
||||
px[row * bw + col] = color;
|
||||
}
|
||||
|
||||
static void px_hline(uint32_t* px, int bw, int bh,
|
||||
int x, int y, int w, uint32_t color) {
|
||||
for (int col = x; col < x + w && col < bw; col++)
|
||||
if (y >= 0 && y < bh) px[y * bw + col] = color;
|
||||
}
|
||||
|
||||
static void px_text(uint32_t* px, int bw, int bh,
|
||||
int x, int y, const char* text, Color c, int size) {
|
||||
if (g_font)
|
||||
g_font->draw_to_buffer(px, bw, bh, x, y, text, c, size);
|
||||
}
|
||||
```
|
||||
|
||||
### Rounded Rectangles
|
||||
|
||||
```cpp
|
||||
static void px_fill_rounded(uint32_t* px, int bw, int bh,
|
||||
int x, int y, int w, int h, int r, uint32_t color) {
|
||||
for (int row = y; row < y + h && row < bh; row++) {
|
||||
for (int col = x; col < x + w && col < bw; col++) {
|
||||
int dx = 0, dy = 0;
|
||||
if (col < x + r && row < y + r) { dx = x + r - col; dy = y + r - row; }
|
||||
else if (col >= x+w-r && row < y + r) { dx = col - (x+w-r-1); dy = y + r - row; }
|
||||
else if (col < x + r && row >= y+h-r) { dx = x + r - col; dy = row - (y+h-r-1); }
|
||||
else if (col >= x+w-r && row >= y+h-r) { dx = col - (x+w-r-1); dy = row - (y+h-r-1); }
|
||||
if (dx * dx + dy * dy <= r * r)
|
||||
px[row * bw + col] = color;
|
||||
else if (dx == 0 && dy == 0)
|
||||
px[row * bw + col] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Desktop-Integrated Apps
|
||||
|
||||
Desktop apps are compiled into the desktop binary itself. They register callback functions that the compositor calls during its event loop.
|
||||
|
||||
### Creating a Desktop App
|
||||
|
||||
**Step 1: Define your app state**
|
||||
|
||||
```cpp
|
||||
// In apps/app_myapp.cpp
|
||||
struct MyAppState {
|
||||
int counter;
|
||||
char label[64];
|
||||
};
|
||||
```
|
||||
|
||||
**Step 2: Implement callbacks**
|
||||
|
||||
```cpp
|
||||
static void myapp_on_draw(Window* win, Framebuffer& fb) {
|
||||
MyAppState* state = (MyAppState*)win->app_data;
|
||||
Canvas c(win);
|
||||
|
||||
c.fill(colors::WINDOW_BG);
|
||||
|
||||
// Draw toolbar
|
||||
c.fill_rect(0, 0, win->content_w, 36, Color::from_rgb(0xF5, 0xF5, 0xF5));
|
||||
c.hline(0, 36, win->content_w, colors::BORDER);
|
||||
|
||||
// Draw content
|
||||
c.text(20, 60, state->label, colors::TEXT_COLOR);
|
||||
}
|
||||
|
||||
static void myapp_on_mouse(Window* win, MouseEvent& ev) {
|
||||
MyAppState* state = (MyAppState*)win->app_data;
|
||||
if (ev.left_pressed()) {
|
||||
state->counter++;
|
||||
win->dirty = true; // Request redraw
|
||||
}
|
||||
}
|
||||
|
||||
static void myapp_on_key(Window* win, const Montauk::KeyEvent& key) {
|
||||
if (!key.pressed) return;
|
||||
MyAppState* state = (MyAppState*)win->app_data;
|
||||
// Handle keystrokes...
|
||||
win->dirty = true;
|
||||
}
|
||||
|
||||
static void myapp_on_close(Window* win) {
|
||||
MyAppState* state = (MyAppState*)win->app_data;
|
||||
montauk::mfree(state);
|
||||
}
|
||||
```
|
||||
|
||||
**Step 3: Write the open function**
|
||||
|
||||
```cpp
|
||||
void open_myapp(DesktopState* ds) {
|
||||
int idx = desktop_create_window(ds, "My App", 400, 300, 320, 400);
|
||||
if (idx < 0) return;
|
||||
Window* win = &ds->windows[idx];
|
||||
|
||||
MyAppState* state = (MyAppState*)montauk::malloc(sizeof(MyAppState));
|
||||
montauk::memset(state, 0, sizeof(MyAppState));
|
||||
|
||||
win->app_data = state;
|
||||
win->on_draw = myapp_on_draw;
|
||||
win->on_mouse = myapp_on_mouse;
|
||||
win->on_key = myapp_on_key;
|
||||
win->on_close = myapp_on_close;
|
||||
win->dirty = true;
|
||||
}
|
||||
```
|
||||
|
||||
**Step 4: Register in the app menu**
|
||||
|
||||
Add an entry in `desktop_init()` (`main.cpp`) to the app menu so users can launch it. Include the `open_myapp` function in `apps_common.hpp` or similar.
|
||||
|
||||
### Callback Reference
|
||||
|
||||
| Callback | Signature | When Called |
|
||||
|---|---|---|
|
||||
| `on_draw` | `void(Window*, Framebuffer&)` | Every frame when `win->dirty` is true |
|
||||
| `on_mouse` | `void(Window*, MouseEvent&)` | Mouse event within window content area |
|
||||
| `on_key` | `void(Window*, const KeyEvent&)` | Keyboard event while window is focused |
|
||||
| `on_close` | `void(Window*)` | Window close button clicked |
|
||||
| `on_poll` | `void(Window*)` | Every frame, for background processing |
|
||||
|
||||
### The `dirty` Flag
|
||||
|
||||
Desktop apps use a `dirty` flag to control redraws. Set `win->dirty = true` after any state change that requires a visual update. The compositor skips `on_draw` for non-dirty windows.
|
||||
|
||||
---
|
||||
|
||||
## Drawing and Rendering
|
||||
|
||||
### Canvas API (Desktop Apps)
|
||||
|
||||
The `Canvas` wraps a window's pixel buffer with drawing primitives:
|
||||
|
||||
```cpp
|
||||
Canvas c(win); // Construct from Window*
|
||||
|
||||
// Fills
|
||||
c.fill(Color c); // Entire buffer
|
||||
c.fill_rect(int x, int y, int w, int h, Color c); // Rectangle
|
||||
c.fill_rounded_rect(int x, int y, int w, int h, int r, Color c); // Rounded rect
|
||||
|
||||
// Lines
|
||||
c.hline(int x, int y, int len, Color c); // Horizontal
|
||||
c.vline(int x, int y, int len, Color c); // Vertical
|
||||
c.rect(int x, int y, int w, int h, Color c); // Outline
|
||||
|
||||
// Text
|
||||
c.text(int x, int y, const char* str, Color c); // TrueType or bitmap
|
||||
c.text_2x(int x, int y, const char* str, Color c); // 2x scaled bitmap
|
||||
c.text_mono(int x, int y, const char* str, Color c); // Monospace
|
||||
|
||||
// UI elements
|
||||
c.button(int x, int y, int w, int h, const char* label,
|
||||
Color bg, Color fg, int radius); // Styled button
|
||||
c.icon(int x, int y, const SvgIcon& ic); // SVG icon
|
||||
|
||||
// Layout helpers
|
||||
c.kv_line(int x, int* y, const char* line, Color c, int line_h); // Key-value line
|
||||
c.separator(int x_start, int x_end, int* y, Color c, int spacing); // Horizontal separator
|
||||
```
|
||||
|
||||
### Framebuffer API (Low-Level)
|
||||
|
||||
For direct framebuffer access (used by the compositor itself and fullscreen apps):
|
||||
|
||||
```cpp
|
||||
Framebuffer fb;
|
||||
fb.put_pixel(x, y, color);
|
||||
fb.put_pixel_alpha(x, y, color); // With alpha blending
|
||||
fb.fill_rect(x, y, w, h, color);
|
||||
fb.fill_rect_alpha(x, y, w, h, color);
|
||||
fb.blit(x, y, w, h, pixels); // Copy pixel region
|
||||
fb.blit_alpha(x, y, w, h, pixels); // With alpha blending
|
||||
fb.clear(color);
|
||||
fb.flip(); // Swap to hardware
|
||||
```
|
||||
|
||||
### Drawing Primitives
|
||||
|
||||
From `gui/draw.hpp`, available for both Framebuffer-based rendering:
|
||||
|
||||
```cpp
|
||||
draw_hline(fb, x, y, w, color);
|
||||
draw_vline(fb, x, y, h, color);
|
||||
draw_rect(fb, x, y, w, h, color);
|
||||
fill_rounded_rect(fb, x, y, w, h, radius, color);
|
||||
fill_circle(fb, cx, cy, r, color);
|
||||
draw_circle(fb, cx, cy, r, color);
|
||||
draw_line(fb, x0, y0, x1, y1, color); // Bresenham's
|
||||
draw_shadow(fb, x, y, w, h, offset, color);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Text and Fonts
|
||||
|
||||
### TrueType Fonts (Preferred)
|
||||
|
||||
MontaukOS uses `stb_truetype` for font rendering. Fonts are loaded from the VFS:
|
||||
|
||||
```cpp
|
||||
TrueTypeFont* font = new TrueTypeFont();
|
||||
font->init("0:/fonts/Roboto-Medium.ttf");
|
||||
|
||||
// Render text to a pixel buffer
|
||||
font->draw_to_buffer(pixels, buf_w, buf_h, x, y, "Hello", color, 18);
|
||||
|
||||
// Measure text width before drawing
|
||||
int width = font->measure_text("Hello", 18);
|
||||
|
||||
// Get line height for layout
|
||||
int line_h = font->get_line_height(18);
|
||||
```
|
||||
|
||||
### System Fonts
|
||||
|
||||
The desktop initializes a set of global fonts:
|
||||
|
||||
```cpp
|
||||
fonts::init(); // Call once at startup
|
||||
|
||||
// Available fonts
|
||||
fonts::system_font // Roboto-Medium.ttf (UI text)
|
||||
fonts::system_bold // Roboto-Bold.ttf (headings)
|
||||
fonts::mono // JetBrainsMono-Regular.ttf (code/terminal)
|
||||
fonts::mono_bold // JetBrainsMono-Bold.ttf
|
||||
|
||||
// Standard sizes
|
||||
fonts::UI_SIZE // 18 (body text)
|
||||
fonts::TITLE_SIZE // 18 (window titles)
|
||||
fonts::LARGE_SIZE // 28 (headings)
|
||||
fonts::TERM_SIZE // 18 (terminal)
|
||||
```
|
||||
|
||||
### Glyph Caching
|
||||
|
||||
TrueType fonts cache rasterized glyphs per pixel size. Up to 4 size caches are maintained per font. Access the cache directly for advanced metrics:
|
||||
|
||||
```cpp
|
||||
GlyphCache* cache = font->get_cache(18);
|
||||
// cache->ascent, cache->descent — for line-height calculation
|
||||
```
|
||||
|
||||
### Bitmap Font (Fallback)
|
||||
|
||||
An 8x8 bitmap font is always available for basic text rendering when TrueType is not loaded:
|
||||
|
||||
```cpp
|
||||
draw_char(fb, x, y, 'A', color);
|
||||
draw_text(fb, x, y, "Hello", color);
|
||||
int w = text_width("Hello");
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Input Handling
|
||||
|
||||
### Keyboard
|
||||
|
||||
```cpp
|
||||
// In standalone apps (via win_poll)
|
||||
if (ev.type == 0) {
|
||||
Montauk::KeyEvent& key = ev.key;
|
||||
if (!key.pressed) { /* key release */ }
|
||||
|
||||
if (key.ascii >= 0x20 && key.ascii < 0x7F) {
|
||||
// Printable character
|
||||
}
|
||||
|
||||
// Special keys by scancode
|
||||
switch (key.scancode) {
|
||||
case 0x01: /* Escape */ break;
|
||||
case 0x0E: /* Backspace */ break;
|
||||
case 0x1C: /* Enter */ break;
|
||||
case 0x0F: /* Tab */ break;
|
||||
case 0x53: /* Delete */ break;
|
||||
case 0x48: /* Up */ break;
|
||||
case 0x50: /* Down */ break;
|
||||
case 0x4B: /* Left */ break;
|
||||
case 0x4D: /* Right */ break;
|
||||
case 0x47: /* Home */ break;
|
||||
case 0x4F: /* End */ break;
|
||||
case 0x49: /* Page Up */ break;
|
||||
case 0x51: /* Page Down */ break;
|
||||
}
|
||||
|
||||
// Modifiers
|
||||
if (key.ctrl) { /* Ctrl held */ }
|
||||
if (key.shift) { /* Shift held */ }
|
||||
if (key.alt) { /* Alt held */ }
|
||||
}
|
||||
```
|
||||
|
||||
### Mouse
|
||||
|
||||
```cpp
|
||||
// In standalone apps (via win_poll)
|
||||
if (ev.type == 1) {
|
||||
int mx = ev.mouse.x;
|
||||
int my = ev.mouse.y;
|
||||
|
||||
// Button state
|
||||
bool left_down = ev.mouse.buttons & 0x01;
|
||||
bool right_down = ev.mouse.buttons & 0x02;
|
||||
|
||||
// Detect clicks (press edge)
|
||||
bool left_pressed = (ev.mouse.buttons & 0x01) && !(ev.mouse.prev_buttons & 0x01);
|
||||
bool left_released = !(ev.mouse.buttons & 0x01) && (ev.mouse.prev_buttons & 0x01);
|
||||
|
||||
// Scroll wheel
|
||||
int scroll = ev.mouse.scroll; // Positive = up, negative = down
|
||||
}
|
||||
```
|
||||
|
||||
In desktop apps, the `MouseEvent` struct provides convenience methods:
|
||||
|
||||
```cpp
|
||||
void myapp_on_mouse(Window* win, MouseEvent& ev) {
|
||||
if (ev.left_pressed()) { /* click start */ }
|
||||
if (ev.left_released()) { /* click end */ }
|
||||
if (ev.left_held()) { /* dragging */ }
|
||||
if (ev.right_pressed()) { /* context menu */ }
|
||||
if (ev.scroll != 0) { /* scroll */ }
|
||||
}
|
||||
```
|
||||
|
||||
### Hit Testing
|
||||
|
||||
A common pattern for clickable UI regions:
|
||||
|
||||
```cpp
|
||||
struct ButtonRect { int x, y, w, h; };
|
||||
|
||||
bool hit_test(ButtonRect& btn, int mx, int my) {
|
||||
return mx >= btn.x && mx < btn.x + btn.w &&
|
||||
my >= btn.y && my < btn.y + btn.h;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Widgets
|
||||
|
||||
MontaukOS provides built-in widget types in `gui/widgets.hpp`:
|
||||
|
||||
### Button
|
||||
|
||||
```cpp
|
||||
Button btn;
|
||||
btn.init(x, y, width, height, "Click Me");
|
||||
btn.bg = colors::ACCENT;
|
||||
btn.fg = colors::WHITE;
|
||||
btn.on_click = [](void* data) { /* handle click */ };
|
||||
btn.userdata = my_state;
|
||||
|
||||
// In draw callback
|
||||
btn.draw(fb);
|
||||
|
||||
// In mouse callback
|
||||
btn.handle_mouse(ev);
|
||||
```
|
||||
|
||||
### TextBox
|
||||
|
||||
```cpp
|
||||
TextBox tb;
|
||||
tb.init(x, y, width, height);
|
||||
|
||||
// In draw callback
|
||||
tb.draw(fb);
|
||||
|
||||
// In mouse callback (sets focus)
|
||||
tb.handle_mouse(ev);
|
||||
|
||||
// In key callback (text input)
|
||||
tb.handle_key(key);
|
||||
|
||||
// Read value
|
||||
const char* value = tb.text;
|
||||
```
|
||||
|
||||
### Scrollbar
|
||||
|
||||
```cpp
|
||||
Scrollbar sb;
|
||||
sb.init(x, y, width, height);
|
||||
sb.content_height = 2000; // Total content height
|
||||
sb.view_height = 400; // Visible area height
|
||||
|
||||
// In draw callback
|
||||
sb.draw(fb);
|
||||
|
||||
// In mouse callback
|
||||
sb.handle_mouse(ev);
|
||||
|
||||
// Use scroll_offset for content positioning
|
||||
int offset = sb.scroll_offset;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Colors and Theming
|
||||
|
||||
### Color Construction
|
||||
|
||||
```cpp
|
||||
Color c1 = Color::from_rgb(0xFF, 0x00, 0x00); // Red
|
||||
Color c2 = Color::from_rgba(0x00, 0x00, 0xFF, 0x80); // Semi-transparent blue
|
||||
Color c3 = Color::from_hex(0x367BF0); // From hex
|
||||
uint32_t pixel = c3.to_pixel(); // ARGB for pixel buffer
|
||||
```
|
||||
|
||||
### System Colors
|
||||
|
||||
Defined in `gui/gui.hpp` under the `colors` namespace:
|
||||
|
||||
| Constant | Hex | Usage |
|
||||
|---|---|---|
|
||||
| `WINDOW_BG` | `#FFFFFF` | Window content background |
|
||||
| `TEXT_COLOR` | `#333333` | Primary text |
|
||||
| `ACCENT` | `#367BF0` | Links, selections, active elements |
|
||||
| `BORDER` | `#D0D0D0` | Window/widget borders |
|
||||
| `PANEL_BG` | `#2B3E50` | Taskbar/panel background |
|
||||
| `PANEL_TEXT` | `#FFFFFF` | Panel text |
|
||||
| `TITLEBAR_BG` | `#F5F5F5` | Window titlebar |
|
||||
| `DESKTOP_BG` | `#E0E0E0` | Desktop background |
|
||||
| `CLOSE_BTN` | `#FF5F57` | Close button (red) |
|
||||
| `MAX_BTN` | `#28CA42` | Maximize button (green) |
|
||||
| `MIN_BTN` | `#FFBD2E` | Minimize button (yellow) |
|
||||
| `TERM_BG` | `#2D2D2D` | Terminal background |
|
||||
| `TERM_FG` | `#CCCCCC` | Terminal text |
|
||||
| `SCROLLBAR_BG` | | Scrollbar track |
|
||||
| `SCROLLBAR_FG` | | Scrollbar thumb |
|
||||
|
||||
### Toolbar Convention
|
||||
|
||||
Standard toolbar pattern used across desktop apps:
|
||||
|
||||
```cpp
|
||||
// 36px tall, light gray background, thin bottom border
|
||||
c.fill_rect(0, 0, win->content_w, 36, Color::from_rgb(0xF5, 0xF5, 0xF5));
|
||||
c.hline(0, 36, win->content_w, colors::BORDER);
|
||||
|
||||
// 24x24 icon buttons centered at y=6
|
||||
c.icon(8, 6, my_icon);
|
||||
|
||||
// Content starts below toolbar
|
||||
int content_y = 37;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Memory Management
|
||||
|
||||
### Userspace Heap
|
||||
|
||||
Use `montauk::malloc`, `montauk::mfree`, and `montauk::realloc` for dynamic allocation:
|
||||
|
||||
```cpp
|
||||
#include <montauk/heap.h>
|
||||
|
||||
MyState* state = (MyState*)montauk::malloc(sizeof(MyState));
|
||||
montauk::memset(state, 0, sizeof(MyState));
|
||||
// ... use state ...
|
||||
montauk::mfree(state);
|
||||
|
||||
// Resize
|
||||
char* buf = (char*)montauk::malloc(256);
|
||||
buf = (char*)montauk::realloc(buf, 512);
|
||||
```
|
||||
|
||||
The allocator uses size-class buckets (32 to 4096 bytes) with an overflow list for larger allocations.
|
||||
|
||||
### Kernel Page Allocation
|
||||
|
||||
`montauk::alloc` / `montauk::free` allocate kernel pages. Avoid for temporary buffers; use the heap instead.
|
||||
|
||||
### Important Notes
|
||||
|
||||
- **User stack is 32 KiB** (8 pages). Deep call chains (e.g., TrueType rendering) can approach this limit. Avoid large stack allocations.
|
||||
- Use `inline` (not `static`) for shared globals in headers to avoid per-translation-unit copies and heap corruption.
|
||||
- The libc needs `-fno-tree-loop-distribute-patterns` in CFLAGS to prevent GCC from converting `memcpy`/`memset` into calls to themselves.
|
||||
|
||||
---
|
||||
|
||||
## Networking and HTTPS
|
||||
|
||||
MontaukOS provides a shared TLS library (`tls/tls.hpp`) backed by BearSSL, and the MontaukAI dev environment adds a higher-level HTTP wrapper (`http/http.hpp`) on top. Build with `USE_TLS=1` to link TLS support.
|
||||
|
||||
### HTTP Wrapper (`http/http.hpp`)
|
||||
|
||||
Header-only library that handles DNS resolution, request building, TLS, response parsing, and cleanup. All functions return an `http::Response` struct.
|
||||
|
||||
#### Setup
|
||||
|
||||
```cpp
|
||||
#include <http/http.hpp>
|
||||
|
||||
// Load CA certificates once at startup (required for HTTPS)
|
||||
tls::TrustAnchors tas = tls::load_trust_anchors();
|
||||
```
|
||||
|
||||
#### GET
|
||||
|
||||
```cpp
|
||||
auto resp = http::get("api.example.com", "/v1/data", tas);
|
||||
if (resp.status == 200) {
|
||||
// resp.body is a pointer to the response body
|
||||
// resp.body_len is its length
|
||||
}
|
||||
http::free_response(&resp);
|
||||
```
|
||||
|
||||
#### POST
|
||||
|
||||
```cpp
|
||||
const char* json = "{\"name\":\"MontaukOS\",\"version\":1}";
|
||||
auto resp = http::post("api.example.com", "/v1/submit",
|
||||
"application/json",
|
||||
json, montauk::slen(json),
|
||||
tas);
|
||||
if (resp.status == 201) {
|
||||
// Created successfully
|
||||
}
|
||||
http::free_response(&resp);
|
||||
```
|
||||
|
||||
#### Other Methods (PUT, PATCH, DELETE, ...)
|
||||
|
||||
```cpp
|
||||
auto resp = http::request("PUT", "api.example.com", "/v1/item/42",
|
||||
"application/json",
|
||||
body, bodyLen, tas);
|
||||
http::free_response(&resp);
|
||||
|
||||
// DELETE with no body
|
||||
auto resp2 = http::request("DELETE", "api.example.com", "/v1/item/42",
|
||||
nullptr, nullptr, 0, tas);
|
||||
http::free_response(&resp2);
|
||||
```
|
||||
|
||||
#### Plain HTTP (No TLS, Port 80)
|
||||
|
||||
```cpp
|
||||
auto resp = http::get_plain("example.com", "/");
|
||||
if (resp.status == 200) {
|
||||
// resp.body ...
|
||||
}
|
||||
http::free_response(&resp);
|
||||
```
|
||||
|
||||
#### Reading Response Headers
|
||||
|
||||
```cpp
|
||||
char content_type[128];
|
||||
if (http::get_header(&resp, "Content-Type", content_type, sizeof(content_type))) {
|
||||
// content_type is e.g. "application/json; charset=utf-8"
|
||||
}
|
||||
```
|
||||
|
||||
#### Custom Headers
|
||||
|
||||
Pass extra headers as a string with `\r\n` terminators:
|
||||
|
||||
```cpp
|
||||
auto resp = http::get("api.example.com", "/v1/data", tas,
|
||||
32768, // response buffer size
|
||||
"Authorization: Bearer tok_abc123\r\n"
|
||||
"Accept: application/json\r\n");
|
||||
http::free_response(&resp);
|
||||
```
|
||||
|
||||
#### Cancellable Requests
|
||||
|
||||
For GUI apps that need to stay responsive during network I/O:
|
||||
|
||||
```cpp
|
||||
static bool g_quit = false;
|
||||
static bool check_abort() { return g_quit; }
|
||||
|
||||
auto resp = http::get("api.example.com", "/v1/slow", tas,
|
||||
32768, nullptr, check_abort);
|
||||
http::free_response(&resp);
|
||||
```
|
||||
|
||||
Set `g_quit = true` from your keyboard handler (e.g., on Escape) to cancel mid-request.
|
||||
|
||||
#### Response Struct Reference
|
||||
|
||||
```cpp
|
||||
struct http::Response {
|
||||
int status; // HTTP status code (200, 404, ...) or -1 on error
|
||||
const char* headers; // Pointer to header block (within raw buffer)
|
||||
int headers_len;
|
||||
const char* body; // Pointer to body (within raw buffer)
|
||||
int body_len;
|
||||
char* raw; // Owned buffer — freed by free_response()
|
||||
int raw_len;
|
||||
};
|
||||
```
|
||||
|
||||
#### Function Signatures
|
||||
|
||||
```cpp
|
||||
// HTTPS GET
|
||||
http::Response http::get(const char* host, const char* path,
|
||||
const tls::TrustAnchors& tas,
|
||||
int resp_buf_size = 32768,
|
||||
const char* extra_headers = nullptr,
|
||||
tls::AbortCheckFn abort_check = nullptr);
|
||||
|
||||
// HTTPS POST
|
||||
http::Response http::post(const char* host, const char* path,
|
||||
const char* content_type,
|
||||
const char* body, int body_len,
|
||||
const tls::TrustAnchors& tas,
|
||||
int resp_buf_size = 32768,
|
||||
const char* extra_headers = nullptr,
|
||||
tls::AbortCheckFn abort_check = nullptr);
|
||||
|
||||
// HTTPS with any method
|
||||
http::Response http::request(const char* method,
|
||||
const char* host, const char* path,
|
||||
const char* content_type,
|
||||
const char* body, int body_len,
|
||||
const tls::TrustAnchors& tas,
|
||||
int resp_buf_size = 32768,
|
||||
const char* extra_headers = nullptr,
|
||||
tls::AbortCheckFn abort_check = nullptr);
|
||||
|
||||
// Plain HTTP GET (port 80, no TLS)
|
||||
http::Response http::get_plain(const char* host, const char* path,
|
||||
int resp_buf_size = 32768,
|
||||
const char* extra_headers = nullptr);
|
||||
|
||||
// Parse raw HTTP response buffer (used internally, available if needed)
|
||||
int http::parse_response(char* buf, int len, http::Response* out);
|
||||
|
||||
// Case-insensitive header lookup
|
||||
bool http::get_header(const http::Response* resp, const char* name,
|
||||
char* out_val, int max_len);
|
||||
|
||||
// Free the response's raw buffer
|
||||
void http::free_response(http::Response* resp);
|
||||
```
|
||||
|
||||
### Low-Level TLS API (`tls/tls.hpp`)
|
||||
|
||||
If you need more control than `http::` provides (e.g., streaming responses, custom BearSSL setup), use the TLS layer directly:
|
||||
|
||||
```cpp
|
||||
#include <tls/tls.hpp>
|
||||
|
||||
tls::TrustAnchors tas = tls::load_trust_anchors();
|
||||
|
||||
// Build raw HTTP request yourself
|
||||
char req[512];
|
||||
// ... "GET /stream HTTP/1.1\r\nHost: ...\r\n\r\n" ...
|
||||
|
||||
char buf[65536];
|
||||
int n = tls::https_fetch("example.com", ip, 443, req, reqLen, tas, buf, sizeof(buf));
|
||||
```
|
||||
|
||||
See `syscalls.md` for the full `tls::` API reference.
|
||||
|
||||
### Plain TCP/UDP
|
||||
|
||||
For non-TLS networking without the HTTP wrapper, use the raw socket syscalls directly (see `syscalls.md`):
|
||||
|
||||
```cpp
|
||||
int sock = montauk::socket(Montauk::SOCK_TCP); // or SOCK_UDP
|
||||
montauk::connect(sock, ip, port);
|
||||
montauk::send(sock, data, len);
|
||||
int n = montauk::recv(sock, buf, maxLen);
|
||||
montauk::closesocket(sock);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## App Manifests
|
||||
|
||||
External standalone apps can be discovered by the desktop through TOML manifest files placed in `0:/apps/`:
|
||||
|
||||
```toml
|
||||
[app]
|
||||
name = "My App"
|
||||
binary = "myapp"
|
||||
icon = "myapp_icon.svg"
|
||||
|
||||
[menu]
|
||||
category = "Applications"
|
||||
visible = true
|
||||
```
|
||||
|
||||
**Categories:** `Applications`, `Internet`, `System`, `Games`
|
||||
|
||||
The desktop scans `0:/apps/` at startup and adds matching entries to the application menu. The `binary` field is the executable name (looked up in the system path).
|
||||
|
||||
---
|
||||
|
||||
## Build System
|
||||
|
||||
### Independent Development (MontaukAI)
|
||||
|
||||
The `MontaukAI/` directory provides a self-contained build environment. Edit the top of `Makefile` to configure your app:
|
||||
|
||||
```makefile
|
||||
APP_NAME := myapp
|
||||
SRCS := src/main.cpp src/stb_truetype_impl.cpp src/cxxrt.cpp src/network.cpp
|
||||
```
|
||||
|
||||
Build with optional feature flags:
|
||||
|
||||
```bash
|
||||
make # GUI-only app
|
||||
make USE_TLS=1 # With HTTPS/TLS (links libtls + libbearssl)
|
||||
make USE_JPEG=1 # With JPEG decoding (links libjpeg)
|
||||
make USE_TLS=1 USE_JPEG=1 # Both
|
||||
make install # Copy ELF to MontaukOS ramdisk
|
||||
```
|
||||
|
||||
The sysroot contains all headers and pre-built libraries:
|
||||
|
||||
```
|
||||
sysroot/
|
||||
├── include/
|
||||
│ ├── montauk/ syscall.h, heap.h, string.h, config.h, toml.h, user.h
|
||||
│ ├── gui/ gui.hpp, canvas.hpp, truetype.hpp, widgets.hpp, svg.hpp, ...
|
||||
│ ├── tls/ tls.hpp (HTTPS/TLS)
|
||||
│ ├── Api/ Syscall.hpp (low-level syscall numbers)
|
||||
│ ├── libc/ stdio.h, stdlib.h, string.h, ... (freestanding libc)
|
||||
│ ├── bearssl*.h BearSSL headers (for USE_TLS=1)
|
||||
│ └── (freestanding C/C++ standard headers)
|
||||
└── lib/
|
||||
├── liblibc.a C library (always linked)
|
||||
├── libtls.a TLS helper library
|
||||
├── libbearssl.a BearSSL crypto
|
||||
└── libjpeg.a JPEG decoding (stb_image)
|
||||
```
|
||||
|
||||
Key build details:
|
||||
- **Toolchain:** `x86_64-elf-g++` cross-compiler (falls back to system g++)
|
||||
- **Standard:** C++20 (`-std=gnu++20`), freestanding, no exceptions/RTTI
|
||||
- **SSE:** Enabled (`-msse -msse2`) for floating-point / TrueType rendering
|
||||
- **Entry point:** `extern "C" void _start()` (not `main`)
|
||||
- **Load address:** `0x400000` (set in `link.ld`)
|
||||
- **Runtime support:** `src/cxxrt.cpp` provides `operator new/delete` via `montauk::malloc/mfree`
|
||||
- **TrueType support:** `src/stb_truetype_impl.cpp` provides the stb_truetype implementation
|
||||
|
||||
### In-Tree Development
|
||||
|
||||
Standalone apps can also live in `MontaukOS/programs/src/<appname>/` with their own `Makefile`. Each app's Makefile sets `SRCS`, `CXXFLAGS`, `LDFLAGS`, and links against libraries in `programs/lib/`.
|
||||
|
||||
Desktop-integrated apps are compiled as part of the desktop binary — add your `.cpp` file to the desktop's source list in `programs/src/desktop/Makefile`.
|
||||
@@ -0,0 +1,572 @@
|
||||
# MontaukOS Syscall Reference
|
||||
|
||||
All syscalls are available through `#include <montauk/syscall.h>` in the `montauk` namespace. The syscall layer provides `syscall0()` through `syscall6()` primitives using AMD64 calling conventions. All raw syscalls return `int64_t`.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Process Management](#process-management)
|
||||
- [File System](#file-system)
|
||||
- [Memory](#memory)
|
||||
- [Console I/O](#console-io)
|
||||
- [Keyboard and Mouse](#keyboard-and-mouse)
|
||||
- [Window Server](#window-server)
|
||||
- [Framebuffer](#framebuffer)
|
||||
- [Networking](#networking)
|
||||
- [Audio](#audio)
|
||||
- [Bluetooth](#bluetooth)
|
||||
- [Timekeeping](#timekeeping)
|
||||
- [System Information](#system-information)
|
||||
- [Storage and Disks](#storage-and-disks)
|
||||
- [Terminal](#terminal)
|
||||
- [Process I/O Redirection](#process-io-redirection)
|
||||
- [Configuration](#configuration)
|
||||
- [User Management](#user-management)
|
||||
- [Utility Libraries](#utility-libraries)
|
||||
|
||||
---
|
||||
|
||||
## Process Management
|
||||
|
||||
```cpp
|
||||
void exit(int code); // Terminate process (noreturn)
|
||||
void yield(); // Yield CPU to scheduler
|
||||
void sleep_ms(uint64_t ms); // Sleep for milliseconds
|
||||
int getpid(); // Get current process ID
|
||||
int spawn(const char* path, const char* args); // Spawn child process (-1 on error)
|
||||
int waitpid(int pid); // Wait for process to exit
|
||||
int kill(int pid); // Kill a process
|
||||
int proclist(ProcInfo* buf, int max); // List all processes (returns count)
|
||||
```
|
||||
|
||||
**`ProcInfo` struct:**
|
||||
```cpp
|
||||
struct ProcInfo {
|
||||
int pid;
|
||||
char name[32];
|
||||
// ... additional fields
|
||||
};
|
||||
```
|
||||
|
||||
### Arguments
|
||||
|
||||
```cpp
|
||||
int getargs(char* buf, uint64_t maxLen); // Get command-line arguments passed to this process
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## File System
|
||||
|
||||
```cpp
|
||||
int open(const char* path); // Open file (returns fd, negative on error)
|
||||
int close(int handle); // Close file handle
|
||||
int read(int handle, uint8_t* buf, uint64_t off, uint64_t size); // Read bytes at offset (returns bytes read)
|
||||
int fwrite(int handle, const uint8_t* buf, uint64_t off, uint64_t size); // Write bytes at offset
|
||||
uint64_t getsize(int handle); // Get file size
|
||||
int readdir(const char* path, const char** names, int max); // List directory entries (returns count)
|
||||
int fcreate(const char* path); // Create file (returns fd)
|
||||
int fdelete(const char* path); // Delete file (0 on success)
|
||||
int fmkdir(const char* path); // Create directory
|
||||
int drivelist(int* outDrives, int max); // Enumerate mounted drives (returns count)
|
||||
```
|
||||
|
||||
### Path Format
|
||||
|
||||
Paths use the format `<drive>:/<path>`, e.g. `0:/fonts/Roboto-Medium.ttf`. Drive 0 is the boot drive (ramdisk).
|
||||
|
||||
### Example: Reading a File
|
||||
|
||||
```cpp
|
||||
int fd = montauk::open("0:/config/settings.toml");
|
||||
if (fd < 0) { /* error */ }
|
||||
|
||||
uint64_t size = montauk::getsize(fd);
|
||||
uint8_t* buf = (uint8_t*)montauk::malloc(size + 1);
|
||||
montauk::read(fd, buf, 0, size);
|
||||
buf[size] = 0; // null-terminate
|
||||
montauk::close(fd);
|
||||
|
||||
// ... use buf ...
|
||||
montauk::mfree(buf);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Memory
|
||||
|
||||
```cpp
|
||||
void* alloc(uint64_t size); // Allocate kernel pages (avoid for temp buffers)
|
||||
void free(void* ptr); // Free kernel pages
|
||||
```
|
||||
|
||||
For general-purpose allocation, prefer the userspace heap (`montauk/heap.h`):
|
||||
|
||||
```cpp
|
||||
void* malloc(uint64_t size);
|
||||
void mfree(void* ptr);
|
||||
void* realloc(void* ptr, uint64_t size);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Console I/O
|
||||
|
||||
```cpp
|
||||
void print(const char* text); // Write string to kernel console
|
||||
void putchar(char c); // Write single character
|
||||
```
|
||||
|
||||
These write to the kernel's text-mode console, not to a GUI window.
|
||||
|
||||
---
|
||||
|
||||
## Keyboard and Mouse
|
||||
|
||||
### Keyboard (Direct, Non-Windowed)
|
||||
|
||||
```cpp
|
||||
bool is_key_available(); // Poll for pending keystroke
|
||||
void getkey(Montauk::KeyEvent* out); // Get next keystroke (blocks)
|
||||
char getchar(); // Get single ASCII character (blocks)
|
||||
```
|
||||
|
||||
**`KeyEvent` struct:**
|
||||
```cpp
|
||||
struct KeyEvent {
|
||||
bool pressed; // true = key down, false = key up
|
||||
uint8_t scancode; // PS/2 scancode
|
||||
char ascii; // ASCII value (0 if non-printable)
|
||||
bool shift, ctrl, alt;
|
||||
};
|
||||
```
|
||||
|
||||
**Common Scancodes:**
|
||||
|
||||
| Scancode | Key |
|
||||
|---|---|
|
||||
| `0x01` | Escape |
|
||||
| `0x0E` | Backspace |
|
||||
| `0x0F` | Tab |
|
||||
| `0x1C` | Enter |
|
||||
| `0x39` | Space |
|
||||
| `0x53` | Delete |
|
||||
| `0x48` | Up |
|
||||
| `0x50` | Down |
|
||||
| `0x4B` | Left |
|
||||
| `0x4D` | Right |
|
||||
| `0x47` | Home |
|
||||
| `0x4F` | End |
|
||||
| `0x49` | Page Up |
|
||||
| `0x51` | Page Down |
|
||||
|
||||
### Mouse (Direct, Non-Windowed)
|
||||
|
||||
```cpp
|
||||
void mouse_state(Montauk::MouseState* out); // Get current mouse state
|
||||
void set_mouse_bounds(int32_t maxX, int32_t maxY); // Set mouse boundary
|
||||
```
|
||||
|
||||
**`MouseState` struct:**
|
||||
```cpp
|
||||
struct MouseState {
|
||||
int32_t x, y;
|
||||
uint8_t buttons; // 0x01=Left, 0x02=Right, 0x04=Middle
|
||||
};
|
||||
```
|
||||
|
||||
For GUI apps, prefer the windowed event system (`win_poll`) over direct mouse/keyboard syscalls.
|
||||
|
||||
---
|
||||
|
||||
## Window Server
|
||||
|
||||
These syscalls are for standalone GUI apps that run as separate processes. The desktop compositor manages window frames; your app renders into a shared pixel buffer.
|
||||
|
||||
```cpp
|
||||
int win_create(const char* title, int w, int h, WinCreateResult* result);
|
||||
void win_destroy(int id);
|
||||
uint64_t win_present(int id); // Mark window dirty, present to screen
|
||||
int win_poll(int id, WinEvent* event); // Poll events (0=none, 1=event, <0=closed)
|
||||
uint64_t win_resize(int id, int w, int h); // Resize, returns new pixel buffer address
|
||||
uint64_t win_map(int id); // Get pixel buffer address
|
||||
int win_enumerate(WinInfo* info, int max); // List all windows
|
||||
int win_sendevent(int id, const WinEvent* event); // Send event to a window
|
||||
int win_setscale(int scale); // Set UI scale factor
|
||||
int win_getscale(); // Get UI scale factor
|
||||
int win_setcursor(int id, int cursor); // Set cursor style
|
||||
```
|
||||
|
||||
**`WinCreateResult` struct:**
|
||||
```cpp
|
||||
struct WinCreateResult {
|
||||
int id; // Window ID for subsequent calls
|
||||
uint64_t pixelVa; // Virtual address of shared pixel buffer (uint32_t* ARGB)
|
||||
};
|
||||
```
|
||||
|
||||
**`WinEvent` struct:**
|
||||
```cpp
|
||||
struct WinEvent {
|
||||
int type; // 0=Key, 1=Mouse, 2=Resize, 3=Close
|
||||
union {
|
||||
struct { uint8_t scancode; char ascii; bool pressed, shift, ctrl, alt; } key;
|
||||
struct { int x, y; uint8_t buttons, prev_buttons; int32_t scroll; } mouse;
|
||||
struct { int w, h; } resize;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
### Event Loop Pattern
|
||||
|
||||
```cpp
|
||||
while (true) {
|
||||
Montauk::WinEvent ev;
|
||||
int r = montauk::win_poll(win_id, &ev);
|
||||
if (r < 0) break; // Window closed
|
||||
if (r == 0) {
|
||||
montauk::sleep_ms(16); // No events, idle at ~60fps
|
||||
continue;
|
||||
}
|
||||
switch (ev.type) {
|
||||
case 0: handle_key(ev.key); break;
|
||||
case 1: handle_mouse(ev.mouse); break;
|
||||
case 2: handle_resize(ev.resize); break;
|
||||
case 3: goto done; // Close
|
||||
}
|
||||
render(pixels);
|
||||
montauk::win_present(win_id);
|
||||
}
|
||||
done:
|
||||
montauk::win_destroy(win_id);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Framebuffer
|
||||
|
||||
For direct framebuffer access (fullscreen apps, not typical for windowed apps):
|
||||
|
||||
```cpp
|
||||
void fb_info(FbInfo* info); // Get dimensions and pitch
|
||||
void* fb_map(); // Map framebuffer to user address space
|
||||
```
|
||||
|
||||
**`FbInfo` struct:**
|
||||
```cpp
|
||||
struct FbInfo {
|
||||
uint32_t width, height;
|
||||
uint32_t pitch; // Bytes per row
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Networking
|
||||
|
||||
### DNS and Connectivity
|
||||
|
||||
```cpp
|
||||
int32_t ping(uint32_t ip, uint32_t timeoutMs); // Ping, returns RTT in ms (-1 on timeout)
|
||||
uint32_t resolve(const char* hostname); // DNS lookup, returns IPv4 (0 on failure)
|
||||
void get_netcfg(NetCfg* out); // Get network config
|
||||
int set_netcfg(const NetCfg* cfg); // Set network config
|
||||
```
|
||||
|
||||
### Sockets
|
||||
|
||||
```cpp
|
||||
int socket(int type); // Create socket (0=TCP, 1=UDP)
|
||||
int connect(int fd, uint32_t ip, uint16_t port); // TCP connect
|
||||
int bind(int fd, uint16_t port); // Bind to port
|
||||
int listen(int fd); // Start listening
|
||||
int accept(int fd); // Accept connection (returns new fd)
|
||||
int send(int fd, const void* data, uint32_t len); // Send data (returns bytes sent)
|
||||
int recv(int fd, void* buf, uint32_t maxLen); // Receive data (returns bytes read)
|
||||
int closesocket(int fd); // Close socket
|
||||
```
|
||||
|
||||
### UDP
|
||||
|
||||
```cpp
|
||||
int sendto(int fd, const void* data, uint32_t len,
|
||||
uint32_t destIp, uint16_t destPort);
|
||||
int recvfrom(int fd, void* buf, uint32_t maxLen,
|
||||
uint32_t* srcIp, uint16_t* srcPort);
|
||||
```
|
||||
|
||||
### Example: Plain HTTP GET (Port 80)
|
||||
|
||||
```cpp
|
||||
uint32_t ip = montauk::resolve("example.com");
|
||||
int sock = montauk::socket(0); // TCP
|
||||
montauk::connect(sock, ip, 80);
|
||||
|
||||
const char* req = "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n";
|
||||
montauk::send(sock, req, montauk::slen(req));
|
||||
|
||||
char buf[4096];
|
||||
int n = montauk::recv(sock, buf, sizeof(buf) - 1);
|
||||
buf[n] = 0;
|
||||
|
||||
montauk::closesocket(sock);
|
||||
```
|
||||
|
||||
### TLS / HTTPS Library
|
||||
|
||||
Header: `tls/tls.hpp` — requires linking `libtls.a` and `libbearssl.a` (build with `USE_TLS=1`).
|
||||
|
||||
Provides a high-level `tls::https_fetch()` that handles socket creation, BearSSL TLS 1.2 setup, handshake, request/response exchange, and cleanup in a single call.
|
||||
|
||||
```cpp
|
||||
#include <tls/tls.hpp>
|
||||
|
||||
// Load CA certificates (from 0:/etc/ca-certificates.crt)
|
||||
tls::TrustAnchors tas = tls::load_trust_anchors();
|
||||
|
||||
// Build HTTP request
|
||||
const char* host = "en.wikipedia.org";
|
||||
uint32_t ip = montauk::resolve(host);
|
||||
|
||||
char req[256];
|
||||
// ... build "GET /path HTTP/1.1\r\nHost: ...\r\n\r\n" into req ...
|
||||
int reqLen = montauk::slen(req);
|
||||
|
||||
// Fetch (handles TLS handshake, send, receive, teardown)
|
||||
char resp[32768];
|
||||
int n = tls::https_fetch(host, ip, 443, req, reqLen, tas, resp, sizeof(resp));
|
||||
if (n > 0) {
|
||||
resp[n] = 0;
|
||||
// ... parse HTTP response ...
|
||||
}
|
||||
```
|
||||
|
||||
**API reference:**
|
||||
|
||||
```cpp
|
||||
namespace tls {
|
||||
// Load PEM CA bundle from 0:/etc/ca-certificates.crt
|
||||
TrustAnchors load_trust_anchors();
|
||||
|
||||
// High-level: DNS → socket → TLS → exchange → cleanup
|
||||
int https_fetch(const char* host, uint32_t ip, uint16_t port,
|
||||
const char* request, int reqLen,
|
||||
const TrustAnchors& tas,
|
||||
char* respBuf, int respMax,
|
||||
AbortCheckFn abort_check = nullptr);
|
||||
|
||||
// Lower-level: run TLS exchange on an existing socket + BearSSL engine
|
||||
int tls_exchange(int fd, br_ssl_engine_context* eng,
|
||||
const char* request, int reqLen,
|
||||
char* respBuf, int respMax,
|
||||
AbortCheckFn abort_check = nullptr);
|
||||
|
||||
// Helpers for manual BearSSL usage
|
||||
int tls_send_all(int fd, const unsigned char* data, size_t len);
|
||||
int tls_recv_some(int fd, unsigned char* buf, size_t maxlen);
|
||||
void get_bearssl_time(uint32_t* days, uint32_t* seconds);
|
||||
}
|
||||
```
|
||||
|
||||
The optional `AbortCheckFn` callback (e.g., `bool check_quit()`) lets terminal/GUI apps cancel a fetch in progress (return `true` to abort).
|
||||
|
||||
### HTTP Wrapper (`http/http.hpp`)
|
||||
|
||||
The MontaukAI dev environment includes a higher-level HTTP wrapper built on top of `tls::https_fetch()`. It handles DNS, request building, TLS, and response parsing automatically. See the "Networking and HTTPS" section in `gui-apps.md` for full documentation and examples.
|
||||
|
||||
```cpp
|
||||
#include <http/http.hpp>
|
||||
|
||||
tls::TrustAnchors tas = tls::load_trust_anchors();
|
||||
|
||||
auto resp = http::get("api.example.com", "/v1/data", tas);
|
||||
if (resp.status == 200) { /* resp.body, resp.body_len */ }
|
||||
http::free_response(&resp);
|
||||
|
||||
auto resp2 = http::post("api.example.com", "/v1/submit",
|
||||
"application/json", json, jsonLen, tas);
|
||||
http::free_response(&resp2);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Audio
|
||||
|
||||
```cpp
|
||||
int audio_open(uint32_t sampleRate, uint8_t channels, uint8_t bitsPerSample);
|
||||
int audio_close(int handle);
|
||||
int audio_write(int handle, const void* data, uint32_t size); // Write PCM samples
|
||||
int audio_ctl(int handle, int cmd, int value); // Generic control
|
||||
```
|
||||
|
||||
### Convenience Wrappers
|
||||
|
||||
```cpp
|
||||
int audio_set_volume(int handle, int percent); // 0-100
|
||||
int audio_get_volume(int handle);
|
||||
int audio_pause(int handle);
|
||||
int audio_resume(int handle);
|
||||
int audio_get_pos(int handle); // Playback position
|
||||
int audio_get_output(int handle); // Current output device
|
||||
int audio_bt_status(int handle); // Bluetooth audio status
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Bluetooth
|
||||
|
||||
```cpp
|
||||
int bt_scan(BtScanResult* buf, int maxCount, uint32_t timeoutMs); // Scan for devices
|
||||
int bt_connect(const uint8_t* bdAddr); // Connect
|
||||
int bt_disconnect(const uint8_t* bdAddr); // Disconnect
|
||||
int bt_list(BtDevInfo* buf, int maxCount); // List connected devices
|
||||
int bt_info(BtAdapterInfo* buf); // Adapter info
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Timekeeping
|
||||
|
||||
```cpp
|
||||
uint64_t get_ticks(); // CPU tick counter
|
||||
uint64_t get_milliseconds(); // Milliseconds since boot
|
||||
void gettime(Montauk::DateTime* out); // Wall-clock time
|
||||
```
|
||||
|
||||
**`DateTime` struct:**
|
||||
```cpp
|
||||
struct DateTime {
|
||||
uint16_t year;
|
||||
uint8_t month, day, hour, minute, second;
|
||||
uint8_t weekday;
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## System Information
|
||||
|
||||
```cpp
|
||||
void get_info(SysInfo* info); // CPU, memory, system info
|
||||
void memstats(MemStats* out); // Memory usage statistics
|
||||
int64_t getrandom(void* buf, uint32_t len); // Cryptographic random bytes
|
||||
void reset(); // System reset (noreturn)
|
||||
void shutdown(); // System shutdown (noreturn)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Storage and Disks
|
||||
|
||||
```cpp
|
||||
int partlist(PartInfo* buf, int max); // List GPT partitions
|
||||
int disk_read(int blockDev, uint64_t lba, uint32_t sectorCount, void* buf); // Raw sector read
|
||||
int disk_write(int blockDev, uint64_t lba, uint32_t sectorCount, const void* buf); // Raw sector write
|
||||
int gpt_init(int blockDev); // Initialize GPT
|
||||
int gpt_add(const GptAddParams* params); // Add partition
|
||||
int fs_mount(int partIndex, int driveNum); // Mount filesystem
|
||||
int fs_format(const FsFormatParams* params); // Format filesystem
|
||||
int diskinfo(DiskInfo* buf, int port); // Get disk info
|
||||
int devlist(DevInfo* buf, int max); // List block devices
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Terminal
|
||||
|
||||
For terminal-mode (non-GUI) applications:
|
||||
|
||||
```cpp
|
||||
void termsize(int* cols, int* rows); // Get terminal dimensions
|
||||
void termscale(int scale_x, int scale_y); // Set text scaling
|
||||
void get_termscale(int* scale_x, int* scale_y); // Get text scaling
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Process I/O Redirection
|
||||
|
||||
For launching child processes with redirected I/O (used by the terminal emulator):
|
||||
|
||||
```cpp
|
||||
int spawn_redir(const char* path, const char* args); // Spawn with I/O pipes
|
||||
int childio_read(int childPid, char* buf, int maxLen); // Read child stdout
|
||||
int childio_write(int childPid, const char* data, int len); // Write to child stdin
|
||||
int childio_writekey(int childPid, const Montauk::KeyEvent* key); // Send keystroke to child
|
||||
int childio_settermsz(int childPid, int cols, int rows); // Set child terminal size
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
Header: `montauk/config.h`
|
||||
|
||||
TOML-based configuration stored in `0:/config/`. Provides per-system and per-user config files.
|
||||
|
||||
```cpp
|
||||
toml::Doc config::load(const char* name); // Load 0:/config/<name>.toml
|
||||
int config::save(const char* name, toml::Doc* doc); // Save config (0 = success)
|
||||
toml::Doc config::load_user(const char* username, const char* name); // Per-user config
|
||||
int config::save_user(const char* username, const char* name, toml::Doc* doc);
|
||||
|
||||
void config::set_string(toml::Doc* doc, const char* key, const char* val);
|
||||
void config::set_int(toml::Doc* doc, const char* key, int64_t val);
|
||||
void config::set_bool(toml::Doc* doc, const char* key, bool val);
|
||||
bool config::unset(toml::Doc* doc, const char* key);
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
```cpp
|
||||
auto doc = montauk::config::load("session");
|
||||
const char* user = doc.get_string("session.username", "guest");
|
||||
|
||||
montauk::config::set_string(&doc, "session.theme", "dark");
|
||||
montauk::config::save("session", &doc);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## User Management
|
||||
|
||||
Header: `montauk/user.h`
|
||||
|
||||
User authentication and session management with SHA-256 password hashing.
|
||||
|
||||
```cpp
|
||||
bool user::authenticate(const char* username, const char* password);
|
||||
bool user::create_user(const char* username, const char* display_name,
|
||||
const char* password, const char* role);
|
||||
bool user::delete_user(const char* username);
|
||||
bool user::change_password(const char* username, const char* new_password);
|
||||
|
||||
void user::set_session(const char* username); // Log in
|
||||
void user::clear_session(); // Log out
|
||||
bool user::get_session_username(char* buf, int sz); // Get current user
|
||||
bool user::get_home_dir(char* buf, int sz); // Get user's home directory
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Utility Libraries
|
||||
|
||||
### String Functions (`montauk/string.h`)
|
||||
|
||||
```cpp
|
||||
int slen(const char* s);
|
||||
bool streq(const char* a, const char* b);
|
||||
bool starts_with(const char* str, const char* prefix);
|
||||
void memcpy(void* dst, const void* src, uint64_t n);
|
||||
void memmove(void* dst, const void* src, uint64_t n);
|
||||
void memset(void* dst, int val, uint64_t n);
|
||||
void strcpy(char* dst, const char* src);
|
||||
void strncpy(char* dst, const char* src, int max);
|
||||
```
|
||||
|
||||
### Heap (`montauk/heap.h`)
|
||||
|
||||
```cpp
|
||||
void* malloc(uint64_t size);
|
||||
void mfree(void* ptr);
|
||||
void* realloc(void* ptr, uint64_t size);
|
||||
```
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* link.ld
|
||||
* Linker script for MontaukOS userspace programs
|
||||
* Copyright (c) 2025 Daniel Hammer
|
||||
*
|
||||
* Programs are loaded at a standard user-space address.
|
||||
*/
|
||||
|
||||
OUTPUT_FORMAT(elf64-x86-64)
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x400000;
|
||||
|
||||
.text : {
|
||||
*(.text .text.*)
|
||||
}
|
||||
|
||||
. = ALIGN(4096);
|
||||
|
||||
.rodata : {
|
||||
*(.rodata .rodata.*)
|
||||
}
|
||||
|
||||
. = ALIGN(4096);
|
||||
|
||||
.data : {
|
||||
*(.data .data.*)
|
||||
}
|
||||
|
||||
.bss : {
|
||||
*(.bss .bss.*)
|
||||
*(COMMON)
|
||||
}
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame*)
|
||||
*(.note .note.*)
|
||||
*(.comment*)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* cxxrt.cpp
|
||||
* Minimal C++ runtime support for freestanding MontaukOS apps.
|
||||
* Provides operator new/delete backed by montauk::malloc/mfree.
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <montauk/heap.h>
|
||||
|
||||
void* operator new(size_t size) { return montauk::malloc(size); }
|
||||
void* operator new[](size_t size) { return montauk::malloc(size); }
|
||||
void operator delete(void* ptr) noexcept { montauk::mfree(ptr); }
|
||||
void operator delete[](void* ptr) noexcept { montauk::mfree(ptr); }
|
||||
void operator delete(void* ptr, size_t) noexcept { montauk::mfree(ptr); }
|
||||
void operator delete[](void* ptr, size_t) noexcept { montauk::mfree(ptr); }
|
||||
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* main.cpp
|
||||
* Template standalone GUI app for MontaukOS
|
||||
*
|
||||
* This is a minimal working app that creates a window, renders text,
|
||||
* and handles input events. Use it as a starting point for your app.
|
||||
*/
|
||||
|
||||
#include <montauk/syscall.h>
|
||||
#include <montauk/string.h>
|
||||
#include <montauk/heap.h>
|
||||
#include <gui/gui.hpp>
|
||||
#include <gui/truetype.hpp>
|
||||
|
||||
using namespace gui;
|
||||
|
||||
// ============================================================================
|
||||
// State
|
||||
// ============================================================================
|
||||
|
||||
static TrueTypeFont* g_font;
|
||||
static int g_win_w = 500;
|
||||
static int g_win_h = 400;
|
||||
static int g_click_count = 0;
|
||||
|
||||
// ============================================================================
|
||||
// Drawing helpers
|
||||
// ============================================================================
|
||||
|
||||
static void px_fill(uint32_t* px, int bw, int bh,
|
||||
int x, int y, int w, int h, uint32_t color) {
|
||||
for (int row = y; row < y + h && row < bh; row++)
|
||||
for (int col = x; col < x + w && col < bw; col++)
|
||||
if (row >= 0 && col >= 0)
|
||||
px[row * bw + col] = color;
|
||||
}
|
||||
|
||||
static void px_fill_rounded(uint32_t* px, int bw, int bh,
|
||||
int x, int y, int w, int h, int r, uint32_t color) {
|
||||
for (int row = y; row < y + h && row < bh; row++) {
|
||||
for (int col = x; col < x + w && col < bw; col++) {
|
||||
if (row < 0 || col < 0) continue;
|
||||
int dx = 0, dy = 0;
|
||||
if (col < x + r && row < y + r) { dx = x + r - col; dy = y + r - row; }
|
||||
else if (col >= x+w-r && row < y + r) { dx = col-(x+w-r-1); dy = y + r - row; }
|
||||
else if (col < x + r && row >= y+h-r) { dx = x + r - col; dy = row-(y+h-r-1); }
|
||||
else if (col >= x+w-r && row >= y+h-r) { dx = col-(x+w-r-1); dy = row-(y+h-r-1); }
|
||||
if (dx * dx + dy * dy <= r * r)
|
||||
px[row * bw + col] = color;
|
||||
else if (dx == 0 && dy == 0)
|
||||
px[row * bw + col] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void px_text(uint32_t* px, int bw, int bh,
|
||||
int x, int y, const char* text, Color c, int size) {
|
||||
if (g_font)
|
||||
g_font->draw_to_buffer(px, bw, bh, x, y, text, c, size);
|
||||
}
|
||||
|
||||
static void px_hline(uint32_t* px, int bw, int bh,
|
||||
int x, int y, int w, uint32_t color) {
|
||||
if (y < 0 || y >= bh) return;
|
||||
for (int col = x; col < x + w && col < bw; col++)
|
||||
if (col >= 0) px[y * bw + col] = color;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Rendering
|
||||
// ============================================================================
|
||||
|
||||
static void render(uint32_t* pixels) {
|
||||
// Background
|
||||
px_fill(pixels, g_win_w, g_win_h, 0, 0, g_win_w, g_win_h,
|
||||
Color::from_rgb(0xFF, 0xFF, 0xFF).to_pixel());
|
||||
|
||||
// Toolbar
|
||||
px_fill(pixels, g_win_w, g_win_h, 0, 0, g_win_w, 36,
|
||||
Color::from_rgb(0xF5, 0xF5, 0xF5).to_pixel());
|
||||
px_hline(pixels, g_win_w, g_win_h, 0, 36, g_win_w,
|
||||
Color::from_rgb(0xD0, 0xD0, 0xD0).to_pixel());
|
||||
|
||||
// Title in toolbar
|
||||
px_text(pixels, g_win_w, g_win_h, 12, 10, "My App",
|
||||
Color::from_rgb(0x33, 0x33, 0x33), 18);
|
||||
|
||||
// Content area
|
||||
px_text(pixels, g_win_w, g_win_h, 20, 60, "Hello from MontaukOS!",
|
||||
Color::from_rgb(0x33, 0x33, 0x33), 18);
|
||||
|
||||
// Click counter
|
||||
char buf[64];
|
||||
const char* prefix = "Clicks: ";
|
||||
int i = 0;
|
||||
while (prefix[i]) { buf[i] = prefix[i]; i++; }
|
||||
int n = g_click_count;
|
||||
if (n == 0) { buf[i++] = '0'; }
|
||||
else {
|
||||
char tmp[16]; int ti = 0;
|
||||
while (n > 0) { tmp[ti++] = '0' + (n % 10); n /= 10; }
|
||||
for (int j = ti - 1; j >= 0; j--) buf[i++] = tmp[j];
|
||||
}
|
||||
buf[i] = 0;
|
||||
|
||||
px_text(pixels, g_win_w, g_win_h, 20, 90, buf,
|
||||
Color::from_rgb(0x66, 0x66, 0x66), 16);
|
||||
|
||||
// A styled button
|
||||
px_fill_rounded(pixels, g_win_w, g_win_h,
|
||||
20, 130, 120, 36, 4,
|
||||
Color::from_rgb(0x36, 0x7B, 0xF0).to_pixel());
|
||||
px_text(pixels, g_win_w, g_win_h, 42, 139, "Click me",
|
||||
Color::from_rgb(0xFF, 0xFF, 0xFF), 16);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Entry point
|
||||
// ============================================================================
|
||||
|
||||
extern "C" void _start() {
|
||||
// Load font
|
||||
g_font = new TrueTypeFont();
|
||||
if (!g_font->init("0:/fonts/Roboto-Medium.ttf"))
|
||||
g_font = nullptr;
|
||||
|
||||
// Create window
|
||||
Montauk::WinCreateResult wres;
|
||||
montauk::win_create("My App", g_win_w, g_win_h, &wres);
|
||||
int win_id = wres.id;
|
||||
uint32_t* pixels = (uint32_t*)(uintptr_t)wres.pixelVa;
|
||||
|
||||
// Initial render
|
||||
render(pixels);
|
||||
montauk::win_present(win_id);
|
||||
|
||||
// Event loop
|
||||
while (true) {
|
||||
Montauk::WinEvent ev;
|
||||
int r = montauk::win_poll(win_id, &ev);
|
||||
|
||||
if (r < 0) break;
|
||||
if (r == 0) {
|
||||
montauk::sleep_ms(16);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (ev.type) {
|
||||
case 0: // Keyboard
|
||||
if (ev.key.pressed && ev.key.scancode == 0x01)
|
||||
goto done; // ESC to close
|
||||
break;
|
||||
|
||||
case 1: // Mouse
|
||||
if ((ev.mouse.buttons & 0x01) && !(ev.mouse.prev_buttons & 0x01)) {
|
||||
// Left click — check if inside button
|
||||
int mx = ev.mouse.x, my = ev.mouse.y;
|
||||
if (mx >= 20 && mx < 140 && my >= 130 && my < 166)
|
||||
g_click_count++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // Resize
|
||||
g_win_w = ev.resize.w;
|
||||
g_win_h = ev.resize.h;
|
||||
pixels = (uint32_t*)(uintptr_t)montauk::win_resize(win_id, g_win_w, g_win_h);
|
||||
break;
|
||||
|
||||
case 3: // Close
|
||||
goto done;
|
||||
}
|
||||
|
||||
render(pixels);
|
||||
montauk::win_present(win_id);
|
||||
}
|
||||
|
||||
done:
|
||||
montauk::win_destroy(win_id);
|
||||
montauk::exit(0);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* stb_truetype_impl.cpp
|
||||
* Single compilation unit for stb_truetype in MontaukOS freestanding environment
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <montauk/heap.h>
|
||||
#include <montauk/string.h>
|
||||
#include <gui/stb_math.h>
|
||||
|
||||
#define STBTT_ifloor(x) ((int) stb_floor(x))
|
||||
#define STBTT_iceil(x) ((int) stb_ceil(x))
|
||||
#define STBTT_sqrt(x) stb_sqrt(x)
|
||||
#define STBTT_pow(x,y) stb_pow(x,y)
|
||||
#define STBTT_fmod(x,y) stb_fmod(x,y)
|
||||
#define STBTT_cos(x) stb_cos(x)
|
||||
#define STBTT_acos(x) stb_acos(x)
|
||||
#define STBTT_fabs(x) stb_fabs(x)
|
||||
|
||||
#define STBTT_malloc(x,u) ((void)(u), montauk::malloc(x))
|
||||
#define STBTT_free(x,u) ((void)(u), montauk::mfree(x))
|
||||
|
||||
#define STBTT_memcpy(d,s,n) montauk::memcpy(d,s,n)
|
||||
#define STBTT_memset(d,v,n) montauk::memset(d,v,n)
|
||||
|
||||
#define STBTT_strlen(x) montauk::slen(x)
|
||||
|
||||
#define STBTT_assert(x) ((void)(x))
|
||||
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#include <gui/stb_truetype.h>
|
||||
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
* Syscall.hpp
|
||||
* MontaukOS syscall definitions for userspace programs
|
||||
* Copyright (c) 2025 Daniel Hammer
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
namespace Montauk {
|
||||
|
||||
// Syscall numbers
|
||||
static constexpr uint64_t SYS_EXIT = 0;
|
||||
static constexpr uint64_t SYS_YIELD = 1;
|
||||
static constexpr uint64_t SYS_SLEEP_MS = 2;
|
||||
static constexpr uint64_t SYS_GETPID = 3;
|
||||
static constexpr uint64_t SYS_PRINT = 4;
|
||||
static constexpr uint64_t SYS_PUTCHAR = 5;
|
||||
static constexpr uint64_t SYS_OPEN = 6;
|
||||
static constexpr uint64_t SYS_READ = 7;
|
||||
static constexpr uint64_t SYS_GETSIZE = 8;
|
||||
static constexpr uint64_t SYS_CLOSE = 9;
|
||||
static constexpr uint64_t SYS_READDIR = 10;
|
||||
static constexpr uint64_t SYS_ALLOC = 11;
|
||||
static constexpr uint64_t SYS_FREE = 12;
|
||||
static constexpr uint64_t SYS_GETTICKS = 13;
|
||||
static constexpr uint64_t SYS_GETMILLISECONDS = 14;
|
||||
static constexpr uint64_t SYS_GETINFO = 15;
|
||||
static constexpr uint64_t SYS_ISKEYAVAILABLE = 16;
|
||||
static constexpr uint64_t SYS_GETKEY = 17;
|
||||
static constexpr uint64_t SYS_GETCHAR = 18;
|
||||
static constexpr uint64_t SYS_PING = 19;
|
||||
static constexpr uint64_t SYS_SPAWN = 20;
|
||||
static constexpr uint64_t SYS_FBINFO = 21;
|
||||
static constexpr uint64_t SYS_FBMAP = 22;
|
||||
static constexpr uint64_t SYS_WAITPID = 23;
|
||||
static constexpr uint64_t SYS_TERMSIZE = 24;
|
||||
static constexpr uint64_t SYS_GETARGS = 25;
|
||||
static constexpr uint64_t SYS_RESET = 26;
|
||||
static constexpr uint64_t SYS_SHUTDOWN = 27;
|
||||
static constexpr uint64_t SYS_GETTIME = 28;
|
||||
static constexpr uint64_t SYS_SOCKET = 29;
|
||||
static constexpr uint64_t SYS_CONNECT = 30;
|
||||
static constexpr uint64_t SYS_BIND = 31;
|
||||
static constexpr uint64_t SYS_LISTEN = 32;
|
||||
static constexpr uint64_t SYS_ACCEPT = 33;
|
||||
static constexpr uint64_t SYS_SEND = 34;
|
||||
static constexpr uint64_t SYS_RECV = 35;
|
||||
static constexpr uint64_t SYS_CLOSESOCK = 36;
|
||||
static constexpr uint64_t SYS_GETNETCFG = 37;
|
||||
static constexpr uint64_t SYS_SETNETCFG = 38;
|
||||
static constexpr uint64_t SYS_SENDTO = 39;
|
||||
static constexpr uint64_t SYS_RECVFROM = 40;
|
||||
static constexpr uint64_t SYS_FWRITE = 41;
|
||||
static constexpr uint64_t SYS_FCREATE = 42;
|
||||
static constexpr uint64_t SYS_FDELETE = 77;
|
||||
static constexpr uint64_t SYS_FMKDIR = 78;
|
||||
static constexpr uint64_t SYS_DRIVELIST = 79;
|
||||
static constexpr uint64_t SYS_TERMSCALE = 43;
|
||||
static constexpr uint64_t SYS_RESOLVE = 44;
|
||||
static constexpr uint64_t SYS_GETRANDOM = 45;
|
||||
static constexpr uint64_t SYS_KLOG = 46;
|
||||
static constexpr uint64_t SYS_MOUSESTATE = 47;
|
||||
static constexpr uint64_t SYS_SETMOUSEBOUNDS = 48;
|
||||
static constexpr uint64_t SYS_SPAWN_REDIR = 49;
|
||||
static constexpr uint64_t SYS_CHILDIO_READ = 50;
|
||||
static constexpr uint64_t SYS_CHILDIO_WRITE = 51;
|
||||
static constexpr uint64_t SYS_CHILDIO_WRITEKEY = 52;
|
||||
static constexpr uint64_t SYS_CHILDIO_SETTERMSZ = 53;
|
||||
|
||||
// Window server syscalls
|
||||
static constexpr uint64_t SYS_WINCREATE = 54;
|
||||
static constexpr uint64_t SYS_WINDESTROY = 55;
|
||||
static constexpr uint64_t SYS_WINPRESENT = 56;
|
||||
static constexpr uint64_t SYS_WINPOLL = 57;
|
||||
static constexpr uint64_t SYS_WINENUM = 58;
|
||||
static constexpr uint64_t SYS_WINMAP = 59;
|
||||
static constexpr uint64_t SYS_WINSENDEVENT = 60;
|
||||
static constexpr uint64_t SYS_WINRESIZE = 64;
|
||||
static constexpr uint64_t SYS_WINSETSCALE = 65;
|
||||
static constexpr uint64_t SYS_WINGETSCALE = 66;
|
||||
static constexpr uint64_t SYS_WINSETCURSOR = 68;
|
||||
|
||||
// Process management syscalls
|
||||
static constexpr uint64_t SYS_PROCLIST = 61;
|
||||
static constexpr uint64_t SYS_KILL = 62;
|
||||
static constexpr uint64_t SYS_DEVLIST = 63;
|
||||
static constexpr uint64_t SYS_DISKINFO = 69;
|
||||
|
||||
// Kernel introspection syscalls
|
||||
static constexpr uint64_t SYS_MEMSTATS = 67;
|
||||
|
||||
// Storage / partition syscalls
|
||||
static constexpr uint64_t SYS_PARTLIST = 70;
|
||||
static constexpr uint64_t SYS_DISKREAD = 71;
|
||||
static constexpr uint64_t SYS_DISKWRITE = 72;
|
||||
static constexpr uint64_t SYS_GPTINIT = 73;
|
||||
static constexpr uint64_t SYS_GPTADD = 74;
|
||||
static constexpr uint64_t SYS_FSMOUNT = 75;
|
||||
static constexpr uint64_t SYS_FSFORMAT = 76;
|
||||
|
||||
// Audio syscalls
|
||||
static constexpr uint64_t SYS_AUDIOOPEN = 80;
|
||||
static constexpr uint64_t SYS_AUDIOCLOSE = 81;
|
||||
static constexpr uint64_t SYS_AUDIOWRITE = 82;
|
||||
static constexpr uint64_t SYS_AUDIOCTL = 83;
|
||||
|
||||
// Bluetooth syscalls
|
||||
static constexpr uint64_t SYS_BTSCAN = 84;
|
||||
static constexpr uint64_t SYS_BTCONNECT = 85;
|
||||
static constexpr uint64_t SYS_BTDISCONNECT = 86;
|
||||
static constexpr uint64_t SYS_BTLIST = 87;
|
||||
static constexpr uint64_t SYS_BTINFO = 88;
|
||||
|
||||
// Audio control commands (for SYS_AUDIOCTL)
|
||||
static constexpr int AUDIO_CTL_SET_VOLUME = 0;
|
||||
static constexpr int AUDIO_CTL_GET_VOLUME = 1;
|
||||
static constexpr int AUDIO_CTL_GET_POS = 2;
|
||||
static constexpr int AUDIO_CTL_PAUSE = 3;
|
||||
static constexpr int AUDIO_CTL_GET_OUTPUT = 4; // 0=HDA, 1=Bluetooth
|
||||
static constexpr int AUDIO_CTL_SET_OUTPUT = 5; // Switch audio output
|
||||
static constexpr int AUDIO_CTL_BT_STATUS = 6; // Get Bluetooth connection status
|
||||
|
||||
static constexpr int SOCK_TCP = 1;
|
||||
static constexpr int SOCK_UDP = 2;
|
||||
|
||||
struct NetCfg {
|
||||
uint32_t ipAddress; // network byte order
|
||||
uint32_t subnetMask; // network byte order
|
||||
uint32_t gateway; // network byte order
|
||||
uint8_t macAddress[6];
|
||||
uint8_t _pad[2];
|
||||
uint32_t dnsServer; // network byte order
|
||||
};
|
||||
|
||||
struct DateTime {
|
||||
uint16_t Year;
|
||||
uint8_t Month;
|
||||
uint8_t Day;
|
||||
uint8_t Hour;
|
||||
uint8_t Minute;
|
||||
uint8_t Second;
|
||||
};
|
||||
|
||||
struct FbInfo {
|
||||
uint64_t width;
|
||||
uint64_t height;
|
||||
uint64_t pitch; // bytes per scanline
|
||||
uint64_t bpp; // bits per pixel (32)
|
||||
uint64_t userAddr; // filled by SYS_FBMAP (0 until mapped)
|
||||
};
|
||||
|
||||
struct SysInfo {
|
||||
char osName[32];
|
||||
char osVersion[32];
|
||||
uint32_t apiVersion;
|
||||
uint32_t maxProcesses;
|
||||
};
|
||||
|
||||
struct KeyEvent {
|
||||
uint8_t scancode;
|
||||
char ascii;
|
||||
bool pressed;
|
||||
bool shift;
|
||||
bool ctrl;
|
||||
bool alt;
|
||||
};
|
||||
|
||||
struct MouseState {
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
int32_t scrollDelta;
|
||||
uint8_t buttons;
|
||||
};
|
||||
|
||||
// Window server shared types
|
||||
struct WinEvent {
|
||||
uint8_t type; // 0=key, 1=mouse, 2=resize, 3=close, 4=scale
|
||||
uint8_t _pad[3];
|
||||
union {
|
||||
KeyEvent key;
|
||||
struct { int32_t x, y, scroll; uint8_t buttons, prev_buttons; } mouse;
|
||||
struct { int32_t w, h; } resize;
|
||||
struct { int32_t scale; } scale;
|
||||
};
|
||||
};
|
||||
|
||||
struct WinInfo {
|
||||
int32_t id;
|
||||
int32_t ownerPid;
|
||||
char title[64];
|
||||
int32_t width, height;
|
||||
uint8_t dirty;
|
||||
uint8_t cursor; // 0=arrow, 1=resize_h, 2=resize_v
|
||||
uint8_t _pad2[2];
|
||||
};
|
||||
|
||||
struct WinCreateResult {
|
||||
int32_t id; // -1 on failure
|
||||
uint32_t _pad;
|
||||
uint64_t pixelVa; // VA of pixel buffer in caller's address space
|
||||
};
|
||||
|
||||
struct DevInfo {
|
||||
uint8_t category; // 0=CPU, 1=Interrupt, 2=Timer, 3=Input, 4=USB, 5=Network, 6=Display, 7=Storage, 8=PCI
|
||||
uint8_t _pad[3];
|
||||
char name[48];
|
||||
char detail[48];
|
||||
};
|
||||
|
||||
struct DiskInfo {
|
||||
uint8_t port; // block device index
|
||||
uint8_t type; // 0=none, 1=SATA, 2=SATAPI, 3=NVMe
|
||||
uint8_t sataGen; // SATA gen (1/2/3)
|
||||
uint8_t _pad0;
|
||||
uint64_t sectorCount; // Total user-addressable sectors
|
||||
uint16_t sectorSizeLog; // Logical sector size (bytes)
|
||||
uint16_t sectorSizePhys; // Physical sector size (bytes)
|
||||
uint16_t rpm; // 0=unknown, 1=SSD, else RPM
|
||||
uint16_t ncqDepth; // 0 if no NCQ
|
||||
uint8_t supportsLba48;
|
||||
uint8_t supportsNcq;
|
||||
uint8_t supportsTrim;
|
||||
uint8_t supportsSmart;
|
||||
uint8_t supportsWriteCache;
|
||||
uint8_t supportsReadAhead;
|
||||
uint8_t _pad1[2];
|
||||
char model[41];
|
||||
char serial[21];
|
||||
char firmware[9];
|
||||
char _pad2[1];
|
||||
};
|
||||
|
||||
struct PartGuid {
|
||||
uint32_t Data1;
|
||||
uint16_t Data2;
|
||||
uint16_t Data3;
|
||||
uint8_t Data4[8];
|
||||
};
|
||||
|
||||
struct PartInfo {
|
||||
int32_t blockDev; // block device index
|
||||
uint32_t _pad0;
|
||||
uint64_t startLba;
|
||||
uint64_t endLba;
|
||||
uint64_t sectorCount;
|
||||
PartGuid typeGuid;
|
||||
PartGuid uniqueGuid;
|
||||
uint64_t attributes;
|
||||
char name[72]; // ASCII partition name
|
||||
char typeName[24]; // human-readable type name
|
||||
};
|
||||
|
||||
struct GptAddParams {
|
||||
int32_t blockDev;
|
||||
uint32_t _pad0;
|
||||
uint64_t startLba; // 0 = auto (fill largest free region)
|
||||
uint64_t endLba; // 0 = auto
|
||||
PartGuid typeGuid;
|
||||
char name[72];
|
||||
};
|
||||
|
||||
// Filesystem type IDs for SYS_FSFORMAT
|
||||
static constexpr int FS_TYPE_FAT32 = 1;
|
||||
static constexpr int FS_TYPE_EXT2 = 2;
|
||||
|
||||
struct FsFormatParams {
|
||||
int32_t partIndex; // global partition index
|
||||
int32_t fsType; // FS_TYPE_FAT32, etc.
|
||||
char label[32]; // volume label
|
||||
};
|
||||
|
||||
// Bluetooth scan result (returned by SYS_BTSCAN)
|
||||
struct BtScanResult {
|
||||
uint8_t bdAddr[6];
|
||||
uint8_t _pad[2];
|
||||
uint32_t classOfDevice;
|
||||
int8_t rssi;
|
||||
uint8_t _pad2[3];
|
||||
char name[64];
|
||||
};
|
||||
|
||||
// Bluetooth connected device info (returned by SYS_BTLIST)
|
||||
struct BtDevInfo {
|
||||
uint8_t bdAddr[6];
|
||||
uint8_t connected;
|
||||
uint8_t encrypted;
|
||||
uint16_t handle;
|
||||
uint8_t linkType;
|
||||
uint8_t _pad;
|
||||
};
|
||||
|
||||
// Bluetooth adapter info (returned by SYS_BTINFO)
|
||||
struct BtAdapterInfo {
|
||||
uint8_t bdAddr[6];
|
||||
uint8_t initialized;
|
||||
uint8_t scanning;
|
||||
char name[64];
|
||||
};
|
||||
|
||||
struct ProcInfo {
|
||||
int32_t pid;
|
||||
int32_t parentPid;
|
||||
uint8_t state; // 0=Free, 1=Ready, 2=Running, 3=Terminated
|
||||
uint8_t _pad[3];
|
||||
char name[64];
|
||||
uint64_t heapUsed; // heapNext - UserHeapBase (bytes)
|
||||
};
|
||||
|
||||
struct MemStats {
|
||||
uint64_t totalBytes;
|
||||
uint64_t freeBytes;
|
||||
uint64_t usedBytes;
|
||||
uint64_t pageSize;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/* Copyright (C) 2012-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _X86GPRINTRIN_H_INCLUDED
|
||||
# error "Never use <adxintrin.h> directly; include <x86gprintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _ADXINTRIN_H_INCLUDED
|
||||
#define _ADXINTRIN_H_INCLUDED
|
||||
|
||||
extern __inline unsigned char
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_subborrow_u32 (unsigned char __CF, unsigned int __X,
|
||||
unsigned int __Y, unsigned int *__P)
|
||||
{
|
||||
return __builtin_ia32_sbb_u32 (__CF, __X, __Y, __P);
|
||||
}
|
||||
|
||||
extern __inline unsigned char
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_addcarry_u32 (unsigned char __CF, unsigned int __X,
|
||||
unsigned int __Y, unsigned int *__P)
|
||||
{
|
||||
return __builtin_ia32_addcarryx_u32 (__CF, __X, __Y, __P);
|
||||
}
|
||||
|
||||
extern __inline unsigned char
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_addcarryx_u32 (unsigned char __CF, unsigned int __X,
|
||||
unsigned int __Y, unsigned int *__P)
|
||||
{
|
||||
return __builtin_ia32_addcarryx_u32 (__CF, __X, __Y, __P);
|
||||
}
|
||||
|
||||
#ifdef __x86_64__
|
||||
extern __inline unsigned char
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_subborrow_u64 (unsigned char __CF, unsigned long long __X,
|
||||
unsigned long long __Y, unsigned long long *__P)
|
||||
{
|
||||
return __builtin_ia32_sbb_u64 (__CF, __X, __Y, __P);
|
||||
}
|
||||
|
||||
extern __inline unsigned char
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_addcarry_u64 (unsigned char __CF, unsigned long long __X,
|
||||
unsigned long long __Y, unsigned long long *__P)
|
||||
{
|
||||
return __builtin_ia32_addcarryx_u64 (__CF, __X, __Y, __P);
|
||||
}
|
||||
|
||||
extern __inline unsigned char
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_addcarryx_u64 (unsigned char __CF, unsigned long long __X,
|
||||
unsigned long long __Y, unsigned long long *__P)
|
||||
{
|
||||
return __builtin_ia32_addcarryx_u64 (__CF, __X, __Y, __P);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ADXINTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,94 @@
|
||||
// <algorithm> -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2024 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1994
|
||||
* Hewlett-Packard Company
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Hewlett-Packard Company makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1996,1997
|
||||
* Silicon Graphics Computer Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Silicon Graphics makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
/** @file include/algorithm
|
||||
* This is a Standard C++ Library header.
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_ALGORITHM
|
||||
#define _GLIBCXX_ALGORITHM 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include <bits/stl_algobase.h>
|
||||
#include <bits/stl_algo.h>
|
||||
#if __cplusplus > 201703L
|
||||
# include <bits/ranges_algo.h>
|
||||
#endif
|
||||
|
||||
#define __glibcxx_want_clamp
|
||||
#define __glibcxx_want_constexpr_algorithms
|
||||
#define __glibcxx_want_freestanding_algorithm
|
||||
#define __glibcxx_want_parallel_algorithm
|
||||
#define __glibcxx_want_ranges_contains
|
||||
#define __glibcxx_want_ranges_find_last
|
||||
#define __glibcxx_want_ranges_fold
|
||||
#define __glibcxx_want_robust_nonmodifying_seq_ops
|
||||
#define __glibcxx_want_sample
|
||||
#define __glibcxx_want_shift
|
||||
#include <bits/version.h>
|
||||
|
||||
#if __cpp_lib_parallel_algorithm // C++ >= 17 && HOSTED
|
||||
// Parallel STL algorithms
|
||||
# if _PSTL_EXECUTION_POLICIES_DEFINED
|
||||
// If <execution> has already been included, pull in implementations
|
||||
# include <pstl/glue_algorithm_impl.h>
|
||||
# else
|
||||
// Otherwise just pull in forward declarations
|
||||
# include <pstl/glue_algorithm_defs.h>
|
||||
# define _PSTL_ALGORITHM_FORWARD_DECLARED 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef _GLIBCXX_PARALLEL
|
||||
# include <parallel/algorithm>
|
||||
#endif
|
||||
|
||||
#endif /* _GLIBCXX_ALGORITHM */
|
||||
@@ -0,0 +1,93 @@
|
||||
/* Copyright (C) 2007-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Implemented from the specification included in the AMD Programmers
|
||||
Manual Update, version 2.x */
|
||||
|
||||
#ifndef _AMMINTRIN_H_INCLUDED
|
||||
#define _AMMINTRIN_H_INCLUDED
|
||||
|
||||
/* We need definitions from the SSE3, SSE2 and SSE header files*/
|
||||
#include <pmmintrin.h>
|
||||
|
||||
#ifndef __SSE4A__
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("sse4a")
|
||||
#define __DISABLE_SSE4A__
|
||||
#endif /* __SSE4A__ */
|
||||
|
||||
extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_stream_sd (double * __P, __m128d __Y)
|
||||
{
|
||||
__builtin_ia32_movntsd (__P, (__v2df) __Y);
|
||||
}
|
||||
|
||||
extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_stream_ss (float * __P, __m128 __Y)
|
||||
{
|
||||
__builtin_ia32_movntss (__P, (__v4sf) __Y);
|
||||
}
|
||||
|
||||
extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_extract_si64 (__m128i __X, __m128i __Y)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_extrq ((__v2di) __X, (__v16qi) __Y);
|
||||
}
|
||||
|
||||
#ifdef __OPTIMIZE__
|
||||
extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_extracti_si64 (__m128i __X, unsigned const int __I, unsigned const int __L)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_extrqi ((__v2di) __X, __I, __L);
|
||||
}
|
||||
#else
|
||||
#define _mm_extracti_si64(X, I, L) \
|
||||
((__m128i) __builtin_ia32_extrqi ((__v2di)(__m128i)(X), \
|
||||
(unsigned int)(I), (unsigned int)(L)))
|
||||
#endif
|
||||
|
||||
extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_insert_si64 (__m128i __X,__m128i __Y)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_insertq ((__v2di)__X, (__v2di)__Y);
|
||||
}
|
||||
|
||||
#ifdef __OPTIMIZE__
|
||||
extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_inserti_si64(__m128i __X, __m128i __Y, unsigned const int __I, unsigned const int __L)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_insertqi ((__v2di)__X, (__v2di)__Y, __I, __L);
|
||||
}
|
||||
#else
|
||||
#define _mm_inserti_si64(X, Y, I, L) \
|
||||
((__m128i) __builtin_ia32_insertqi ((__v2di)(__m128i)(X), \
|
||||
(__v2di)(__m128i)(Y), \
|
||||
(unsigned int)(I), (unsigned int)(L)))
|
||||
#endif
|
||||
|
||||
#ifdef __DISABLE_SSE4A__
|
||||
#undef __DISABLE_SSE4A__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_SSE4A__ */
|
||||
|
||||
#endif /* _AMMINTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,52 @@
|
||||
/* Copyright (C) 2020-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#if !defined _IMMINTRIN_H_INCLUDED
|
||||
#error "Never use <amxbf16intrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AMXBF16INTRIN_H_INCLUDED
|
||||
#define _AMXBF16INTRIN_H_INCLUDED
|
||||
|
||||
#if !defined(__AMX_BF16__)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("amx-bf16")
|
||||
#define __DISABLE_AMX_BF16__
|
||||
#endif /* __AMX_BF16__ */
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#define _tile_dpbf16ps_internal(dst,src1,src2) \
|
||||
__asm__ volatile\
|
||||
("{tdpbf16ps\t%%tmm"#src2", %%tmm"#src1", %%tmm"#dst"|tdpbf16ps\t%%tmm"#dst", %%tmm"#src1", %%tmm"#src2"}" ::)
|
||||
|
||||
#define _tile_dpbf16ps(dst,src1,src2) \
|
||||
_tile_dpbf16ps_internal (dst, src1, src2)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __DISABLE_AMX_BF16__
|
||||
#undef __DISABLE_AMX_BF16__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AMX_BF16__ */
|
||||
|
||||
#endif /* _AMXBF16INTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,59 @@
|
||||
/* Copyright (C) 2023-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#if !defined _IMMINTRIN_H_INCLUDED
|
||||
#error "Never use <amxcomplexintrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AMXCOMPLEXINTRIN_H_INCLUDED
|
||||
#define _AMXCOMPLEXINTRIN_H_INCLUDED
|
||||
|
||||
#if !defined(__AMX_COMPLEX__)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("amx-complex")
|
||||
#define __DISABLE_AMX_COMPLEX__
|
||||
#endif /* __AMX_COMPLEX__ */
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#define _tile_cmmimfp16ps_internal(src1_dst,src2,src3) \
|
||||
__asm__ volatile\
|
||||
("{tcmmimfp16ps\t%%tmm"#src3", %%tmm"#src2", %%tmm"#src1_dst"|tcmmimfp16ps\t%%tmm"#src1_dst", %%tmm"#src2", %%tmm"#src3"}" ::)
|
||||
|
||||
#define _tile_cmmrlfp16ps_internal(src1_dst,src2,src3) \
|
||||
__asm__ volatile\
|
||||
("{tcmmrlfp16ps\t%%tmm"#src3", %%tmm"#src2", %%tmm"#src1_dst"|tcmmrlfp16ps\t%%tmm"#src1_dst", %%tmm"#src2", %%tmm"#src3"}" ::)
|
||||
|
||||
#define _tile_cmmimfp16ps(src1_dst,src2,src3) \
|
||||
_tile_cmmimfp16ps_internal (src1_dst, src2, src3)
|
||||
|
||||
#define _tile_cmmrlfp16ps(src1_dst,src2,src3) \
|
||||
_tile_cmmrlfp16ps_internal (src1_dst, src2, src3)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __DISABLE_AMX_COMPLEX__
|
||||
#undef __DISABLE_AMX_COMPLEX__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AMX_COMPLEX__ */
|
||||
|
||||
#endif /* _AMXCOMPLEXINTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,46 @@
|
||||
/* Copyright (C) 2020-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#if !defined _IMMINTRIN_H_INCLUDED
|
||||
#error "Never use <amxfp16intrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AMXFP16INTRIN_H_INCLUDED
|
||||
#define _AMXFP16INTRIN_H_INCLUDED
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#define _tile_dpfp16ps_internal(dst,src1,src2) \
|
||||
__asm__ volatile \
|
||||
("{tdpfp16ps\t%%tmm"#src2", %%tmm"#src1", %%tmm"#dst"|tdpfp16ps\t%%tmm"#dst", %%tmm"#src1", %%tmm"#src2"}" ::)
|
||||
|
||||
#define _tile_dpfp16ps(dst,src1,src2) \
|
||||
_tile_dpfp16ps_internal (dst,src1,src2)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __DISABLE_AMX_FP16__
|
||||
#undef __DISABLE_AMX_FP16__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AMX_FP16__ */
|
||||
|
||||
#endif /* _AMXFP16INTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,61 @@
|
||||
/* Copyright (C) 2020-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#if !defined _IMMINTRIN_H_INCLUDED
|
||||
#error "Never use <amxint8intrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AMXINT8INTRIN_H_INCLUDED
|
||||
#define _AMXINT8INTRIN_H_INCLUDED
|
||||
|
||||
#if !defined(__AMX_INT8__)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("amx-int8")
|
||||
#define __DISABLE_AMX_INT8__
|
||||
#endif /* __AMX_INT8__ */
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#define _tile_int8_dp_internal(name,dst,src1,src2) \
|
||||
__asm__ volatile \
|
||||
("{"#name"\t%%tmm"#src2", %%tmm"#src1", %%tmm"#dst"|"#name"\t%%tmm"#dst", %%tmm"#src1", %%tmm"#src2"}" ::)
|
||||
|
||||
#define _tile_dpbssd(dst,src1,src2) \
|
||||
_tile_int8_dp_internal (tdpbssd, dst, src1, src2)
|
||||
|
||||
#define _tile_dpbsud(dst,src1,src2) \
|
||||
_tile_int8_dp_internal (tdpbsud, dst, src1, src2)
|
||||
|
||||
#define _tile_dpbusd(dst,src1,src2) \
|
||||
_tile_int8_dp_internal (tdpbusd, dst, src1, src2)
|
||||
|
||||
#define _tile_dpbuud(dst,src1,src2) \
|
||||
_tile_int8_dp_internal (tdpbuud, dst, src1, src2)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __DISABLE_AMX_INT8__
|
||||
#undef __DISABLE_AMX_INT8__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AMX_INT8__ */
|
||||
|
||||
#endif /* _AMXINT8INTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,98 @@
|
||||
/* Copyright (C) 2020-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#if !defined _IMMINTRIN_H_INCLUDED
|
||||
#error "Never use <amxtileintrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AMXTILEINTRIN_H_INCLUDED
|
||||
#define _AMXTILEINTRIN_H_INCLUDED
|
||||
|
||||
#if !defined(__AMX_TILE__)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("amx-tile")
|
||||
#define __DISABLE_AMX_TILE__
|
||||
#endif /* __AMX_TILE__ */
|
||||
|
||||
#if defined(__x86_64__)
|
||||
extern __inline void
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_tile_loadconfig (const void *__config)
|
||||
{
|
||||
__builtin_ia32_ldtilecfg (__config);
|
||||
}
|
||||
|
||||
extern __inline void
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_tile_storeconfig (void *__config)
|
||||
{
|
||||
__builtin_ia32_sttilecfg (__config);
|
||||
}
|
||||
|
||||
extern __inline void
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_tile_release (void)
|
||||
{
|
||||
__asm__ volatile ("tilerelease" ::);
|
||||
}
|
||||
|
||||
#define _tile_loadd(dst,base,stride) \
|
||||
_tile_loadd_internal (dst, base, stride)
|
||||
|
||||
#define _tile_loadd_internal(dst,base,stride) \
|
||||
__asm__ volatile \
|
||||
("{tileloadd\t(%0,%1,1), %%tmm"#dst"|tileloadd\t%%tmm"#dst", [%0+%1*1]}" \
|
||||
:: "r" ((const void*) (base)), "r" ((__PTRDIFF_TYPE__) (stride)))
|
||||
|
||||
#define _tile_stream_loadd(dst,base,stride) \
|
||||
_tile_stream_loadd_internal (dst, base, stride)
|
||||
|
||||
#define _tile_stream_loadd_internal(dst,base,stride) \
|
||||
__asm__ volatile \
|
||||
("{tileloaddt1\t(%0,%1,1), %%tmm"#dst"|tileloaddt1\t%%tmm"#dst", [%0+%1*1]}" \
|
||||
:: "r" ((const void*) (base)), "r" ((__PTRDIFF_TYPE__) (stride)))
|
||||
|
||||
#define _tile_stored(dst,base,stride) \
|
||||
_tile_stored_internal (dst, base, stride)
|
||||
|
||||
#define _tile_stored_internal(src,base,stride) \
|
||||
__asm__ volatile \
|
||||
("{tilestored\t%%tmm"#src", (%0,%1,1)|tilestored\t[%0+%1*1], %%tmm"#src"}" \
|
||||
:: "r" ((void*) (base)), "r" ((__PTRDIFF_TYPE__) (stride)) \
|
||||
: "memory")
|
||||
|
||||
#define _tile_zero(dst) \
|
||||
_tile_zero_internal (dst)
|
||||
|
||||
#define _tile_zero_internal(dst) \
|
||||
__asm__ volatile \
|
||||
("tilezero\t%%tmm"#dst ::)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __DISABLE_AMX_TILE__
|
||||
#undef __DISABLE_AMX_TILE__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AMX_TILE__ */
|
||||
|
||||
#endif /* _AMXTILEINTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,519 @@
|
||||
// <array> -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007-2024 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file include/array
|
||||
* This is a Standard C++ Library header.
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_ARRAY
|
||||
#define _GLIBCXX_ARRAY 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#if __cplusplus < 201103L
|
||||
# include <bits/c++0x_warning.h>
|
||||
#else
|
||||
|
||||
#include <compare>
|
||||
#include <initializer_list>
|
||||
|
||||
#include <type_traits>
|
||||
#include <bits/functexcept.h>
|
||||
#include <bits/stl_algobase.h>
|
||||
#include <bits/range_access.h> // std::begin, std::end etc.
|
||||
#include <bits/utility.h> // std::index_sequence, std::tuple_size
|
||||
#include <debug/assertions.h>
|
||||
|
||||
#define __glibcxx_want_array_constexpr
|
||||
#define __glibcxx_want_freestanding_array
|
||||
#define __glibcxx_want_nonmember_container_access
|
||||
#define __glibcxx_want_to_array
|
||||
#include <bits/version.h>
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
template<typename _Tp, size_t _Nm>
|
||||
struct __array_traits
|
||||
{
|
||||
using _Type = _Tp[_Nm];
|
||||
using _Is_swappable = __is_swappable<_Tp>;
|
||||
using _Is_nothrow_swappable = __is_nothrow_swappable<_Tp>;
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
struct __array_traits<_Tp, 0>
|
||||
{
|
||||
// Empty type used instead of _Tp[0] for std::array<_Tp, 0>.
|
||||
struct _Type
|
||||
{
|
||||
// Indexing is undefined.
|
||||
__attribute__((__always_inline__,__noreturn__))
|
||||
_Tp& operator[](size_t) const noexcept { __builtin_trap(); }
|
||||
|
||||
// Conversion to a pointer produces a null pointer.
|
||||
__attribute__((__always_inline__))
|
||||
constexpr explicit operator _Tp*() const noexcept { return nullptr; }
|
||||
};
|
||||
|
||||
using _Is_swappable = true_type;
|
||||
using _Is_nothrow_swappable = true_type;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A standard container for storing a fixed size sequence of elements.
|
||||
*
|
||||
* @ingroup sequences
|
||||
*
|
||||
* Meets the requirements of a <a href="tables.html#65">container</a>, a
|
||||
* <a href="tables.html#66">reversible container</a>, and a
|
||||
* <a href="tables.html#67">sequence</a>.
|
||||
*
|
||||
* Sets support random access iterators.
|
||||
*
|
||||
* @tparam Tp Type of element. Required to be a complete type.
|
||||
* @tparam Nm Number of elements.
|
||||
*/
|
||||
template<typename _Tp, std::size_t _Nm>
|
||||
struct array
|
||||
{
|
||||
typedef _Tp value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef const value_type* const_pointer;
|
||||
typedef value_type& reference;
|
||||
typedef const value_type& const_reference;
|
||||
typedef value_type* iterator;
|
||||
typedef const value_type* const_iterator;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::reverse_iterator<iterator> reverse_iterator;
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
|
||||
// Support for zero-sized arrays mandatory.
|
||||
typename __array_traits<_Tp, _Nm>::_Type _M_elems;
|
||||
|
||||
// No explicit construct/copy/destroy for aggregate type.
|
||||
|
||||
// DR 776.
|
||||
_GLIBCXX20_CONSTEXPR void
|
||||
fill(const value_type& __u)
|
||||
{ std::fill_n(begin(), size(), __u); }
|
||||
|
||||
_GLIBCXX20_CONSTEXPR void
|
||||
swap(array& __other)
|
||||
noexcept(__array_traits<_Tp, _Nm>::_Is_nothrow_swappable::value)
|
||||
{ std::swap_ranges(begin(), end(), __other.begin()); }
|
||||
|
||||
// Iterators.
|
||||
[[__gnu__::__const__, __nodiscard__]]
|
||||
_GLIBCXX17_CONSTEXPR iterator
|
||||
begin() noexcept
|
||||
{ return iterator(data()); }
|
||||
|
||||
[[__nodiscard__]]
|
||||
_GLIBCXX17_CONSTEXPR const_iterator
|
||||
begin() const noexcept
|
||||
{ return const_iterator(data()); }
|
||||
|
||||
[[__gnu__::__const__, __nodiscard__]]
|
||||
_GLIBCXX17_CONSTEXPR iterator
|
||||
end() noexcept
|
||||
{ return iterator(data() + _Nm); }
|
||||
|
||||
[[__nodiscard__]]
|
||||
_GLIBCXX17_CONSTEXPR const_iterator
|
||||
end() const noexcept
|
||||
{ return const_iterator(data() + _Nm); }
|
||||
|
||||
[[__gnu__::__const__, __nodiscard__]]
|
||||
_GLIBCXX17_CONSTEXPR reverse_iterator
|
||||
rbegin() noexcept
|
||||
{ return reverse_iterator(end()); }
|
||||
|
||||
[[__nodiscard__]]
|
||||
_GLIBCXX17_CONSTEXPR const_reverse_iterator
|
||||
rbegin() const noexcept
|
||||
{ return const_reverse_iterator(end()); }
|
||||
|
||||
[[__gnu__::__const__, __nodiscard__]]
|
||||
_GLIBCXX17_CONSTEXPR reverse_iterator
|
||||
rend() noexcept
|
||||
{ return reverse_iterator(begin()); }
|
||||
|
||||
[[__nodiscard__]]
|
||||
_GLIBCXX17_CONSTEXPR const_reverse_iterator
|
||||
rend() const noexcept
|
||||
{ return const_reverse_iterator(begin()); }
|
||||
|
||||
[[__nodiscard__]]
|
||||
_GLIBCXX17_CONSTEXPR const_iterator
|
||||
cbegin() const noexcept
|
||||
{ return const_iterator(data()); }
|
||||
|
||||
[[__nodiscard__]]
|
||||
_GLIBCXX17_CONSTEXPR const_iterator
|
||||
cend() const noexcept
|
||||
{ return const_iterator(data() + _Nm); }
|
||||
|
||||
[[__nodiscard__]]
|
||||
_GLIBCXX17_CONSTEXPR const_reverse_iterator
|
||||
crbegin() const noexcept
|
||||
{ return const_reverse_iterator(end()); }
|
||||
|
||||
[[__nodiscard__]]
|
||||
_GLIBCXX17_CONSTEXPR const_reverse_iterator
|
||||
crend() const noexcept
|
||||
{ return const_reverse_iterator(begin()); }
|
||||
|
||||
// Capacity.
|
||||
[[__nodiscard__, __gnu__::__const__, __gnu__::__always_inline__]]
|
||||
constexpr size_type
|
||||
size() const noexcept { return _Nm; }
|
||||
|
||||
[[__nodiscard__, __gnu__::__const__, __gnu__::__always_inline__]]
|
||||
constexpr size_type
|
||||
max_size() const noexcept { return _Nm; }
|
||||
|
||||
[[__nodiscard__, __gnu__::__const__, __gnu__::__always_inline__]]
|
||||
constexpr bool
|
||||
empty() const noexcept { return size() == 0; }
|
||||
|
||||
// Element access.
|
||||
[[__nodiscard__]]
|
||||
_GLIBCXX17_CONSTEXPR reference
|
||||
operator[](size_type __n) noexcept
|
||||
{
|
||||
__glibcxx_requires_subscript(__n);
|
||||
return _M_elems[__n];
|
||||
}
|
||||
|
||||
[[__nodiscard__]]
|
||||
constexpr const_reference
|
||||
operator[](size_type __n) const noexcept
|
||||
{
|
||||
#if __cplusplus >= 201402L
|
||||
__glibcxx_requires_subscript(__n);
|
||||
#endif
|
||||
return _M_elems[__n];
|
||||
}
|
||||
|
||||
_GLIBCXX17_CONSTEXPR reference
|
||||
at(size_type __n)
|
||||
{
|
||||
if (__n >= _Nm)
|
||||
std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
|
||||
">= _Nm (which is %zu)"),
|
||||
__n, _Nm);
|
||||
return _M_elems[__n];
|
||||
}
|
||||
|
||||
constexpr const_reference
|
||||
at(size_type __n) const
|
||||
{
|
||||
// Result of conditional expression must be an lvalue so use
|
||||
// boolean ? lvalue : (throw-expr, lvalue)
|
||||
return __n < _Nm ? _M_elems[__n]
|
||||
: (std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
|
||||
">= _Nm (which is %zu)"),
|
||||
__n, _Nm),
|
||||
_M_elems[__n]);
|
||||
}
|
||||
|
||||
[[__nodiscard__]]
|
||||
_GLIBCXX17_CONSTEXPR reference
|
||||
front() noexcept
|
||||
{
|
||||
__glibcxx_requires_nonempty();
|
||||
return _M_elems[(size_type)0];
|
||||
}
|
||||
|
||||
[[__nodiscard__]]
|
||||
constexpr const_reference
|
||||
front() const noexcept
|
||||
{
|
||||
#if __cplusplus >= 201402L
|
||||
__glibcxx_requires_nonempty();
|
||||
#endif
|
||||
return _M_elems[(size_type)0];
|
||||
}
|
||||
|
||||
[[__nodiscard__]]
|
||||
_GLIBCXX17_CONSTEXPR reference
|
||||
back() noexcept
|
||||
{
|
||||
__glibcxx_requires_nonempty();
|
||||
return _M_elems[_Nm - 1];
|
||||
}
|
||||
|
||||
[[__nodiscard__]]
|
||||
constexpr const_reference
|
||||
back() const noexcept
|
||||
{
|
||||
#if __cplusplus >= 201402L
|
||||
__glibcxx_requires_nonempty();
|
||||
#endif
|
||||
return _M_elems[_Nm - 1];
|
||||
}
|
||||
|
||||
[[__nodiscard__, __gnu__::__const__, __gnu__::__always_inline__]]
|
||||
_GLIBCXX17_CONSTEXPR pointer
|
||||
data() noexcept
|
||||
{ return static_cast<pointer>(_M_elems); }
|
||||
|
||||
[[__nodiscard__]]
|
||||
_GLIBCXX17_CONSTEXPR const_pointer
|
||||
data() const noexcept
|
||||
{ return static_cast<const_pointer>(_M_elems); }
|
||||
};
|
||||
|
||||
#if __cpp_deduction_guides >= 201606
|
||||
template<typename _Tp, typename... _Up>
|
||||
array(_Tp, _Up...)
|
||||
-> array<enable_if_t<(is_same_v<_Tp, _Up> && ...), _Tp>,
|
||||
1 + sizeof...(_Up)>;
|
||||
#endif
|
||||
|
||||
// Array comparisons.
|
||||
template<typename _Tp, std::size_t _Nm>
|
||||
[[__nodiscard__]]
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
inline bool
|
||||
operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
|
||||
{ return std::equal(__one.begin(), __one.end(), __two.begin()); }
|
||||
|
||||
#if __cpp_lib_three_way_comparison // C++ >= 20 && lib_concepts
|
||||
template<typename _Tp, size_t _Nm>
|
||||
[[nodiscard]]
|
||||
constexpr __detail::__synth3way_t<_Tp>
|
||||
operator<=>(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b)
|
||||
{
|
||||
if constexpr (_Nm && __is_memcmp_ordered<_Tp>::__value)
|
||||
if (!std::__is_constant_evaluated())
|
||||
{
|
||||
constexpr size_t __n = _Nm * sizeof(_Tp);
|
||||
return __builtin_memcmp(__a.data(), __b.data(), __n) <=> 0;
|
||||
}
|
||||
|
||||
for (size_t __i = 0; __i < _Nm; ++__i)
|
||||
{
|
||||
auto __c = __detail::__synth3way(__a[__i], __b[__i]);
|
||||
if (__c != 0)
|
||||
return __c;
|
||||
}
|
||||
return strong_ordering::equal;
|
||||
}
|
||||
#else
|
||||
template<typename _Tp, std::size_t _Nm>
|
||||
[[__nodiscard__]]
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
inline bool
|
||||
operator!=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
|
||||
{ return !(__one == __two); }
|
||||
|
||||
template<typename _Tp, std::size_t _Nm>
|
||||
[[__nodiscard__]]
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
inline bool
|
||||
operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b)
|
||||
{
|
||||
return std::lexicographical_compare(__a.begin(), __a.end(),
|
||||
__b.begin(), __b.end());
|
||||
}
|
||||
|
||||
template<typename _Tp, std::size_t _Nm>
|
||||
[[__nodiscard__]]
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
inline bool
|
||||
operator>(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
|
||||
{ return __two < __one; }
|
||||
|
||||
template<typename _Tp, std::size_t _Nm>
|
||||
[[__nodiscard__]]
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
inline bool
|
||||
operator<=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
|
||||
{ return !(__one > __two); }
|
||||
|
||||
template<typename _Tp, std::size_t _Nm>
|
||||
[[__nodiscard__]]
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
inline bool
|
||||
operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
|
||||
{ return !(__one < __two); }
|
||||
#endif // three_way_comparison && concepts
|
||||
|
||||
// Specialized algorithms.
|
||||
template<typename _Tp, std::size_t _Nm>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
inline
|
||||
#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
|
||||
// Constrained free swap overload, see p0185r1
|
||||
__enable_if_t<__array_traits<_Tp, _Nm>::_Is_swappable::value>
|
||||
#else
|
||||
void
|
||||
#endif
|
||||
swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two)
|
||||
noexcept(noexcept(__one.swap(__two)))
|
||||
{ __one.swap(__two); }
|
||||
|
||||
#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
|
||||
template<typename _Tp, std::size_t _Nm>
|
||||
__enable_if_t<!__array_traits<_Tp, _Nm>::_Is_swappable::value>
|
||||
swap(array<_Tp, _Nm>&, array<_Tp, _Nm>&) = delete;
|
||||
#endif
|
||||
|
||||
template<std::size_t _Int, typename _Tp, std::size_t _Nm>
|
||||
[[__nodiscard__]]
|
||||
constexpr _Tp&
|
||||
get(array<_Tp, _Nm>& __arr) noexcept
|
||||
{
|
||||
static_assert(_Int < _Nm, "array index is within bounds");
|
||||
return __arr._M_elems[_Int];
|
||||
}
|
||||
|
||||
template<std::size_t _Int, typename _Tp, std::size_t _Nm>
|
||||
[[__nodiscard__]]
|
||||
constexpr _Tp&&
|
||||
get(array<_Tp, _Nm>&& __arr) noexcept
|
||||
{
|
||||
static_assert(_Int < _Nm, "array index is within bounds");
|
||||
return std::move(std::get<_Int>(__arr));
|
||||
}
|
||||
|
||||
template<std::size_t _Int, typename _Tp, std::size_t _Nm>
|
||||
[[__nodiscard__]]
|
||||
constexpr const _Tp&
|
||||
get(const array<_Tp, _Nm>& __arr) noexcept
|
||||
{
|
||||
static_assert(_Int < _Nm, "array index is within bounds");
|
||||
return __arr._M_elems[_Int];
|
||||
}
|
||||
|
||||
template<std::size_t _Int, typename _Tp, std::size_t _Nm>
|
||||
[[__nodiscard__]]
|
||||
constexpr const _Tp&&
|
||||
get(const array<_Tp, _Nm>&& __arr) noexcept
|
||||
{
|
||||
static_assert(_Int < _Nm, "array index is within bounds");
|
||||
return std::move(std::get<_Int>(__arr));
|
||||
}
|
||||
|
||||
#ifdef __cpp_lib_to_array // C++ >= 20 && __cpp_generic_lambdas >= 201707L
|
||||
template<typename _Tp, size_t _Nm>
|
||||
[[nodiscard]]
|
||||
constexpr array<remove_cv_t<_Tp>, _Nm>
|
||||
to_array(_Tp (&__a)[_Nm])
|
||||
noexcept(is_nothrow_constructible_v<_Tp, _Tp&>)
|
||||
{
|
||||
static_assert(!is_array_v<_Tp>);
|
||||
static_assert(is_constructible_v<_Tp, _Tp&>);
|
||||
if constexpr (is_constructible_v<_Tp, _Tp&>)
|
||||
{
|
||||
if constexpr (is_trivially_copyable_v<_Tp>
|
||||
&& is_trivially_default_constructible_v<_Tp>
|
||||
&& is_copy_assignable_v<_Tp>)
|
||||
{
|
||||
array<remove_cv_t<_Tp>, _Nm> __arr;
|
||||
if (!__is_constant_evaluated() && _Nm != 0)
|
||||
__builtin_memcpy((void*)__arr.data(), (void*)__a, sizeof(__a));
|
||||
else
|
||||
for (size_t __i = 0; __i < _Nm; ++__i)
|
||||
__arr._M_elems[__i] = __a[__i];
|
||||
return __arr;
|
||||
}
|
||||
else
|
||||
return [&__a]<size_t... _Idx>(index_sequence<_Idx...>) {
|
||||
return array<remove_cv_t<_Tp>, _Nm>{{ __a[_Idx]... }};
|
||||
}(make_index_sequence<_Nm>{});
|
||||
}
|
||||
else
|
||||
__builtin_unreachable(); // FIXME: see PR c++/91388
|
||||
}
|
||||
|
||||
template<typename _Tp, size_t _Nm>
|
||||
[[nodiscard]]
|
||||
constexpr array<remove_cv_t<_Tp>, _Nm>
|
||||
to_array(_Tp (&&__a)[_Nm])
|
||||
noexcept(is_nothrow_move_constructible_v<_Tp>)
|
||||
{
|
||||
static_assert(!is_array_v<_Tp>);
|
||||
static_assert(is_move_constructible_v<_Tp>);
|
||||
if constexpr (is_move_constructible_v<_Tp>)
|
||||
{
|
||||
if constexpr (is_trivially_copyable_v<_Tp>
|
||||
&& is_trivially_default_constructible_v<_Tp>
|
||||
&& is_copy_assignable_v<_Tp>)
|
||||
{
|
||||
array<remove_cv_t<_Tp>, _Nm> __arr;
|
||||
if (!__is_constant_evaluated() && _Nm != 0)
|
||||
__builtin_memcpy((void*)__arr.data(), (void*)__a, sizeof(__a));
|
||||
else
|
||||
for (size_t __i = 0; __i < _Nm; ++__i)
|
||||
__arr._M_elems[__i] = __a[__i];
|
||||
return __arr;
|
||||
}
|
||||
else
|
||||
return [&__a]<size_t... _Idx>(index_sequence<_Idx...>) {
|
||||
return array<remove_cv_t<_Tp>, _Nm>{{ std::move(__a[_Idx])... }};
|
||||
}(make_index_sequence<_Nm>{});
|
||||
}
|
||||
else
|
||||
__builtin_unreachable(); // FIXME: see PR c++/91388
|
||||
}
|
||||
#endif // __cpp_lib_to_array
|
||||
|
||||
// Tuple interface to class template array.
|
||||
|
||||
/// Partial specialization for std::array
|
||||
template<typename _Tp, size_t _Nm>
|
||||
struct tuple_size<array<_Tp, _Nm>>
|
||||
: public integral_constant<size_t, _Nm> { };
|
||||
|
||||
/// Partial specialization for std::array
|
||||
template<size_t _Ind, typename _Tp, size_t _Nm>
|
||||
struct tuple_element<_Ind, array<_Tp, _Nm>>
|
||||
{
|
||||
static_assert(_Ind < _Nm, "array index is in range");
|
||||
using type = _Tp;
|
||||
};
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
template<typename _Tp, size_t _Nm>
|
||||
inline constexpr size_t tuple_size_v<array<_Tp, _Nm>> = _Nm;
|
||||
|
||||
template<typename _Tp, size_t _Nm>
|
||||
inline constexpr size_t tuple_size_v<const array<_Tp, _Nm>> = _Nm;
|
||||
#endif
|
||||
|
||||
template<typename _Tp, size_t _Nm>
|
||||
struct __is_tuple_like_impl<array<_Tp, _Nm>> : true_type
|
||||
{ };
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
||||
#endif // C++11
|
||||
|
||||
#endif // _GLIBCXX_ARRAY
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,216 @@
|
||||
/* Copyright (C) 2015-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#if !defined _IMMINTRIN_H_INCLUDED
|
||||
# error "Never use <avx5124fmapsintrin.h> directly; include <x86intrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AVX5124FMAPSINTRIN_H_INCLUDED
|
||||
#define _AVX5124FMAPSINTRIN_H_INCLUDED
|
||||
|
||||
#ifndef __AVX5124FMAPS__
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avx5124fmaps,evex512")
|
||||
#define __DISABLE_AVX5124FMAPS__
|
||||
#endif /* __AVX5124FMAPS__ */
|
||||
|
||||
extern __inline __m512
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_4fmadd_ps (__m512 __A, __m512 __B, __m512 __C,
|
||||
__m512 __D, __m512 __E, __m128 *__F)
|
||||
{
|
||||
return (__m512) __builtin_ia32_4fmaddps ((__v16sf) __B,
|
||||
(__v16sf) __C,
|
||||
(__v16sf) __D,
|
||||
(__v16sf) __E,
|
||||
(__v16sf) __A,
|
||||
(const __v4sf *) __F);
|
||||
}
|
||||
|
||||
extern __inline __m512
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_4fmadd_ps (__m512 __A, __mmask16 __U, __m512 __B,
|
||||
__m512 __C, __m512 __D, __m512 __E, __m128 *__F)
|
||||
{
|
||||
return (__m512) __builtin_ia32_4fmaddps_mask ((__v16sf) __B,
|
||||
(__v16sf) __C,
|
||||
(__v16sf) __D,
|
||||
(__v16sf) __E,
|
||||
(__v16sf) __A,
|
||||
(const __v4sf *) __F,
|
||||
(__v16sf) __A,
|
||||
(__mmask16) __U);
|
||||
}
|
||||
|
||||
extern __inline __m512
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_4fmadd_ps (__mmask16 __U,
|
||||
__m512 __A, __m512 __B, __m512 __C,
|
||||
__m512 __D, __m512 __E, __m128 *__F)
|
||||
{
|
||||
return (__m512) __builtin_ia32_4fmaddps_mask ((__v16sf) __B,
|
||||
(__v16sf) __C,
|
||||
(__v16sf) __D,
|
||||
(__v16sf) __E,
|
||||
(__v16sf) __A,
|
||||
(const __v4sf *) __F,
|
||||
(__v16sf) _mm512_setzero_ps (),
|
||||
(__mmask16) __U);
|
||||
}
|
||||
|
||||
extern __inline __m128
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_4fmadd_ss (__m128 __A, __m128 __B, __m128 __C,
|
||||
__m128 __D, __m128 __E, __m128 *__F)
|
||||
{
|
||||
return (__m128) __builtin_ia32_4fmaddss ((__v4sf) __B,
|
||||
(__v4sf) __C,
|
||||
(__v4sf) __D,
|
||||
(__v4sf) __E,
|
||||
(__v4sf) __A,
|
||||
(const __v4sf *) __F);
|
||||
}
|
||||
|
||||
extern __inline __m128
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask_4fmadd_ss (__m128 __A, __mmask8 __U, __m128 __B, __m128 __C,
|
||||
__m128 __D, __m128 __E, __m128 *__F)
|
||||
{
|
||||
return (__m128) __builtin_ia32_4fmaddss_mask ((__v4sf) __B,
|
||||
(__v4sf) __C,
|
||||
(__v4sf) __D,
|
||||
(__v4sf) __E,
|
||||
(__v4sf) __A,
|
||||
(const __v4sf *) __F,
|
||||
(__v4sf) __A,
|
||||
(__mmask8) __U);
|
||||
}
|
||||
|
||||
extern __inline __m128
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_maskz_4fmadd_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C,
|
||||
__m128 __D, __m128 __E, __m128 *__F)
|
||||
{
|
||||
return (__m128) __builtin_ia32_4fmaddss_mask ((__v4sf) __B,
|
||||
(__v4sf) __C,
|
||||
(__v4sf) __D,
|
||||
(__v4sf) __E,
|
||||
(__v4sf) __A,
|
||||
(const __v4sf *) __F,
|
||||
(__v4sf) _mm_setzero_ps (),
|
||||
(__mmask8) __U);
|
||||
}
|
||||
|
||||
extern __inline __m512
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_4fnmadd_ps (__m512 __A, __m512 __B, __m512 __C,
|
||||
__m512 __D, __m512 __E, __m128 *__F)
|
||||
{
|
||||
return (__m512) __builtin_ia32_4fnmaddps ((__v16sf) __B,
|
||||
(__v16sf) __C,
|
||||
(__v16sf) __D,
|
||||
(__v16sf) __E,
|
||||
(__v16sf) __A,
|
||||
(const __v4sf *) __F);
|
||||
}
|
||||
|
||||
extern __inline __m512
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_4fnmadd_ps (__m512 __A, __mmask16 __U, __m512 __B,
|
||||
__m512 __C, __m512 __D, __m512 __E, __m128 *__F)
|
||||
{
|
||||
return (__m512) __builtin_ia32_4fnmaddps_mask ((__v16sf) __B,
|
||||
(__v16sf) __C,
|
||||
(__v16sf) __D,
|
||||
(__v16sf) __E,
|
||||
(__v16sf) __A,
|
||||
(const __v4sf *) __F,
|
||||
(__v16sf) __A,
|
||||
(__mmask16) __U);
|
||||
}
|
||||
|
||||
extern __inline __m512
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_4fnmadd_ps (__mmask16 __U,
|
||||
__m512 __A, __m512 __B, __m512 __C,
|
||||
__m512 __D, __m512 __E, __m128 *__F)
|
||||
{
|
||||
return (__m512) __builtin_ia32_4fnmaddps_mask ((__v16sf) __B,
|
||||
(__v16sf) __C,
|
||||
(__v16sf) __D,
|
||||
(__v16sf) __E,
|
||||
(__v16sf) __A,
|
||||
(const __v4sf *) __F,
|
||||
(__v16sf) _mm512_setzero_ps (),
|
||||
(__mmask16) __U);
|
||||
}
|
||||
|
||||
extern __inline __m128
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_4fnmadd_ss (__m128 __A, __m128 __B, __m128 __C,
|
||||
__m128 __D, __m128 __E, __m128 *__F)
|
||||
{
|
||||
return (__m128) __builtin_ia32_4fnmaddss ((__v4sf) __B,
|
||||
(__v4sf) __C,
|
||||
(__v4sf) __D,
|
||||
(__v4sf) __E,
|
||||
(__v4sf) __A,
|
||||
(const __v4sf *) __F);
|
||||
}
|
||||
|
||||
extern __inline __m128
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask_4fnmadd_ss (__m128 __A, __mmask8 __U, __m128 __B, __m128 __C,
|
||||
__m128 __D, __m128 __E, __m128 *__F)
|
||||
{
|
||||
return (__m128) __builtin_ia32_4fnmaddss_mask ((__v4sf) __B,
|
||||
(__v4sf) __C,
|
||||
(__v4sf) __D,
|
||||
(__v4sf) __E,
|
||||
(__v4sf) __A,
|
||||
(const __v4sf *) __F,
|
||||
(__v4sf) __A,
|
||||
(__mmask8) __U);
|
||||
}
|
||||
|
||||
extern __inline __m128
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_maskz_4fnmadd_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C,
|
||||
__m128 __D, __m128 __E, __m128 *__F)
|
||||
{
|
||||
return (__m128) __builtin_ia32_4fnmaddss_mask ((__v4sf) __B,
|
||||
(__v4sf) __C,
|
||||
(__v4sf) __D,
|
||||
(__v4sf) __E,
|
||||
(__v4sf) __A,
|
||||
(const __v4sf *) __F,
|
||||
(__v4sf) _mm_setzero_ps (),
|
||||
(__mmask8) __U);
|
||||
}
|
||||
|
||||
#ifdef __DISABLE_AVX5124FMAPS__
|
||||
#undef __DISABLE_AVX5124FMAPS__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVX5124FMAPS__ */
|
||||
|
||||
#endif /* _AVX5124FMAPSINTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,132 @@
|
||||
/* Copyright (C) 2015-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#if !defined _IMMINTRIN_H_INCLUDED
|
||||
# error "Never use <avx5124vnniwintrin.h> directly; include <x86intrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AVX5124VNNIWINTRIN_H_INCLUDED
|
||||
#define _AVX5124VNNIWINTRIN_H_INCLUDED
|
||||
|
||||
#ifndef __AVX5124VNNIW__
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avx5124vnniw,evex512")
|
||||
#define __DISABLE_AVX5124VNNIW__
|
||||
#endif /* __AVX5124VNNIW__ */
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_4dpwssd_epi32 (__m512i __A, __m512i __B, __m512i __C,
|
||||
__m512i __D, __m512i __E, __m128i *__F)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vp4dpwssd ((__v16si) __B,
|
||||
(__v16si) __C,
|
||||
(__v16si) __D,
|
||||
(__v16si) __E,
|
||||
(__v16si) __A,
|
||||
(const __v4si *) __F);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_4dpwssd_epi32 (__m512i __A, __mmask16 __U, __m512i __B,
|
||||
__m512i __C, __m512i __D, __m512i __E,
|
||||
__m128i *__F)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vp4dpwssd_mask ((__v16si) __B,
|
||||
(__v16si) __C,
|
||||
(__v16si) __D,
|
||||
(__v16si) __E,
|
||||
(__v16si) __A,
|
||||
(const __v4si *) __F,
|
||||
(__v16si) __A,
|
||||
(__mmask16) __U);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_4dpwssd_epi32 (__mmask16 __U, __m512i __A, __m512i __B,
|
||||
__m512i __C, __m512i __D, __m512i __E,
|
||||
__m128i *__F)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vp4dpwssd_mask ((__v16si) __B,
|
||||
(__v16si) __C,
|
||||
(__v16si) __D,
|
||||
(__v16si) __E,
|
||||
(__v16si) __A,
|
||||
(const __v4si *) __F,
|
||||
(__v16si) _mm512_setzero_ps (),
|
||||
(__mmask16) __U);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_4dpwssds_epi32 (__m512i __A, __m512i __B, __m512i __C,
|
||||
__m512i __D, __m512i __E, __m128i *__F)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vp4dpwssds ((__v16si) __B,
|
||||
(__v16si) __C,
|
||||
(__v16si) __D,
|
||||
(__v16si) __E,
|
||||
(__v16si) __A,
|
||||
(const __v4si *) __F);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_4dpwssds_epi32 (__m512i __A, __mmask16 __U, __m512i __B,
|
||||
__m512i __C, __m512i __D, __m512i __E,
|
||||
__m128i *__F)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vp4dpwssds_mask ((__v16si) __B,
|
||||
(__v16si) __C,
|
||||
(__v16si) __D,
|
||||
(__v16si) __E,
|
||||
(__v16si) __A,
|
||||
(const __v4si *) __F,
|
||||
(__v16si) __A,
|
||||
(__mmask16) __U);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_4dpwssds_epi32 (__mmask16 __U, __m512i __A, __m512i __B,
|
||||
__m512i __C, __m512i __D, __m512i __E,
|
||||
__m128i *__F)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vp4dpwssds_mask ((__v16si) __B,
|
||||
(__v16si) __C,
|
||||
(__v16si) __D,
|
||||
(__v16si) __E,
|
||||
(__v16si) __A,
|
||||
(const __v4si *) __F,
|
||||
(__v16si) _mm512_setzero_ps (),
|
||||
(__mmask16) __U);
|
||||
}
|
||||
|
||||
#ifdef __DISABLE_AVX5124VNNIW__
|
||||
#undef __DISABLE_AVX5124VNNIW__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVX5124VNNIW__ */
|
||||
|
||||
#endif /* _AVX5124VNNIWINTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,163 @@
|
||||
/* Copyright (C) 2019-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _IMMINTRIN_H_INCLUDED
|
||||
#error "Never use <avx512bf16intrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AVX512BF16INTRIN_H_INCLUDED
|
||||
#define _AVX512BF16INTRIN_H_INCLUDED
|
||||
|
||||
#if !defined (__AVX512BF16__) || defined (__EVEX512__)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avx512bf16,no-evex512")
|
||||
#define __DISABLE_AVX512BF16__
|
||||
#endif /* __AVX512BF16__ */
|
||||
|
||||
/* Convert One BF16 Data to One Single Float Data. */
|
||||
extern __inline float
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_cvtsbh_ss (__bf16 __A)
|
||||
{
|
||||
return __builtin_ia32_cvtbf2sf (__A);
|
||||
}
|
||||
|
||||
#ifdef __DISABLE_AVX512BF16__
|
||||
#undef __DISABLE_AVX512BF16__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVX512BF16__ */
|
||||
|
||||
#if !defined (__AVX512BF16__) || !defined (__EVEX512__)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avx512bf16,evex512")
|
||||
#define __DISABLE_AVX512BF16_512__
|
||||
#endif /* __AVX512BF16_512__ */
|
||||
|
||||
/* Internal data types for implementing the intrinsics. */
|
||||
typedef __bf16 __v32bf __attribute__ ((__vector_size__ (64)));
|
||||
|
||||
/* The Intel API is flexible enough that we must allow aliasing with other
|
||||
vector types, and their scalar components. */
|
||||
typedef __bf16 __m512bh __attribute__ ((__vector_size__ (64), __may_alias__));
|
||||
|
||||
/* vcvtne2ps2bf16 */
|
||||
|
||||
extern __inline __m512bh
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_cvtne2ps_pbh (__m512 __A, __m512 __B)
|
||||
{
|
||||
return (__m512bh)__builtin_ia32_cvtne2ps2bf16_v32bf(__A, __B);
|
||||
}
|
||||
|
||||
extern __inline __m512bh
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_cvtne2ps_pbh (__m512bh __A, __mmask32 __B, __m512 __C, __m512 __D)
|
||||
{
|
||||
return (__m512bh)__builtin_ia32_cvtne2ps2bf16_v32bf_mask(__C, __D, __A, __B);
|
||||
}
|
||||
|
||||
extern __inline __m512bh
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_cvtne2ps_pbh (__mmask32 __A, __m512 __B, __m512 __C)
|
||||
{
|
||||
return (__m512bh)__builtin_ia32_cvtne2ps2bf16_v32bf_maskz(__B, __C, __A);
|
||||
}
|
||||
|
||||
/* vcvtneps2bf16 */
|
||||
|
||||
extern __inline __m256bh
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_cvtneps_pbh (__m512 __A)
|
||||
{
|
||||
return (__m256bh)__builtin_ia32_cvtneps2bf16_v16sf(__A);
|
||||
}
|
||||
|
||||
extern __inline __m256bh
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_cvtneps_pbh (__m256bh __A, __mmask16 __B, __m512 __C)
|
||||
{
|
||||
return (__m256bh)__builtin_ia32_cvtneps2bf16_v16sf_mask(__C, __A, __B);
|
||||
}
|
||||
|
||||
extern __inline __m256bh
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_cvtneps_pbh (__mmask16 __A, __m512 __B)
|
||||
{
|
||||
return (__m256bh)__builtin_ia32_cvtneps2bf16_v16sf_maskz(__B, __A);
|
||||
}
|
||||
|
||||
/* vdpbf16ps */
|
||||
|
||||
extern __inline __m512
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_dpbf16_ps (__m512 __A, __m512bh __B, __m512bh __C)
|
||||
{
|
||||
return (__m512)__builtin_ia32_dpbf16ps_v16sf(__A, __B, __C);
|
||||
}
|
||||
|
||||
extern __inline __m512
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_dpbf16_ps (__m512 __A, __mmask16 __B, __m512bh __C, __m512bh __D)
|
||||
{
|
||||
return (__m512)__builtin_ia32_dpbf16ps_v16sf_mask(__A, __C, __D, __B);
|
||||
}
|
||||
|
||||
extern __inline __m512
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_dpbf16_ps (__mmask16 __A, __m512 __B, __m512bh __C, __m512bh __D)
|
||||
{
|
||||
return (__m512)__builtin_ia32_dpbf16ps_v16sf_maskz(__B, __C, __D, __A);
|
||||
}
|
||||
|
||||
extern __inline __m512
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_cvtpbh_ps (__m256bh __A)
|
||||
{
|
||||
return (__m512)_mm512_castsi512_ps ((__m512i)_mm512_slli_epi32 (
|
||||
(__m512i)_mm512_cvtepi16_epi32 ((__m256i)__A), 16));
|
||||
}
|
||||
|
||||
extern __inline __m512
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_cvtpbh_ps (__mmask16 __U, __m256bh __A)
|
||||
{
|
||||
return (__m512)_mm512_castsi512_ps ((__m512i) _mm512_slli_epi32 (
|
||||
(__m512i)_mm512_maskz_cvtepi16_epi32 (
|
||||
(__mmask16)__U, (__m256i)__A), 16));
|
||||
}
|
||||
|
||||
extern __inline __m512
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_cvtpbh_ps (__m512 __S, __mmask16 __U, __m256bh __A)
|
||||
{
|
||||
return (__m512)_mm512_castsi512_ps ((__m512i)(_mm512_mask_slli_epi32 (
|
||||
(__m512i)__S, (__mmask16)__U,
|
||||
(__m512i)_mm512_cvtepi16_epi32 ((__m256i)__A), 16)));
|
||||
}
|
||||
|
||||
#ifdef __DISABLE_AVX512BF16_512__
|
||||
#undef __DISABLE_AVX512BF16_512__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVX512BF16_512__ */
|
||||
|
||||
#endif /* _AVX512BF16INTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,276 @@
|
||||
/* Copyright (C) 2019-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _IMMINTRIN_H_INCLUDED
|
||||
#error "Never use <avx512bf16vlintrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AVX512BF16VLINTRIN_H_INCLUDED
|
||||
#define _AVX512BF16VLINTRIN_H_INCLUDED
|
||||
|
||||
#if !defined(__AVX512VL__) || !defined(__AVX512BF16__) || defined (__EVEX512__)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avx512bf16,avx512vl,no-evex512")
|
||||
#define __DISABLE_AVX512BF16VL__
|
||||
#endif /* __AVX512BF16__ */
|
||||
|
||||
/* Internal data types for implementing the intrinsics. */
|
||||
typedef __bf16 __v16bf __attribute__ ((__vector_size__ (32)));
|
||||
typedef __bf16 __v8bf __attribute__ ((__vector_size__ (16)));
|
||||
|
||||
/* The Intel API is flexible enough that we must allow aliasing with other
|
||||
vector types, and their scalar components. */
|
||||
typedef __bf16 __m256bh __attribute__ ((__vector_size__ (32), __may_alias__));
|
||||
typedef __bf16 __m128bh __attribute__ ((__vector_size__ (16), __may_alias__));
|
||||
|
||||
typedef __bf16 __bfloat16;
|
||||
|
||||
extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_avx512_castsi128_ps(__m128i __A)
|
||||
{
|
||||
return (__m128) __A;
|
||||
}
|
||||
|
||||
extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_avx512_castsi256_ps (__m256i __A)
|
||||
{
|
||||
return (__m256) __A;
|
||||
}
|
||||
|
||||
extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_avx512_slli_epi32 (__m128i __A, int __B)
|
||||
{
|
||||
return (__m128i)__builtin_ia32_pslldi128 ((__v4si)__A, __B);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_avx512_slli_epi32 (__m256i __A, int __B)
|
||||
{
|
||||
return (__m256i)__builtin_ia32_pslldi256 ((__v8si)__A, __B);
|
||||
}
|
||||
|
||||
extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_avx512_cvtepi16_epi32 (__m128i __X)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_pmovsxwd128 ((__v8hi)__X);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_avx512_cvtepi16_epi32 (__m128i __X)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_pmovsxwd256 ((__v8hi)__X);
|
||||
}
|
||||
|
||||
#define _mm256_cvtneps_pbh(A) \
|
||||
(__m128bh) __builtin_ia32_cvtneps2bf16_v8sf (A)
|
||||
#define _mm_cvtneps_pbh(A) \
|
||||
(__m128bh) __builtin_ia32_cvtneps2bf16_v4sf (A)
|
||||
|
||||
/* vcvtne2ps2bf16 */
|
||||
|
||||
extern __inline __m256bh
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_cvtne2ps_pbh (__m256 __A, __m256 __B)
|
||||
{
|
||||
return (__m256bh)__builtin_ia32_cvtne2ps2bf16_v16bf(__A, __B);
|
||||
}
|
||||
|
||||
extern __inline __m256bh
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_mask_cvtne2ps_pbh (__m256bh __A, __mmask16 __B, __m256 __C, __m256 __D)
|
||||
{
|
||||
return (__m256bh)__builtin_ia32_cvtne2ps2bf16_v16bf_mask(__C, __D, __A, __B);
|
||||
}
|
||||
|
||||
extern __inline __m256bh
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_maskz_cvtne2ps_pbh (__mmask16 __A, __m256 __B, __m256 __C)
|
||||
{
|
||||
return (__m256bh)__builtin_ia32_cvtne2ps2bf16_v16bf_maskz(__B, __C, __A);
|
||||
}
|
||||
|
||||
extern __inline __m128bh
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_cvtne2ps_pbh (__m128 __A, __m128 __B)
|
||||
{
|
||||
return (__m128bh)__builtin_ia32_cvtne2ps2bf16_v8bf(__A, __B);
|
||||
}
|
||||
|
||||
extern __inline __m128bh
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask_cvtne2ps_pbh (__m128bh __A, __mmask8 __B, __m128 __C, __m128 __D)
|
||||
{
|
||||
return (__m128bh)__builtin_ia32_cvtne2ps2bf16_v8bf_mask(__C, __D, __A, __B);
|
||||
}
|
||||
|
||||
extern __inline __m128bh
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_maskz_cvtne2ps_pbh (__mmask8 __A, __m128 __B, __m128 __C)
|
||||
{
|
||||
return (__m128bh)__builtin_ia32_cvtne2ps2bf16_v8bf_maskz(__B, __C, __A);
|
||||
}
|
||||
|
||||
/* vcvtneps2bf16 */
|
||||
|
||||
extern __inline __m128bh
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_mask_cvtneps_pbh (__m128bh __A, __mmask8 __B, __m256 __C)
|
||||
{
|
||||
return (__m128bh)__builtin_ia32_cvtneps2bf16_v8sf_mask(__C, __A, __B);
|
||||
}
|
||||
|
||||
extern __inline __m128bh
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_maskz_cvtneps_pbh (__mmask8 __A, __m256 __B)
|
||||
{
|
||||
return (__m128bh)__builtin_ia32_cvtneps2bf16_v8sf_maskz(__B, __A);
|
||||
}
|
||||
|
||||
extern __inline __m128bh
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask_cvtneps_pbh (__m128bh __A, __mmask8 __B, __m128 __C)
|
||||
{
|
||||
return (__m128bh)__builtin_ia32_cvtneps2bf16_v4sf_mask(__C, __A, __B);
|
||||
}
|
||||
|
||||
extern __inline __m128bh
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_maskz_cvtneps_pbh (__mmask8 __A, __m128 __B)
|
||||
{
|
||||
return (__m128bh)__builtin_ia32_cvtneps2bf16_v4sf_maskz(__B, __A);
|
||||
}
|
||||
|
||||
/* vdpbf16ps */
|
||||
|
||||
extern __inline __m256
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_dpbf16_ps (__m256 __A, __m256bh __B, __m256bh __C)
|
||||
{
|
||||
return (__m256)__builtin_ia32_dpbf16ps_v8sf(__A, __B, __C);
|
||||
}
|
||||
|
||||
extern __inline __m256
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_mask_dpbf16_ps (__m256 __A, __mmask8 __B, __m256bh __C, __m256bh __D)
|
||||
{
|
||||
return (__m256)__builtin_ia32_dpbf16ps_v8sf_mask(__A, __C, __D, __B);
|
||||
}
|
||||
|
||||
extern __inline __m256
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_maskz_dpbf16_ps (__mmask8 __A, __m256 __B, __m256bh __C, __m256bh __D)
|
||||
{
|
||||
return (__m256)__builtin_ia32_dpbf16ps_v8sf_maskz(__B, __C, __D, __A);
|
||||
}
|
||||
|
||||
extern __inline __m128
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_dpbf16_ps (__m128 __A, __m128bh __B, __m128bh __C)
|
||||
{
|
||||
return (__m128)__builtin_ia32_dpbf16ps_v4sf(__A, __B, __C);
|
||||
}
|
||||
|
||||
extern __inline __m128
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask_dpbf16_ps (__m128 __A, __mmask8 __B, __m128bh __C, __m128bh __D)
|
||||
{
|
||||
return (__m128)__builtin_ia32_dpbf16ps_v4sf_mask(__A, __C, __D, __B);
|
||||
}
|
||||
|
||||
extern __inline __m128
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_maskz_dpbf16_ps (__mmask8 __A, __m128 __B, __m128bh __C, __m128bh __D)
|
||||
{
|
||||
return (__m128)__builtin_ia32_dpbf16ps_v4sf_maskz(__B, __C, __D, __A);
|
||||
}
|
||||
|
||||
extern __inline __bf16
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_cvtness_sbh (float __A)
|
||||
{
|
||||
__v4sf __V = {__A, 0, 0, 0};
|
||||
__v8bf __R = __builtin_ia32_cvtneps2bf16_v4sf_mask ((__v4sf)__V,
|
||||
(__v8bf)_mm_avx512_undefined_si128 (), (__mmask8)-1);
|
||||
return __R[0];
|
||||
}
|
||||
|
||||
extern __inline __m128
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_cvtpbh_ps (__m128bh __A)
|
||||
{
|
||||
return (__m128)_mm_avx512_castsi128_ps ((__m128i)_mm_avx512_slli_epi32 (
|
||||
(__m128i)_mm_avx512_cvtepi16_epi32 ((__m128i)__A), 16));
|
||||
}
|
||||
|
||||
extern __inline __m256
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_cvtpbh_ps (__m128bh __A)
|
||||
{
|
||||
return (__m256)_mm256_avx512_castsi256_ps ((__m256i)_mm256_avx512_slli_epi32 (
|
||||
(__m256i)_mm256_avx512_cvtepi16_epi32 ((__m128i)__A), 16));
|
||||
}
|
||||
|
||||
extern __inline __m128
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_maskz_cvtpbh_ps (__mmask8 __U, __m128bh __A)
|
||||
{
|
||||
return (__m128)_mm_avx512_castsi128_ps ((__m128i)_mm_avx512_slli_epi32 (
|
||||
(__m128i)_mm_maskz_cvtepi16_epi32 (
|
||||
(__mmask8)__U, (__m128i)__A), 16));
|
||||
}
|
||||
|
||||
extern __inline __m256
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_maskz_cvtpbh_ps (__mmask8 __U, __m128bh __A)
|
||||
{
|
||||
return (__m256)_mm256_avx512_castsi256_ps ((__m256i)_mm256_avx512_slli_epi32 (
|
||||
(__m256i)_mm256_maskz_cvtepi16_epi32 (
|
||||
(__mmask8)__U, (__m128i)__A), 16));
|
||||
}
|
||||
|
||||
extern __inline __m128
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask_cvtpbh_ps (__m128 __S, __mmask8 __U, __m128bh __A)
|
||||
{
|
||||
return (__m128)_mm_avx512_castsi128_ps ((__m128i)_mm_mask_slli_epi32 (
|
||||
(__m128i)__S, (__mmask8)__U, (__m128i)_mm_avx512_cvtepi16_epi32 (
|
||||
(__m128i)__A), 16));
|
||||
}
|
||||
|
||||
extern __inline __m256
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_mask_cvtpbh_ps (__m256 __S, __mmask8 __U, __m128bh __A)
|
||||
{
|
||||
return (__m256)_mm256_avx512_castsi256_ps ((__m256i)_mm256_mask_slli_epi32 (
|
||||
(__m256i)__S, (__mmask8)__U, (__m256i)_mm256_avx512_cvtepi16_epi32 (
|
||||
(__m128i)__A), 16));
|
||||
}
|
||||
|
||||
#ifdef __DISABLE_AVX512BF16VL__
|
||||
#undef __DISABLE_AVX512BF16VL__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVX512BF16VL__ */
|
||||
|
||||
#endif /* _AVX512BF16VLINTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,111 @@
|
||||
/* Copyright (C) 2017-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#if !defined _IMMINTRIN_H_INCLUDED
|
||||
# error "Never use <avx512bitalgintrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AVX512BITALGINTRIN_H_INCLUDED
|
||||
#define _AVX512BITALGINTRIN_H_INCLUDED
|
||||
|
||||
#if !defined (__AVX512BITALG__) || !defined (__EVEX512__)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avx512bitalg,evex512")
|
||||
#define __DISABLE_AVX512BITALG__
|
||||
#endif /* __AVX512BITALG__ */
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_popcnt_epi8 (__m512i __A)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpopcountb_v64qi ((__v64qi) __A);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_popcnt_epi16 (__m512i __A)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpopcountw_v32hi ((__v32hi) __A);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_popcnt_epi8 (__m512i __W, __mmask64 __U, __m512i __A)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpopcountb_v64qi_mask ((__v64qi) __A,
|
||||
(__v64qi) __W,
|
||||
(__mmask64) __U);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_popcnt_epi8 (__mmask64 __U, __m512i __A)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpopcountb_v64qi_mask ((__v64qi) __A,
|
||||
(__v64qi)
|
||||
_mm512_setzero_si512 (),
|
||||
(__mmask64) __U);
|
||||
}
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_popcnt_epi16 (__m512i __W, __mmask32 __U, __m512i __A)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpopcountw_v32hi_mask ((__v32hi) __A,
|
||||
(__v32hi) __W,
|
||||
(__mmask32) __U);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_popcnt_epi16 (__mmask32 __U, __m512i __A)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpopcountw_v32hi_mask ((__v32hi) __A,
|
||||
(__v32hi)
|
||||
_mm512_setzero_si512 (),
|
||||
(__mmask32) __U);
|
||||
}
|
||||
|
||||
extern __inline __mmask64
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_bitshuffle_epi64_mask (__m512i __A, __m512i __B)
|
||||
{
|
||||
return (__mmask64) __builtin_ia32_vpshufbitqmb512_mask ((__v64qi) __A,
|
||||
(__v64qi) __B,
|
||||
(__mmask64) -1);
|
||||
}
|
||||
|
||||
extern __inline __mmask64
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_bitshuffle_epi64_mask (__mmask64 __M, __m512i __A, __m512i __B)
|
||||
{
|
||||
return (__mmask64) __builtin_ia32_vpshufbitqmb512_mask ((__v64qi) __A,
|
||||
(__v64qi) __B,
|
||||
(__mmask64) __M);
|
||||
}
|
||||
|
||||
#ifdef __DISABLE_AVX512BITALG__
|
||||
#undef __DISABLE_AVX512BITALG__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVX512BITALG__ */
|
||||
|
||||
#endif /* _AVX512BITALGINTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,180 @@
|
||||
/* Copyright (C) 2023-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#if !defined _IMMINTRIN_H_INCLUDED
|
||||
# error "Never use <avx512bitalgvlintrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AVX512BITALGVLINTRIN_H_INCLUDED
|
||||
#define _AVX512BITALGVLINTRIN_H_INCLUDED
|
||||
|
||||
#if !defined(__AVX512BITALG__) || !defined(__AVX512VL__) || defined (__EVEX512__)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avx512bitalg,avx512vl,no-evex512")
|
||||
#define __DISABLE_AVX512BITALGVL__
|
||||
#endif /* __AVX512BITALGVL__ */
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_mask_popcnt_epi8 (__m256i __W, __mmask32 __U, __m256i __A)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpopcountb_v32qi_mask ((__v32qi) __A,
|
||||
(__v32qi) __W,
|
||||
(__mmask32) __U);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_maskz_popcnt_epi8 (__mmask32 __U, __m256i __A)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpopcountb_v32qi_mask ((__v32qi) __A,
|
||||
(__v32qi)
|
||||
_mm256_avx512_setzero_si256 (),
|
||||
(__mmask32) __U);
|
||||
}
|
||||
|
||||
extern __inline __mmask32
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_bitshuffle_epi64_mask (__m256i __A, __m256i __B)
|
||||
{
|
||||
return (__mmask32) __builtin_ia32_vpshufbitqmb256_mask ((__v32qi) __A,
|
||||
(__v32qi) __B,
|
||||
(__mmask32) -1);
|
||||
}
|
||||
|
||||
extern __inline __mmask32
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_mask_bitshuffle_epi64_mask (__mmask32 __M, __m256i __A, __m256i __B)
|
||||
{
|
||||
return (__mmask32) __builtin_ia32_vpshufbitqmb256_mask ((__v32qi) __A,
|
||||
(__v32qi) __B,
|
||||
(__mmask32) __M);
|
||||
}
|
||||
|
||||
extern __inline __mmask16
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_bitshuffle_epi64_mask (__m128i __A, __m128i __B)
|
||||
{
|
||||
return (__mmask16) __builtin_ia32_vpshufbitqmb128_mask ((__v16qi) __A,
|
||||
(__v16qi) __B,
|
||||
(__mmask16) -1);
|
||||
}
|
||||
|
||||
extern __inline __mmask16
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask_bitshuffle_epi64_mask (__mmask16 __M, __m128i __A, __m128i __B)
|
||||
{
|
||||
return (__mmask16) __builtin_ia32_vpshufbitqmb128_mask ((__v16qi) __A,
|
||||
(__v16qi) __B,
|
||||
(__mmask16) __M);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_popcnt_epi8 (__m256i __A)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpopcountb_v32qi ((__v32qi) __A);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_popcnt_epi16 (__m256i __A)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpopcountw_v16hi ((__v16hi) __A);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_popcnt_epi8 (__m128i __A)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpopcountb_v16qi ((__v16qi) __A);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_popcnt_epi16 (__m128i __A)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpopcountw_v8hi ((__v8hi) __A);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_mask_popcnt_epi16 (__m256i __W, __mmask16 __U, __m256i __A)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpopcountw_v16hi_mask ((__v16hi) __A,
|
||||
(__v16hi) __W,
|
||||
(__mmask16) __U);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_maskz_popcnt_epi16 (__mmask16 __U, __m256i __A)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpopcountw_v16hi_mask ((__v16hi) __A,
|
||||
(__v16hi)
|
||||
_mm256_avx512_setzero_si256 (),
|
||||
(__mmask16) __U);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask_popcnt_epi8 (__m128i __W, __mmask16 __U, __m128i __A)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpopcountb_v16qi_mask ((__v16qi) __A,
|
||||
(__v16qi) __W,
|
||||
(__mmask16) __U);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_maskz_popcnt_epi8 (__mmask16 __U, __m128i __A)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpopcountb_v16qi_mask ((__v16qi) __A,
|
||||
(__v16qi)
|
||||
_mm_avx512_setzero_si128 (),
|
||||
(__mmask16) __U);
|
||||
}
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask_popcnt_epi16 (__m128i __W, __mmask8 __U, __m128i __A)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpopcountw_v8hi_mask ((__v8hi) __A,
|
||||
(__v8hi) __W,
|
||||
(__mmask8) __U);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_maskz_popcnt_epi16 (__mmask8 __U, __m128i __A)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpopcountw_v8hi_mask ((__v8hi) __A,
|
||||
(__v8hi)
|
||||
_mm_avx512_setzero_si128 (),
|
||||
(__mmask8) __U);
|
||||
}
|
||||
#ifdef __DISABLE_AVX512BITALGVL__
|
||||
#undef __DISABLE_AVX512BITALGVL__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVX512BITALGVL__ */
|
||||
|
||||
#endif /* _AVX512BITALGVLINTRIN_H_INCLUDED */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,184 @@
|
||||
/* Copyright (C) 2013-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _IMMINTRIN_H_INCLUDED
|
||||
#error "Never use <avx512cdintrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AVX512CDINTRIN_H_INCLUDED
|
||||
#define _AVX512CDINTRIN_H_INCLUDED
|
||||
|
||||
#ifndef __AVX512CD__
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avx512cd,evex512")
|
||||
#define __DISABLE_AVX512CD__
|
||||
#endif /* __AVX512CD__ */
|
||||
|
||||
/* Internal data types for implementing the intrinsics. */
|
||||
typedef long long __v8di __attribute__ ((__vector_size__ (64)));
|
||||
typedef int __v16si __attribute__ ((__vector_size__ (64)));
|
||||
|
||||
/* The Intel API is flexible enough that we must allow aliasing with other
|
||||
vector types, and their scalar components. */
|
||||
typedef long long __m512i __attribute__ ((__vector_size__ (64), __may_alias__));
|
||||
typedef double __m512d __attribute__ ((__vector_size__ (64), __may_alias__));
|
||||
|
||||
typedef unsigned char __mmask8;
|
||||
typedef unsigned short __mmask16;
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_conflict_epi32 (__m512i __A)
|
||||
{
|
||||
return (__m512i)
|
||||
__builtin_ia32_vpconflictsi_512_mask ((__v16si) __A,
|
||||
(__v16si) _mm512_setzero_si512 (),
|
||||
(__mmask16) -1);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_conflict_epi32 (__m512i __W, __mmask16 __U, __m512i __A)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpconflictsi_512_mask ((__v16si) __A,
|
||||
(__v16si) __W,
|
||||
(__mmask16) __U);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_conflict_epi32 (__mmask16 __U, __m512i __A)
|
||||
{
|
||||
return (__m512i)
|
||||
__builtin_ia32_vpconflictsi_512_mask ((__v16si) __A,
|
||||
(__v16si) _mm512_setzero_si512 (),
|
||||
(__mmask16) __U);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_conflict_epi64 (__m512i __A)
|
||||
{
|
||||
return (__m512i)
|
||||
__builtin_ia32_vpconflictdi_512_mask ((__v8di) __A,
|
||||
(__v8di) _mm512_setzero_si512 (),
|
||||
(__mmask8) -1);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_conflict_epi64 (__m512i __W, __mmask8 __U, __m512i __A)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpconflictdi_512_mask ((__v8di) __A,
|
||||
(__v8di) __W,
|
||||
(__mmask8) __U);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_conflict_epi64 (__mmask8 __U, __m512i __A)
|
||||
{
|
||||
return (__m512i)
|
||||
__builtin_ia32_vpconflictdi_512_mask ((__v8di) __A,
|
||||
(__v8di) _mm512_setzero_si512 (),
|
||||
(__mmask8) __U);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_lzcnt_epi64 (__m512i __A)
|
||||
{
|
||||
return (__m512i)
|
||||
__builtin_ia32_vplzcntq_512_mask ((__v8di) __A,
|
||||
(__v8di) _mm512_setzero_si512 (),
|
||||
(__mmask8) -1);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_lzcnt_epi64 (__m512i __W, __mmask8 __U, __m512i __A)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vplzcntq_512_mask ((__v8di) __A,
|
||||
(__v8di) __W,
|
||||
(__mmask8) __U);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_lzcnt_epi64 (__mmask8 __U, __m512i __A)
|
||||
{
|
||||
return (__m512i)
|
||||
__builtin_ia32_vplzcntq_512_mask ((__v8di) __A,
|
||||
(__v8di) _mm512_setzero_si512 (),
|
||||
(__mmask8) __U);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_lzcnt_epi32 (__m512i __A)
|
||||
{
|
||||
return (__m512i)
|
||||
__builtin_ia32_vplzcntd_512_mask ((__v16si) __A,
|
||||
(__v16si) _mm512_setzero_si512 (),
|
||||
(__mmask16) -1);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_lzcnt_epi32 (__m512i __W, __mmask16 __U, __m512i __A)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vplzcntd_512_mask ((__v16si) __A,
|
||||
(__v16si) __W,
|
||||
(__mmask16) __U);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_lzcnt_epi32 (__mmask16 __U, __m512i __A)
|
||||
{
|
||||
return (__m512i)
|
||||
__builtin_ia32_vplzcntd_512_mask ((__v16si) __A,
|
||||
(__v16si) _mm512_setzero_si512 (),
|
||||
(__mmask16) __U);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_broadcastmb_epi64 (__mmask8 __A)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_broadcastmb512 (__A);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_broadcastmw_epi32 (__mmask16 __A)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_broadcastmw512 (__A);
|
||||
}
|
||||
|
||||
#ifdef __DISABLE_AVX512CD__
|
||||
#undef __DISABLE_AVX512CD__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVX512CD__ */
|
||||
|
||||
#endif /* _AVX512CDINTRIN_H_INCLUDED */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,536 @@
|
||||
/* Copyright (C) 2013-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _IMMINTRIN_H_INCLUDED
|
||||
#error "Never use <avx512erintrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AVX512ERINTRIN_H_INCLUDED
|
||||
#define _AVX512ERINTRIN_H_INCLUDED
|
||||
|
||||
#ifndef __AVX512ER__
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avx512er,evex512")
|
||||
#define __DISABLE_AVX512ER__
|
||||
#endif /* __AVX512ER__ */
|
||||
|
||||
/* Internal data types for implementing the intrinsics. */
|
||||
typedef double __v8df __attribute__ ((__vector_size__ (64)));
|
||||
typedef float __v16sf __attribute__ ((__vector_size__ (64)));
|
||||
|
||||
/* The Intel API is flexible enough that we must allow aliasing with other
|
||||
vector types, and their scalar components. */
|
||||
typedef float __m512 __attribute__ ((__vector_size__ (64), __may_alias__));
|
||||
typedef double __m512d __attribute__ ((__vector_size__ (64), __may_alias__));
|
||||
|
||||
typedef unsigned char __mmask8;
|
||||
typedef unsigned short __mmask16;
|
||||
|
||||
#ifdef __OPTIMIZE__
|
||||
extern __inline __m512d
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_exp2a23_round_pd (__m512d __A, int __R)
|
||||
{
|
||||
return (__m512d) __builtin_ia32_exp2pd_mask ((__v8df) __A,
|
||||
(__v8df) _mm512_undefined_pd (),
|
||||
(__mmask8) -1, __R);
|
||||
}
|
||||
|
||||
extern __inline __m512d
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_exp2a23_round_pd (__m512d __W, __mmask8 __U, __m512d __A, int __R)
|
||||
{
|
||||
return (__m512d) __builtin_ia32_exp2pd_mask ((__v8df) __A,
|
||||
(__v8df) __W,
|
||||
(__mmask8) __U, __R);
|
||||
}
|
||||
|
||||
extern __inline __m512d
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_exp2a23_round_pd (__mmask8 __U, __m512d __A, int __R)
|
||||
{
|
||||
return (__m512d) __builtin_ia32_exp2pd_mask ((__v8df) __A,
|
||||
(__v8df) _mm512_setzero_pd (),
|
||||
(__mmask8) __U, __R);
|
||||
}
|
||||
|
||||
extern __inline __m512
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_exp2a23_round_ps (__m512 __A, int __R)
|
||||
{
|
||||
return (__m512) __builtin_ia32_exp2ps_mask ((__v16sf) __A,
|
||||
(__v16sf) _mm512_undefined_ps (),
|
||||
(__mmask16) -1, __R);
|
||||
}
|
||||
|
||||
extern __inline __m512
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_exp2a23_round_ps (__m512 __W, __mmask16 __U, __m512 __A, int __R)
|
||||
{
|
||||
return (__m512) __builtin_ia32_exp2ps_mask ((__v16sf) __A,
|
||||
(__v16sf) __W,
|
||||
(__mmask16) __U, __R);
|
||||
}
|
||||
|
||||
extern __inline __m512
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_exp2a23_round_ps (__mmask16 __U, __m512 __A, int __R)
|
||||
{
|
||||
return (__m512) __builtin_ia32_exp2ps_mask ((__v16sf) __A,
|
||||
(__v16sf) _mm512_setzero_ps (),
|
||||
(__mmask16) __U, __R);
|
||||
}
|
||||
|
||||
extern __inline __m512d
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_rcp28_round_pd (__m512d __A, int __R)
|
||||
{
|
||||
return (__m512d) __builtin_ia32_rcp28pd_mask ((__v8df) __A,
|
||||
(__v8df) _mm512_undefined_pd (),
|
||||
(__mmask8) -1, __R);
|
||||
}
|
||||
|
||||
extern __inline __m512d
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_rcp28_round_pd (__m512d __W, __mmask8 __U, __m512d __A, int __R)
|
||||
{
|
||||
return (__m512d) __builtin_ia32_rcp28pd_mask ((__v8df) __A,
|
||||
(__v8df) __W,
|
||||
(__mmask8) __U, __R);
|
||||
}
|
||||
|
||||
extern __inline __m512d
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_rcp28_round_pd (__mmask8 __U, __m512d __A, int __R)
|
||||
{
|
||||
return (__m512d) __builtin_ia32_rcp28pd_mask ((__v8df) __A,
|
||||
(__v8df) _mm512_setzero_pd (),
|
||||
(__mmask8) __U, __R);
|
||||
}
|
||||
|
||||
extern __inline __m512
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_rcp28_round_ps (__m512 __A, int __R)
|
||||
{
|
||||
return (__m512) __builtin_ia32_rcp28ps_mask ((__v16sf) __A,
|
||||
(__v16sf) _mm512_undefined_ps (),
|
||||
(__mmask16) -1, __R);
|
||||
}
|
||||
|
||||
extern __inline __m512
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_rcp28_round_ps (__m512 __W, __mmask16 __U, __m512 __A, int __R)
|
||||
{
|
||||
return (__m512) __builtin_ia32_rcp28ps_mask ((__v16sf) __A,
|
||||
(__v16sf) __W,
|
||||
(__mmask16) __U, __R);
|
||||
}
|
||||
|
||||
extern __inline __m512
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_rcp28_round_ps (__mmask16 __U, __m512 __A, int __R)
|
||||
{
|
||||
return (__m512) __builtin_ia32_rcp28ps_mask ((__v16sf) __A,
|
||||
(__v16sf) _mm512_setzero_ps (),
|
||||
(__mmask16) __U, __R);
|
||||
}
|
||||
|
||||
extern __inline __m128d
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_rcp28_round_sd (__m128d __A, __m128d __B, int __R)
|
||||
{
|
||||
return (__m128d) __builtin_ia32_rcp28sd_round ((__v2df) __B,
|
||||
(__v2df) __A,
|
||||
__R);
|
||||
}
|
||||
|
||||
extern __inline __m128d
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask_rcp28_round_sd (__m128d __W, __mmask8 __U, __m128d __A,
|
||||
__m128d __B, int __R)
|
||||
{
|
||||
return (__m128d) __builtin_ia32_rcp28sd_mask_round ((__v2df) __B,
|
||||
(__v2df) __A,
|
||||
(__v2df) __W,
|
||||
__U,
|
||||
__R);
|
||||
}
|
||||
|
||||
extern __inline __m128d
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_maskz_rcp28_round_sd (__mmask8 __U, __m128d __A, __m128d __B, int __R)
|
||||
{
|
||||
return (__m128d) __builtin_ia32_rcp28sd_mask_round ((__v2df) __B,
|
||||
(__v2df) __A,
|
||||
(__v2df)
|
||||
_mm_setzero_pd (),
|
||||
__U,
|
||||
__R);
|
||||
}
|
||||
|
||||
extern __inline __m128
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_rcp28_round_ss (__m128 __A, __m128 __B, int __R)
|
||||
{
|
||||
return (__m128) __builtin_ia32_rcp28ss_round ((__v4sf) __B,
|
||||
(__v4sf) __A,
|
||||
__R);
|
||||
}
|
||||
|
||||
extern __inline __m128
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask_rcp28_round_ss (__m128 __W, __mmask8 __U, __m128 __A,
|
||||
__m128 __B, int __R)
|
||||
{
|
||||
return (__m128) __builtin_ia32_rcp28ss_mask_round ((__v4sf) __B,
|
||||
(__v4sf) __A,
|
||||
(__v4sf) __W,
|
||||
__U,
|
||||
__R);
|
||||
}
|
||||
|
||||
extern __inline __m128
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_maskz_rcp28_round_ss (__mmask8 __U, __m128 __A, __m128 __B, int __R)
|
||||
{
|
||||
return (__m128) __builtin_ia32_rcp28ss_mask_round ((__v4sf) __B,
|
||||
(__v4sf) __A,
|
||||
(__v4sf)
|
||||
_mm_setzero_ps (),
|
||||
__U,
|
||||
__R);
|
||||
}
|
||||
|
||||
extern __inline __m512d
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_rsqrt28_round_pd (__m512d __A, int __R)
|
||||
{
|
||||
return (__m512d) __builtin_ia32_rsqrt28pd_mask ((__v8df) __A,
|
||||
(__v8df) _mm512_undefined_pd (),
|
||||
(__mmask8) -1, __R);
|
||||
}
|
||||
|
||||
extern __inline __m512d
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_rsqrt28_round_pd (__m512d __W, __mmask8 __U, __m512d __A, int __R)
|
||||
{
|
||||
return (__m512d) __builtin_ia32_rsqrt28pd_mask ((__v8df) __A,
|
||||
(__v8df) __W,
|
||||
(__mmask8) __U, __R);
|
||||
}
|
||||
|
||||
extern __inline __m512d
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_rsqrt28_round_pd (__mmask8 __U, __m512d __A, int __R)
|
||||
{
|
||||
return (__m512d) __builtin_ia32_rsqrt28pd_mask ((__v8df) __A,
|
||||
(__v8df) _mm512_setzero_pd (),
|
||||
(__mmask8) __U, __R);
|
||||
}
|
||||
|
||||
extern __inline __m512
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_rsqrt28_round_ps (__m512 __A, int __R)
|
||||
{
|
||||
return (__m512) __builtin_ia32_rsqrt28ps_mask ((__v16sf) __A,
|
||||
(__v16sf) _mm512_undefined_ps (),
|
||||
(__mmask16) -1, __R);
|
||||
}
|
||||
|
||||
extern __inline __m512
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_rsqrt28_round_ps (__m512 __W, __mmask16 __U, __m512 __A, int __R)
|
||||
{
|
||||
return (__m512) __builtin_ia32_rsqrt28ps_mask ((__v16sf) __A,
|
||||
(__v16sf) __W,
|
||||
(__mmask16) __U, __R);
|
||||
}
|
||||
|
||||
extern __inline __m512
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_rsqrt28_round_ps (__mmask16 __U, __m512 __A, int __R)
|
||||
{
|
||||
return (__m512) __builtin_ia32_rsqrt28ps_mask ((__v16sf) __A,
|
||||
(__v16sf) _mm512_setzero_ps (),
|
||||
(__mmask16) __U, __R);
|
||||
}
|
||||
|
||||
extern __inline __m128d
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_rsqrt28_round_sd (__m128d __A, __m128d __B, int __R)
|
||||
{
|
||||
return (__m128d) __builtin_ia32_rsqrt28sd_round ((__v2df) __B,
|
||||
(__v2df) __A,
|
||||
__R);
|
||||
}
|
||||
|
||||
extern __inline __m128d
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask_rsqrt28_round_sd (__m128d __W, __mmask8 __U, __m128d __A,
|
||||
__m128d __B, int __R)
|
||||
{
|
||||
return (__m128d) __builtin_ia32_rsqrt28sd_mask_round ((__v2df) __B,
|
||||
(__v2df) __A,
|
||||
(__v2df) __W,
|
||||
__U,
|
||||
__R);
|
||||
}
|
||||
|
||||
extern __inline __m128d
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_maskz_rsqrt28_round_sd (__mmask8 __U, __m128d __A, __m128d __B, int __R)
|
||||
{
|
||||
return (__m128d) __builtin_ia32_rsqrt28sd_mask_round ((__v2df) __B,
|
||||
(__v2df) __A,
|
||||
(__v2df)
|
||||
_mm_setzero_pd (),
|
||||
__U,
|
||||
__R);
|
||||
}
|
||||
|
||||
extern __inline __m128
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_rsqrt28_round_ss (__m128 __A, __m128 __B, int __R)
|
||||
{
|
||||
return (__m128) __builtin_ia32_rsqrt28ss_round ((__v4sf) __B,
|
||||
(__v4sf) __A,
|
||||
__R);
|
||||
}
|
||||
|
||||
extern __inline __m128
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask_rsqrt28_round_ss (__m128 __W, __mmask8 __U, __m128 __A,
|
||||
__m128 __B, int __R)
|
||||
{
|
||||
return (__m128) __builtin_ia32_rsqrt28ss_mask_round ((__v4sf) __B,
|
||||
(__v4sf) __A,
|
||||
(__v4sf) __W,
|
||||
__U,
|
||||
__R);
|
||||
}
|
||||
|
||||
extern __inline __m128
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_maskz_rsqrt28_round_ss (__mmask8 __U, __m128 __A, __m128 __B, int __R)
|
||||
{
|
||||
return (__m128) __builtin_ia32_rsqrt28ss_mask_round ((__v4sf) __B,
|
||||
(__v4sf) __A,
|
||||
(__v4sf)
|
||||
_mm_setzero_ps (),
|
||||
__U,
|
||||
__R);
|
||||
}
|
||||
|
||||
#else
|
||||
#define _mm512_exp2a23_round_pd(A, C) \
|
||||
__builtin_ia32_exp2pd_mask(A, (__v8df)_mm512_setzero_pd(), -1, C)
|
||||
|
||||
#define _mm512_mask_exp2a23_round_pd(W, U, A, C) \
|
||||
__builtin_ia32_exp2pd_mask(A, W, U, C)
|
||||
|
||||
#define _mm512_maskz_exp2a23_round_pd(U, A, C) \
|
||||
__builtin_ia32_exp2pd_mask(A, (__v8df)_mm512_setzero_pd(), U, C)
|
||||
|
||||
#define _mm512_exp2a23_round_ps(A, C) \
|
||||
__builtin_ia32_exp2ps_mask(A, (__v16sf)_mm512_setzero_ps(), -1, C)
|
||||
|
||||
#define _mm512_mask_exp2a23_round_ps(W, U, A, C) \
|
||||
__builtin_ia32_exp2ps_mask(A, W, U, C)
|
||||
|
||||
#define _mm512_maskz_exp2a23_round_ps(U, A, C) \
|
||||
__builtin_ia32_exp2ps_mask(A, (__v16sf)_mm512_setzero_ps(), U, C)
|
||||
|
||||
#define _mm512_rcp28_round_pd(A, C) \
|
||||
__builtin_ia32_rcp28pd_mask(A, (__v8df)_mm512_setzero_pd(), -1, C)
|
||||
|
||||
#define _mm512_mask_rcp28_round_pd(W, U, A, C) \
|
||||
__builtin_ia32_rcp28pd_mask(A, W, U, C)
|
||||
|
||||
#define _mm512_maskz_rcp28_round_pd(U, A, C) \
|
||||
__builtin_ia32_rcp28pd_mask(A, (__v8df)_mm512_setzero_pd(), U, C)
|
||||
|
||||
#define _mm512_rcp28_round_ps(A, C) \
|
||||
__builtin_ia32_rcp28ps_mask(A, (__v16sf)_mm512_setzero_ps(), -1, C)
|
||||
|
||||
#define _mm512_mask_rcp28_round_ps(W, U, A, C) \
|
||||
__builtin_ia32_rcp28ps_mask(A, W, U, C)
|
||||
|
||||
#define _mm512_maskz_rcp28_round_ps(U, A, C) \
|
||||
__builtin_ia32_rcp28ps_mask(A, (__v16sf)_mm512_setzero_ps(), U, C)
|
||||
|
||||
#define _mm512_rsqrt28_round_pd(A, C) \
|
||||
__builtin_ia32_rsqrt28pd_mask(A, (__v8df)_mm512_setzero_pd(), -1, C)
|
||||
|
||||
#define _mm512_mask_rsqrt28_round_pd(W, U, A, C) \
|
||||
__builtin_ia32_rsqrt28pd_mask(A, W, U, C)
|
||||
|
||||
#define _mm512_maskz_rsqrt28_round_pd(U, A, C) \
|
||||
__builtin_ia32_rsqrt28pd_mask(A, (__v8df)_mm512_setzero_pd(), U, C)
|
||||
|
||||
#define _mm512_rsqrt28_round_ps(A, C) \
|
||||
__builtin_ia32_rsqrt28ps_mask(A, (__v16sf)_mm512_setzero_ps(), -1, C)
|
||||
|
||||
#define _mm512_mask_rsqrt28_round_ps(W, U, A, C) \
|
||||
__builtin_ia32_rsqrt28ps_mask(A, W, U, C)
|
||||
|
||||
#define _mm512_maskz_rsqrt28_round_ps(U, A, C) \
|
||||
__builtin_ia32_rsqrt28ps_mask(A, (__v16sf)_mm512_setzero_ps(), U, C)
|
||||
|
||||
#define _mm_rcp28_round_sd(A, B, R) \
|
||||
__builtin_ia32_rcp28sd_round(A, B, R)
|
||||
|
||||
#define _mm_mask_rcp28_round_sd(W, U, A, B, R) \
|
||||
__builtin_ia32_rcp28sd_mask_round ((A), (B), (W), (U), (R))
|
||||
|
||||
#define _mm_maskz_rcp28_round_sd(U, A, B, R) \
|
||||
__builtin_ia32_rcp28sd_mask_round ((A), (B), (__v2df) _mm_setzero_pd (), \
|
||||
(U), (R))
|
||||
|
||||
#define _mm_rcp28_round_ss(A, B, R) \
|
||||
__builtin_ia32_rcp28ss_round(A, B, R)
|
||||
|
||||
#define _mm_mask_rcp28_round_ss(W, U, A, B, R) \
|
||||
__builtin_ia32_rcp28ss_mask_round ((A), (B), (W), (U), (R))
|
||||
|
||||
#define _mm_maskz_rcp28_round_ss(U, A, B, R) \
|
||||
__builtin_ia32_rcp28ss_mask_round ((A), (B), (__v4sf) _mm_setzero_ps (), \
|
||||
(U), (R))
|
||||
|
||||
#define _mm_rsqrt28_round_sd(A, B, R) \
|
||||
__builtin_ia32_rsqrt28sd_round(A, B, R)
|
||||
|
||||
#define _mm_mask_rsqrt28_round_sd(W, U, A, B, R) \
|
||||
__builtin_ia32_rsqrt28sd_mask_round ((A), (B), (W), (U), (R))
|
||||
|
||||
#define _mm_maskz_rsqrt28_round_sd(U, A, B, R) \
|
||||
__builtin_ia32_rsqrt28sd_mask_round ((A), (B), (__v2df) _mm_setzero_pd (),\
|
||||
(U), (R))
|
||||
|
||||
#define _mm_rsqrt28_round_ss(A, B, R) \
|
||||
__builtin_ia32_rsqrt28ss_round(A, B, R)
|
||||
|
||||
#define _mm_mask_rsqrt28_round_ss(W, U, A, B, R) \
|
||||
__builtin_ia32_rsqrt28ss_mask_round ((A), (B), (W), (U), (R))
|
||||
|
||||
#define _mm_maskz_rsqrt28_round_ss(U, A, B, R) \
|
||||
__builtin_ia32_rsqrt28ss_mask_round ((A), (B), (__v4sf) _mm_setzero_ps (),\
|
||||
(U), (R))
|
||||
|
||||
#endif
|
||||
|
||||
#define _mm_mask_rcp28_sd(W, U, A, B)\
|
||||
_mm_mask_rcp28_round_sd ((W), (U), (A), (B), _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm_maskz_rcp28_sd(U, A, B)\
|
||||
_mm_maskz_rcp28_round_sd ((U), (A), (B), _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm_mask_rcp28_ss(W, U, A, B)\
|
||||
_mm_mask_rcp28_round_ss ((W), (U), (A), (B), _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm_maskz_rcp28_ss(U, A, B)\
|
||||
_mm_maskz_rcp28_round_ss ((U), (A), (B), _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm_mask_rsqrt28_sd(W, U, A, B)\
|
||||
_mm_mask_rsqrt28_round_sd ((W), (U), (A), (B), _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm_maskz_rsqrt28_sd(U, A, B)\
|
||||
_mm_maskz_rsqrt28_round_sd ((U), (A), (B), _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm_mask_rsqrt28_ss(W, U, A, B)\
|
||||
_mm_mask_rsqrt28_round_ss ((W), (U), (A), (B), _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm_maskz_rsqrt28_ss(U, A, B)\
|
||||
_mm_maskz_rsqrt28_round_ss ((U), (A), (B), _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm512_exp2a23_pd(A) \
|
||||
_mm512_exp2a23_round_pd(A, _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm512_mask_exp2a23_pd(W, U, A) \
|
||||
_mm512_mask_exp2a23_round_pd(W, U, A, _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm512_maskz_exp2a23_pd(U, A) \
|
||||
_mm512_maskz_exp2a23_round_pd(U, A, _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm512_exp2a23_ps(A) \
|
||||
_mm512_exp2a23_round_ps(A, _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm512_mask_exp2a23_ps(W, U, A) \
|
||||
_mm512_mask_exp2a23_round_ps(W, U, A, _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm512_maskz_exp2a23_ps(U, A) \
|
||||
_mm512_maskz_exp2a23_round_ps(U, A, _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm512_rcp28_pd(A) \
|
||||
_mm512_rcp28_round_pd(A, _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm512_mask_rcp28_pd(W, U, A) \
|
||||
_mm512_mask_rcp28_round_pd(W, U, A, _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm512_maskz_rcp28_pd(U, A) \
|
||||
_mm512_maskz_rcp28_round_pd(U, A, _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm512_rcp28_ps(A) \
|
||||
_mm512_rcp28_round_ps(A, _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm512_mask_rcp28_ps(W, U, A) \
|
||||
_mm512_mask_rcp28_round_ps(W, U, A, _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm512_maskz_rcp28_ps(U, A) \
|
||||
_mm512_maskz_rcp28_round_ps(U, A, _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm512_rsqrt28_pd(A) \
|
||||
_mm512_rsqrt28_round_pd(A, _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm512_mask_rsqrt28_pd(W, U, A) \
|
||||
_mm512_mask_rsqrt28_round_pd(W, U, A, _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm512_maskz_rsqrt28_pd(U, A) \
|
||||
_mm512_maskz_rsqrt28_round_pd(U, A, _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm512_rsqrt28_ps(A) \
|
||||
_mm512_rsqrt28_round_ps(A, _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm512_mask_rsqrt28_ps(W, U, A) \
|
||||
_mm512_mask_rsqrt28_round_ps(W, U, A, _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm512_maskz_rsqrt28_ps(U, A) \
|
||||
_mm512_maskz_rsqrt28_round_ps(U, A, _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm_rcp28_sd(A, B) \
|
||||
__builtin_ia32_rcp28sd_round(B, A, _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm_rcp28_ss(A, B) \
|
||||
__builtin_ia32_rcp28ss_round(B, A, _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm_rsqrt28_sd(A, B) \
|
||||
__builtin_ia32_rsqrt28sd_round(B, A, _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#define _mm_rsqrt28_ss(A, B) \
|
||||
__builtin_ia32_rsqrt28ss_round(B, A, _MM_FROUND_CUR_DIRECTION)
|
||||
|
||||
#ifdef __DISABLE_AVX512ER__
|
||||
#undef __DISABLE_AVX512ER__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVX512ER__ */
|
||||
|
||||
#endif /* _AVX512ERINTRIN_H_INCLUDED */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,104 @@
|
||||
/* Copyright (C) 2013-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _IMMINTRIN_H_INCLUDED
|
||||
#error "Never use <avx512ifmaintrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AVX512IFMAINTRIN_H_INCLUDED
|
||||
#define _AVX512IFMAINTRIN_H_INCLUDED
|
||||
|
||||
#if !defined (__AVX512IFMA__) || !defined (__EVEX512__)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avx512ifma,evex512")
|
||||
#define __DISABLE_AVX512IFMA__
|
||||
#endif /* __AVX512IFMA__ */
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_madd52lo_epu64 (__m512i __X, __m512i __Y, __m512i __Z)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpmadd52luq512_mask ((__v8di) __X,
|
||||
(__v8di) __Y,
|
||||
(__v8di) __Z,
|
||||
(__mmask8) -1);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_madd52hi_epu64 (__m512i __X, __m512i __Y, __m512i __Z)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpmadd52huq512_mask ((__v8di) __X,
|
||||
(__v8di) __Y,
|
||||
(__v8di) __Z,
|
||||
(__mmask8) -1);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_madd52lo_epu64 (__m512i __W, __mmask8 __M, __m512i __X,
|
||||
__m512i __Y)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpmadd52luq512_mask ((__v8di) __W,
|
||||
(__v8di) __X,
|
||||
(__v8di) __Y,
|
||||
(__mmask8) __M);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_madd52hi_epu64 (__m512i __W, __mmask8 __M, __m512i __X,
|
||||
__m512i __Y)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpmadd52huq512_mask ((__v8di) __W,
|
||||
(__v8di) __X,
|
||||
(__v8di) __Y,
|
||||
(__mmask8) __M);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_madd52lo_epu64 (__mmask8 __M, __m512i __X, __m512i __Y, __m512i __Z)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpmadd52luq512_maskz ((__v8di) __X,
|
||||
(__v8di) __Y,
|
||||
(__v8di) __Z,
|
||||
(__mmask8) __M);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_madd52hi_epu64 (__mmask8 __M, __m512i __X, __m512i __Y, __m512i __Z)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpmadd52huq512_maskz ((__v8di) __X,
|
||||
(__v8di) __Y,
|
||||
(__v8di) __Z,
|
||||
(__mmask8) __M);
|
||||
}
|
||||
|
||||
#ifdef __DISABLE_AVX512IFMA__
|
||||
#undef __DISABLE_AVX512IFMA__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVX512IFMA__ */
|
||||
|
||||
#endif /* _AVX512IFMAINTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,145 @@
|
||||
/* Copyright (C) 2013-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _IMMINTRIN_H_INCLUDED
|
||||
#error "Never use <avx512ifmavlintrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AVX512IFMAVLINTRIN_H_INCLUDED
|
||||
#define _AVX512IFMAVLINTRIN_H_INCLUDED
|
||||
|
||||
#if !defined(__AVX512VL__) || !defined(__AVX512IFMA__) || defined (__EVEX512__)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avx512ifma,avx512vl,no-evex512")
|
||||
#define __DISABLE_AVX512IFMAVL__
|
||||
#endif /* __AVX512IFMAVL__ */
|
||||
|
||||
#define _mm_madd52lo_epu64(A, B, C) \
|
||||
((__m128i) __builtin_ia32_vpmadd52luq128 ((__v2di) (A), \
|
||||
(__v2di) (B), \
|
||||
(__v2di) (C)))
|
||||
|
||||
#define _mm_madd52hi_epu64(A, B, C) \
|
||||
((__m128i) __builtin_ia32_vpmadd52huq128 ((__v2di) (A), \
|
||||
(__v2di) (B), \
|
||||
(__v2di) (C)))
|
||||
|
||||
#define _mm256_madd52lo_epu64(A, B, C) \
|
||||
((__m256i) __builtin_ia32_vpmadd52luq256 ((__v4di) (A), \
|
||||
(__v4di) (B), \
|
||||
(__v4di) (C)))
|
||||
|
||||
|
||||
#define _mm256_madd52hi_epu64(A, B, C) \
|
||||
((__m256i) __builtin_ia32_vpmadd52huq256 ((__v4di) (A), \
|
||||
(__v4di) (B), \
|
||||
(__v4di) (C)))
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask_madd52lo_epu64 (__m128i __W, __mmask8 __M, __m128i __X, __m128i __Y)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpmadd52luq128_mask ((__v2di) __W,
|
||||
(__v2di) __X,
|
||||
(__v2di) __Y,
|
||||
(__mmask8) __M);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask_madd52hi_epu64 (__m128i __W, __mmask8 __M, __m128i __X, __m128i __Y)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpmadd52huq128_mask ((__v2di) __W,
|
||||
(__v2di) __X,
|
||||
(__v2di) __Y,
|
||||
(__mmask8) __M);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_mask_madd52lo_epu64 (__m256i __W, __mmask8 __M, __m256i __X,
|
||||
__m256i __Y)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpmadd52luq256_mask ((__v4di) __W,
|
||||
(__v4di) __X,
|
||||
(__v4di) __Y,
|
||||
(__mmask8) __M);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_mask_madd52hi_epu64 (__m256i __W, __mmask8 __M, __m256i __X,
|
||||
__m256i __Y)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpmadd52huq256_mask ((__v4di) __W,
|
||||
(__v4di) __X,
|
||||
(__v4di) __Y,
|
||||
(__mmask8) __M);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_maskz_madd52lo_epu64 (__mmask8 __M, __m128i __X, __m128i __Y, __m128i __Z)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpmadd52luq128_maskz ((__v2di) __X,
|
||||
(__v2di) __Y,
|
||||
(__v2di) __Z,
|
||||
(__mmask8) __M);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_maskz_madd52hi_epu64 (__mmask8 __M, __m128i __X, __m128i __Y, __m128i __Z)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpmadd52huq128_maskz ((__v2di) __X,
|
||||
(__v2di) __Y,
|
||||
(__v2di) __Z,
|
||||
(__mmask8) __M);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_maskz_madd52lo_epu64 (__mmask8 __M, __m256i __X, __m256i __Y, __m256i __Z)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpmadd52luq256_maskz ((__v4di) __X,
|
||||
(__v4di) __Y,
|
||||
(__v4di) __Z,
|
||||
(__mmask8) __M);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_maskz_madd52hi_epu64 (__mmask8 __M, __m256i __X, __m256i __Y, __m256i __Z)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpmadd52huq256_maskz ((__v4di) __X,
|
||||
(__v4di) __Y,
|
||||
(__v4di) __Z,
|
||||
(__mmask8) __M);
|
||||
}
|
||||
|
||||
#ifdef __DISABLE_AVX512IFMAVL__
|
||||
#undef __DISABLE_AVX512IFMAVL__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVX512IFMAVL__ */
|
||||
|
||||
#endif /* _AVX512IFMAVLINTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,269 @@
|
||||
/* Copyright (C) 2013-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _IMMINTRIN_H_INCLUDED
|
||||
#error "Never use <avx512pfintrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AVX512PFINTRIN_H_INCLUDED
|
||||
#define _AVX512PFINTRIN_H_INCLUDED
|
||||
|
||||
#ifndef __AVX512PF__
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avx512pf,evex512")
|
||||
#define __DISABLE_AVX512PF__
|
||||
#endif /* __AVX512PF__ */
|
||||
|
||||
/* Internal data types for implementing the intrinsics. */
|
||||
typedef long long __v8di __attribute__ ((__vector_size__ (64)));
|
||||
typedef int __v16si __attribute__ ((__vector_size__ (64)));
|
||||
|
||||
/* The Intel API is flexible enough that we must allow aliasing with other
|
||||
vector types, and their scalar components. */
|
||||
typedef long long __m512i __attribute__ ((__vector_size__ (64), __may_alias__));
|
||||
|
||||
typedef unsigned char __mmask8;
|
||||
typedef unsigned short __mmask16;
|
||||
|
||||
#ifdef __OPTIMIZE__
|
||||
extern __inline void
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_prefetch_i32gather_pd (__m256i __index, void const *__addr,
|
||||
int __scale, int __hint)
|
||||
{
|
||||
__builtin_ia32_gatherpfdpd ((__mmask8) 0xFF, (__v8si) __index, __addr,
|
||||
__scale, __hint);
|
||||
}
|
||||
|
||||
extern __inline void
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_prefetch_i32gather_ps (__m512i __index, void const *__addr,
|
||||
int __scale, int __hint)
|
||||
{
|
||||
__builtin_ia32_gatherpfdps ((__mmask16) 0xFFFF, (__v16si) __index, __addr,
|
||||
__scale, __hint);
|
||||
}
|
||||
|
||||
extern __inline void
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_prefetch_i32gather_pd (__m256i __index, __mmask8 __mask,
|
||||
void const *__addr, int __scale, int __hint)
|
||||
{
|
||||
__builtin_ia32_gatherpfdpd (__mask, (__v8si) __index, __addr, __scale,
|
||||
__hint);
|
||||
}
|
||||
|
||||
extern __inline void
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_prefetch_i32gather_ps (__m512i __index, __mmask16 __mask,
|
||||
void const *__addr, int __scale, int __hint)
|
||||
{
|
||||
__builtin_ia32_gatherpfdps (__mask, (__v16si) __index, __addr, __scale,
|
||||
__hint);
|
||||
}
|
||||
|
||||
extern __inline void
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_prefetch_i64gather_pd (__m512i __index, void const *__addr,
|
||||
int __scale, int __hint)
|
||||
{
|
||||
__builtin_ia32_gatherpfqpd ((__mmask8) 0xFF, (__v8di) __index, __addr,
|
||||
__scale, __hint);
|
||||
}
|
||||
|
||||
extern __inline void
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_prefetch_i64gather_ps (__m512i __index, void const *__addr,
|
||||
int __scale, int __hint)
|
||||
{
|
||||
__builtin_ia32_gatherpfqps ((__mmask8) 0xFF, (__v8di) __index, __addr,
|
||||
__scale, __hint);
|
||||
}
|
||||
|
||||
extern __inline void
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_prefetch_i64gather_pd (__m512i __index, __mmask8 __mask,
|
||||
void const *__addr, int __scale, int __hint)
|
||||
{
|
||||
__builtin_ia32_gatherpfqpd (__mask, (__v8di) __index, __addr, __scale,
|
||||
__hint);
|
||||
}
|
||||
|
||||
extern __inline void
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_prefetch_i64gather_ps (__m512i __index, __mmask8 __mask,
|
||||
void const *__addr, int __scale, int __hint)
|
||||
{
|
||||
__builtin_ia32_gatherpfqps (__mask, (__v8di) __index, __addr, __scale,
|
||||
__hint);
|
||||
}
|
||||
|
||||
extern __inline void
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_prefetch_i32scatter_pd (void *__addr, __m256i __index, int __scale,
|
||||
int __hint)
|
||||
{
|
||||
__builtin_ia32_scatterpfdpd ((__mmask8) 0xFF, (__v8si) __index, __addr,
|
||||
__scale, __hint);
|
||||
}
|
||||
|
||||
extern __inline void
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_prefetch_i32scatter_ps (void *__addr, __m512i __index, int __scale,
|
||||
int __hint)
|
||||
{
|
||||
__builtin_ia32_scatterpfdps ((__mmask16) 0xFFFF, (__v16si) __index, __addr,
|
||||
__scale, __hint);
|
||||
}
|
||||
|
||||
extern __inline void
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_prefetch_i32scatter_pd (void *__addr, __mmask8 __mask,
|
||||
__m256i __index, int __scale, int __hint)
|
||||
{
|
||||
__builtin_ia32_scatterpfdpd (__mask, (__v8si) __index, __addr, __scale,
|
||||
__hint);
|
||||
}
|
||||
|
||||
extern __inline void
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_prefetch_i32scatter_ps (void *__addr, __mmask16 __mask,
|
||||
__m512i __index, int __scale, int __hint)
|
||||
{
|
||||
__builtin_ia32_scatterpfdps (__mask, (__v16si) __index, __addr, __scale,
|
||||
__hint);
|
||||
}
|
||||
|
||||
extern __inline void
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_prefetch_i64scatter_pd (void *__addr, __m512i __index, int __scale,
|
||||
int __hint)
|
||||
{
|
||||
__builtin_ia32_scatterpfqpd ((__mmask8) 0xFF, (__v8di) __index,__addr,
|
||||
__scale, __hint);
|
||||
}
|
||||
|
||||
extern __inline void
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_prefetch_i64scatter_ps (void *__addr, __m512i __index, int __scale,
|
||||
int __hint)
|
||||
{
|
||||
__builtin_ia32_scatterpfqps ((__mmask8) 0xFF, (__v8di) __index, __addr,
|
||||
__scale, __hint);
|
||||
}
|
||||
|
||||
extern __inline void
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_prefetch_i64scatter_pd (void *__addr, __mmask8 __mask,
|
||||
__m512i __index, int __scale, int __hint)
|
||||
{
|
||||
__builtin_ia32_scatterpfqpd (__mask, (__v8di) __index, __addr, __scale,
|
||||
__hint);
|
||||
}
|
||||
|
||||
extern __inline void
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_prefetch_i64scatter_ps (void *__addr, __mmask8 __mask,
|
||||
__m512i __index, int __scale, int __hint)
|
||||
{
|
||||
__builtin_ia32_scatterpfqps (__mask, (__v8di) __index, __addr, __scale,
|
||||
__hint);
|
||||
}
|
||||
|
||||
#else
|
||||
#define _mm512_prefetch_i32gather_pd(INDEX, ADDR, SCALE, HINT) \
|
||||
__builtin_ia32_gatherpfdpd ((__mmask8)0xFF, (__v8si)(__m256i) (INDEX), \
|
||||
(void const *) (ADDR), (int) (SCALE), \
|
||||
(int) (HINT))
|
||||
|
||||
#define _mm512_prefetch_i32gather_ps(INDEX, ADDR, SCALE, HINT) \
|
||||
__builtin_ia32_gatherpfdps ((__mmask16)0xFFFF, (__v16si)(__m512i) (INDEX), \
|
||||
(void const *) (ADDR), (int) (SCALE), \
|
||||
(int) (HINT))
|
||||
|
||||
#define _mm512_mask_prefetch_i32gather_pd(INDEX, MASK, ADDR, SCALE, HINT) \
|
||||
__builtin_ia32_gatherpfdpd ((__mmask8) (MASK), (__v8si)(__m256i) (INDEX), \
|
||||
(void const *) (ADDR), (int) (SCALE), \
|
||||
(int) (HINT))
|
||||
|
||||
#define _mm512_mask_prefetch_i32gather_ps(INDEX, MASK, ADDR, SCALE, HINT) \
|
||||
__builtin_ia32_gatherpfdps ((__mmask16) (MASK), (__v16si)(__m512i) (INDEX),\
|
||||
(void const *) (ADDR), (int) (SCALE), \
|
||||
(int) (HINT))
|
||||
|
||||
#define _mm512_prefetch_i64gather_pd(INDEX, ADDR, SCALE, HINT) \
|
||||
__builtin_ia32_gatherpfqpd ((__mmask8)0xFF, (__v8di)(__m512i) (INDEX), \
|
||||
(void *) (ADDR), (int) (SCALE), (int) (HINT))
|
||||
|
||||
#define _mm512_prefetch_i64gather_ps(INDEX, ADDR, SCALE, HINT) \
|
||||
__builtin_ia32_gatherpfqps ((__mmask8)0xFF, (__v8di)(__m512i) (INDEX), \
|
||||
(void *) (ADDR), (int) (SCALE), (int) (HINT))
|
||||
|
||||
#define _mm512_mask_prefetch_i64gather_pd(INDEX, MASK, ADDR, SCALE, HINT) \
|
||||
__builtin_ia32_gatherpfqpd ((__mmask8) (MASK), (__v8di)(__m512i) (INDEX), \
|
||||
(void *) (ADDR), (int) (SCALE), (int) (HINT))
|
||||
|
||||
#define _mm512_mask_prefetch_i64gather_ps(INDEX, MASK, ADDR, SCALE, HINT) \
|
||||
__builtin_ia32_gatherpfqps ((__mmask8) (MASK), (__v8di)(__m512i) (INDEX), \
|
||||
(void *) (ADDR), (int) (SCALE), (int) (HINT))
|
||||
|
||||
#define _mm512_prefetch_i32scatter_pd(ADDR, INDEX, SCALE, HINT) \
|
||||
__builtin_ia32_scatterpfdpd ((__mmask8)0xFF, (__v8si)(__m256i) (INDEX), \
|
||||
(void *) (ADDR), (int) (SCALE), (int) (HINT))
|
||||
|
||||
#define _mm512_prefetch_i32scatter_ps(ADDR, INDEX, SCALE, HINT) \
|
||||
__builtin_ia32_scatterpfdps ((__mmask16)0xFFFF, (__v16si)(__m512i) (INDEX),\
|
||||
(void *) (ADDR), (int) (SCALE), (int) (HINT))
|
||||
|
||||
#define _mm512_mask_prefetch_i32scatter_pd(ADDR, MASK, INDEX, SCALE, HINT) \
|
||||
__builtin_ia32_scatterpfdpd ((__mmask8) (MASK), (__v8si)(__m256i) (INDEX), \
|
||||
(void *) (ADDR), (int) (SCALE), (int) (HINT))
|
||||
|
||||
#define _mm512_mask_prefetch_i32scatter_ps(ADDR, MASK, INDEX, SCALE, HINT) \
|
||||
__builtin_ia32_scatterpfdps ((__mmask16) (MASK), \
|
||||
(__v16si)(__m512i) (INDEX), \
|
||||
(void *) (ADDR), (int) (SCALE), (int) (HINT))
|
||||
|
||||
#define _mm512_prefetch_i64scatter_pd(ADDR, INDEX, SCALE, HINT) \
|
||||
__builtin_ia32_scatterpfqpd ((__mmask8)0xFF, (__v8di)(__m512i) (INDEX), \
|
||||
(void *) (ADDR), (int) (SCALE), (int) (HINT))
|
||||
|
||||
#define _mm512_prefetch_i64scatter_ps(ADDR, INDEX, SCALE, HINT) \
|
||||
__builtin_ia32_scatterpfqps ((__mmask8)0xFF, (__v8di)(__m512i) (INDEX), \
|
||||
(void *) (ADDR), (int) (SCALE), (int) (HINT))
|
||||
|
||||
#define _mm512_mask_prefetch_i64scatter_pd(ADDR, MASK, INDEX, SCALE, HINT) \
|
||||
__builtin_ia32_scatterpfqpd ((__mmask8) (MASK), (__v8di)(__m512i) (INDEX), \
|
||||
(void *) (ADDR), (int) (SCALE), (int) (HINT))
|
||||
|
||||
#define _mm512_mask_prefetch_i64scatter_ps(ADDR, MASK, INDEX, SCALE, HINT) \
|
||||
__builtin_ia32_scatterpfqps ((__mmask8) (MASK), (__v8di)(__m512i) (INDEX), \
|
||||
(void *) (ADDR), (int) (SCALE), (int) (HINT))
|
||||
#endif
|
||||
|
||||
#ifdef __DISABLE_AVX512PF__
|
||||
#undef __DISABLE_AVX512PF__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVX512PF__ */
|
||||
|
||||
#endif /* _AVX512PFINTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,545 @@
|
||||
/* Copyright (C) 2013-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _IMMINTRIN_H_INCLUDED
|
||||
#error "Never use <avx512vbmi2intrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef __AVX512VBMI2INTRIN_H_INCLUDED
|
||||
#define __AVX512VBMI2INTRIN_H_INCLUDED
|
||||
|
||||
#if !defined(__AVX512VBMI2__) || !defined (__EVEX512__)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avx512vbmi2,evex512")
|
||||
#define __DISABLE_AVX512VBMI2__
|
||||
#endif /* __AVX512VBMI2__ */
|
||||
|
||||
#ifdef __OPTIMIZE__
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_shrdi_epi16 (__m512i __A, __m512i __B, int __C)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpshrd_v32hi ((__v32hi)__A, (__v32hi) __B,
|
||||
__C);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_shrdi_epi32 (__m512i __A, __m512i __B, int __C)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpshrd_v16si ((__v16si)__A, (__v16si) __B,
|
||||
__C);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_shrdi_epi32 (__m512i __A, __mmask16 __B, __m512i __C, __m512i __D,
|
||||
int __E)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpshrd_v16si_mask ((__v16si)__C,
|
||||
(__v16si) __D, __E, (__v16si) __A, (__mmask16)__B);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_shrdi_epi32 (__mmask16 __A, __m512i __B, __m512i __C, int __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpshrd_v16si_mask ((__v16si)__B,
|
||||
(__v16si) __C, __D, (__v16si) _mm512_setzero_si512 (), (__mmask16)__A);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_shrdi_epi64 (__m512i __A, __m512i __B, int __C)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpshrd_v8di ((__v8di)__A, (__v8di) __B, __C);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_shrdi_epi64 (__m512i __A, __mmask8 __B, __m512i __C, __m512i __D,
|
||||
int __E)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpshrd_v8di_mask ((__v8di)__C, (__v8di) __D,
|
||||
__E, (__v8di) __A, (__mmask8)__B);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_shrdi_epi64 (__mmask8 __A, __m512i __B, __m512i __C, int __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpshrd_v8di_mask ((__v8di)__B, (__v8di) __C,
|
||||
__D, (__v8di) _mm512_setzero_si512 (), (__mmask8)__A);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_shldi_epi16 (__m512i __A, __m512i __B, int __C)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpshld_v32hi ((__v32hi)__A, (__v32hi) __B,
|
||||
__C);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_shldi_epi32 (__m512i __A, __m512i __B, int __C)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpshld_v16si ((__v16si)__A, (__v16si) __B,
|
||||
__C);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_shldi_epi32 (__m512i __A, __mmask16 __B, __m512i __C, __m512i __D,
|
||||
int __E)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpshld_v16si_mask ((__v16si)__C,
|
||||
(__v16si) __D, __E, (__v16si) __A, (__mmask16)__B);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_shldi_epi32 (__mmask16 __A, __m512i __B, __m512i __C, int __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpshld_v16si_mask ((__v16si)__B,
|
||||
(__v16si) __C, __D, (__v16si) _mm512_setzero_si512 (), (__mmask16)__A);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_shldi_epi64 (__m512i __A, __m512i __B, int __C)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpshld_v8di ((__v8di)__A, (__v8di) __B, __C);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_shldi_epi64 (__m512i __A, __mmask8 __B, __m512i __C, __m512i __D,
|
||||
int __E)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpshld_v8di_mask ((__v8di)__C, (__v8di) __D,
|
||||
__E, (__v8di) __A, (__mmask8)__B);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_shldi_epi64 (__mmask8 __A, __m512i __B, __m512i __C, int __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpshld_v8di_mask ((__v8di)__B, (__v8di) __C,
|
||||
__D, (__v8di) _mm512_setzero_si512 (), (__mmask8)__A);
|
||||
}
|
||||
#else
|
||||
#define _mm512_shrdi_epi16(A, B, C) \
|
||||
((__m512i) __builtin_ia32_vpshrd_v32hi ((__v32hi)(__m512i)(A), \
|
||||
(__v32hi)(__m512i)(B),(int)(C)))
|
||||
#define _mm512_shrdi_epi32(A, B, C) \
|
||||
((__m512i) __builtin_ia32_vpshrd_v16si ((__v16si)(__m512i)(A), \
|
||||
(__v16si)(__m512i)(B),(int)(C)))
|
||||
#define _mm512_mask_shrdi_epi32(A, B, C, D, E) \
|
||||
((__m512i) __builtin_ia32_vpshrd_v16si_mask ((__v16si)(__m512i)(C), \
|
||||
(__v16si)(__m512i)(D), \
|
||||
(int)(E), \
|
||||
(__v16si)(__m512i)(A), \
|
||||
(__mmask16)(B)))
|
||||
#define _mm512_maskz_shrdi_epi32(A, B, C, D) \
|
||||
((__m512i) \
|
||||
__builtin_ia32_vpshrd_v16si_mask ((__v16si)(__m512i)(B), \
|
||||
(__v16si)(__m512i)(C),(int)(D), \
|
||||
(__v16si)(__m512i)_mm512_setzero_si512 (), \
|
||||
(__mmask16)(A)))
|
||||
#define _mm512_shrdi_epi64(A, B, C) \
|
||||
((__m512i) __builtin_ia32_vpshrd_v8di ((__v8di)(__m512i)(A), \
|
||||
(__v8di)(__m512i)(B),(int)(C)))
|
||||
#define _mm512_mask_shrdi_epi64(A, B, C, D, E) \
|
||||
((__m512i) __builtin_ia32_vpshrd_v8di_mask ((__v8di)(__m512i)(C), \
|
||||
(__v8di)(__m512i)(D), (int)(E), \
|
||||
(__v8di)(__m512i)(A), \
|
||||
(__mmask8)(B)))
|
||||
#define _mm512_maskz_shrdi_epi64(A, B, C, D) \
|
||||
((__m512i) \
|
||||
__builtin_ia32_vpshrd_v8di_mask ((__v8di)(__m512i)(B), \
|
||||
(__v8di)(__m512i)(C),(int)(D), \
|
||||
(__v8di)(__m512i)_mm512_setzero_si512 (), \
|
||||
(__mmask8)(A)))
|
||||
#define _mm512_shldi_epi16(A, B, C) \
|
||||
((__m512i) __builtin_ia32_vpshld_v32hi ((__v32hi)(__m512i)(A), \
|
||||
(__v32hi)(__m512i)(B),(int)(C)))
|
||||
#define _mm512_shldi_epi32(A, B, C) \
|
||||
((__m512i) __builtin_ia32_vpshld_v16si ((__v16si)(__m512i)(A), \
|
||||
(__v16si)(__m512i)(B),(int)(C)))
|
||||
#define _mm512_mask_shldi_epi32(A, B, C, D, E) \
|
||||
((__m512i) __builtin_ia32_vpshld_v16si_mask ((__v16si)(__m512i)(C), \
|
||||
(__v16si)(__m512i)(D), \
|
||||
(int)(E), \
|
||||
(__v16si)(__m512i)(A), \
|
||||
(__mmask16)(B)))
|
||||
#define _mm512_maskz_shldi_epi32(A, B, C, D) \
|
||||
((__m512i) \
|
||||
__builtin_ia32_vpshld_v16si_mask ((__v16si)(__m512i)(B), \
|
||||
(__v16si)(__m512i)(C),(int)(D), \
|
||||
(__v16si)(__m512i)_mm512_setzero_si512 (), \
|
||||
(__mmask16)(A)))
|
||||
#define _mm512_shldi_epi64(A, B, C) \
|
||||
((__m512i) __builtin_ia32_vpshld_v8di ((__v8di)(__m512i)(A), \
|
||||
(__v8di)(__m512i)(B), (int)(C)))
|
||||
#define _mm512_mask_shldi_epi64(A, B, C, D, E) \
|
||||
((__m512i) __builtin_ia32_vpshld_v8di_mask ((__v8di)(__m512i)(C), \
|
||||
(__v8di)(__m512i)(D), (int)(E), \
|
||||
(__v8di)(__m512i)(A), \
|
||||
(__mmask8)(B)))
|
||||
#define _mm512_maskz_shldi_epi64(A, B, C, D) \
|
||||
((__m512i) \
|
||||
__builtin_ia32_vpshld_v8di_mask ((__v8di)(__m512i)(B), \
|
||||
(__v8di)(__m512i)(C),(int)(D), \
|
||||
(__v8di)(__m512i)_mm512_setzero_si512 (), \
|
||||
(__mmask8)(A)))
|
||||
#endif
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_shrdv_epi16 (__m512i __A, __m512i __B, __m512i __C)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpshrdv_v32hi ((__v32hi)__A, (__v32hi) __B,
|
||||
(__v32hi) __C);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_shrdv_epi32 (__m512i __A, __m512i __B, __m512i __C)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpshrdv_v16si ((__v16si)__A, (__v16si) __B,
|
||||
(__v16si) __C);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_shrdv_epi32 (__m512i __A, __mmask16 __B, __m512i __C, __m512i __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpshrdv_v16si_mask ((__v16si)__A,
|
||||
(__v16si) __C, (__v16si) __D, (__mmask16)__B);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_shrdv_epi32 (__mmask16 __A, __m512i __B, __m512i __C, __m512i __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpshrdv_v16si_maskz ((__v16si)__B,
|
||||
(__v16si) __C, (__v16si) __D, (__mmask16)__A);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_shrdv_epi64 (__m512i __A, __m512i __B, __m512i __C)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpshrdv_v8di ((__v8di)__A, (__v8di) __B,
|
||||
(__v8di) __C);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_shrdv_epi64 (__m512i __A, __mmask8 __B, __m512i __C, __m512i __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpshrdv_v8di_mask ((__v8di)__A, (__v8di) __C,
|
||||
(__v8di) __D, (__mmask8)__B);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_shrdv_epi64 (__mmask8 __A, __m512i __B, __m512i __C, __m512i __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpshrdv_v8di_maskz ((__v8di)__B, (__v8di) __C,
|
||||
(__v8di) __D, (__mmask8)__A);
|
||||
}
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_shldv_epi16 (__m512i __A, __m512i __B, __m512i __C)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpshldv_v32hi ((__v32hi)__A, (__v32hi) __B,
|
||||
(__v32hi) __C);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_shldv_epi32 (__m512i __A, __m512i __B, __m512i __C)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpshldv_v16si ((__v16si)__A, (__v16si) __B,
|
||||
(__v16si) __C);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_shldv_epi32 (__m512i __A, __mmask16 __B, __m512i __C, __m512i __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpshldv_v16si_mask ((__v16si)__A,
|
||||
(__v16si) __C, (__v16si) __D, (__mmask16)__B);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_shldv_epi32 (__mmask16 __A, __m512i __B, __m512i __C, __m512i __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpshldv_v16si_maskz ((__v16si)__B,
|
||||
(__v16si) __C, (__v16si) __D, (__mmask16)__A);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_shldv_epi64 (__m512i __A, __m512i __B, __m512i __C)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpshldv_v8di ((__v8di)__A, (__v8di) __B,
|
||||
(__v8di) __C);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_shldv_epi64 (__m512i __A, __mmask8 __B, __m512i __C, __m512i __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpshldv_v8di_mask ((__v8di)__A, (__v8di) __C,
|
||||
(__v8di) __D, (__mmask8)__B);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_shldv_epi64 (__mmask8 __A, __m512i __B, __m512i __C, __m512i __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpshldv_v8di_maskz ((__v8di)__B, (__v8di) __C,
|
||||
(__v8di) __D, (__mmask8)__A);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_compress_epi8 (__m512i __A, __mmask64 __B, __m512i __C)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_compressqi512_mask ((__v64qi)__C,
|
||||
(__v64qi)__A, (__mmask64)__B);
|
||||
}
|
||||
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_compress_epi8 (__mmask64 __A, __m512i __B)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_compressqi512_mask ((__v64qi)__B,
|
||||
(__v64qi)_mm512_setzero_si512 (), (__mmask64)__A);
|
||||
}
|
||||
|
||||
|
||||
extern __inline void
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_compressstoreu_epi8 (void * __A, __mmask64 __B, __m512i __C)
|
||||
{
|
||||
__builtin_ia32_compressstoreuqi512_mask ((__v64qi *) __A, (__v64qi) __C,
|
||||
(__mmask64) __B);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_compress_epi16 (__m512i __A, __mmask32 __B, __m512i __C)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_compresshi512_mask ((__v32hi)__C,
|
||||
(__v32hi)__A, (__mmask32)__B);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_compress_epi16 (__mmask32 __A, __m512i __B)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_compresshi512_mask ((__v32hi)__B,
|
||||
(__v32hi)_mm512_setzero_si512 (), (__mmask32)__A);
|
||||
}
|
||||
|
||||
extern __inline void
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_compressstoreu_epi16 (void * __A, __mmask32 __B, __m512i __C)
|
||||
{
|
||||
__builtin_ia32_compressstoreuhi512_mask ((__v32hi *) __A, (__v32hi) __C,
|
||||
(__mmask32) __B);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_expand_epi8 (__m512i __A, __mmask64 __B, __m512i __C)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_expandqi512_mask ((__v64qi) __C,
|
||||
(__v64qi) __A,
|
||||
(__mmask64) __B);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_expand_epi8 (__mmask64 __A, __m512i __B)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_expandqi512_maskz ((__v64qi) __B,
|
||||
(__v64qi) _mm512_setzero_si512 (), (__mmask64) __A);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_expandloadu_epi8 (__m512i __A, __mmask64 __B, const void * __C)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_expandloadqi512_mask ((const __v64qi *) __C,
|
||||
(__v64qi) __A, (__mmask64) __B);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_expandloadu_epi8 (__mmask64 __A, const void * __B)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_expandloadqi512_maskz ((const __v64qi *) __B,
|
||||
(__v64qi) _mm512_setzero_si512 (), (__mmask64) __A);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_expand_epi16 (__m512i __A, __mmask32 __B, __m512i __C)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_expandhi512_mask ((__v32hi) __C,
|
||||
(__v32hi) __A,
|
||||
(__mmask32) __B);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_expand_epi16 (__mmask32 __A, __m512i __B)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_expandhi512_maskz ((__v32hi) __B,
|
||||
(__v32hi) _mm512_setzero_si512 (), (__mmask32) __A);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_expandloadu_epi16 (__m512i __A, __mmask32 __B, const void * __C)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_expandloadhi512_mask ((const __v32hi *) __C,
|
||||
(__v32hi) __A, (__mmask32) __B);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_expandloadu_epi16 (__mmask32 __A, const void * __B)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_expandloadhi512_maskz ((const __v32hi *) __B,
|
||||
(__v32hi) _mm512_setzero_si512 (), (__mmask32) __A);
|
||||
}
|
||||
|
||||
#ifdef __OPTIMIZE__
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_shrdi_epi16 (__m512i __A, __mmask32 __B, __m512i __C, __m512i __D,
|
||||
int __E)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpshrd_v32hi_mask ((__v32hi)__C,
|
||||
(__v32hi) __D, __E, (__v32hi) __A, (__mmask32)__B);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_shrdi_epi16 (__mmask32 __A, __m512i __B, __m512i __C, int __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpshrd_v32hi_mask ((__v32hi)__B,
|
||||
(__v32hi) __C, __D, (__v32hi) _mm512_setzero_si512 (), (__mmask32)__A);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_shldi_epi16 (__m512i __A, __mmask32 __B, __m512i __C, __m512i __D,
|
||||
int __E)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpshld_v32hi_mask ((__v32hi)__C,
|
||||
(__v32hi) __D, __E, (__v32hi) __A, (__mmask32)__B);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_shldi_epi16 (__mmask32 __A, __m512i __B, __m512i __C, int __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpshld_v32hi_mask ((__v32hi)__B,
|
||||
(__v32hi) __C, __D, (__v32hi) _mm512_setzero_si512 (), (__mmask32)__A);
|
||||
}
|
||||
|
||||
#else
|
||||
#define _mm512_mask_shrdi_epi16(A, B, C, D, E) \
|
||||
((__m512i) __builtin_ia32_vpshrd_v32hi_mask ((__v32hi)(__m512i)(C), \
|
||||
(__v32hi)(__m512i)(D), \
|
||||
(int)(E), \
|
||||
(__v32hi)(__m512i)(A), \
|
||||
(__mmask32)(B)))
|
||||
#define _mm512_maskz_shrdi_epi16(A, B, C, D) \
|
||||
((__m512i) \
|
||||
__builtin_ia32_vpshrd_v32hi_mask ((__v32hi)(__m512i)(B), \
|
||||
(__v32hi)(__m512i)(C),(int)(D), \
|
||||
(__v32hi)(__m512i)_mm512_setzero_si512 (), \
|
||||
(__mmask32)(A)))
|
||||
#define _mm512_mask_shldi_epi16(A, B, C, D, E) \
|
||||
((__m512i) __builtin_ia32_vpshld_v32hi_mask ((__v32hi)(__m512i)(C), \
|
||||
(__v32hi)(__m512i)(D), \
|
||||
(int)(E), \
|
||||
(__v32hi)(__m512i)(A), \
|
||||
(__mmask32)(B)))
|
||||
#define _mm512_maskz_shldi_epi16(A, B, C, D) \
|
||||
((__m512i) \
|
||||
__builtin_ia32_vpshld_v32hi_mask ((__v32hi)(__m512i)(B), \
|
||||
(__v32hi)(__m512i)(C),(int)(D), \
|
||||
(__v32hi)(__m512i)_mm512_setzero_si512 (), \
|
||||
(__mmask32)(A)))
|
||||
#endif
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_shrdv_epi16 (__m512i __A, __mmask32 __B, __m512i __C, __m512i __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpshrdv_v32hi_mask ((__v32hi)__A,
|
||||
(__v32hi) __C, (__v32hi) __D, (__mmask32)__B);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_shrdv_epi16 (__mmask32 __A, __m512i __B, __m512i __C, __m512i __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpshrdv_v32hi_maskz ((__v32hi)__B,
|
||||
(__v32hi) __C, (__v32hi) __D, (__mmask32)__A);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_shldv_epi16 (__m512i __A, __mmask32 __B, __m512i __C, __m512i __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpshldv_v32hi_mask ((__v32hi)__A,
|
||||
(__v32hi) __C, (__v32hi) __D, (__mmask32)__B);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_shldv_epi16 (__mmask32 __A, __m512i __B, __m512i __C, __m512i __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpshldv_v32hi_maskz ((__v32hi)__B,
|
||||
(__v32hi) __C, (__v32hi) __D, (__mmask32)__A);
|
||||
}
|
||||
|
||||
#ifdef __DISABLE_AVX512VBMI2__
|
||||
#undef __DISABLE_AVX512VBMI2__
|
||||
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVX512VBMI2__ */
|
||||
|
||||
#endif /* __AVX512VBMI2INTRIN_H_INCLUDED */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,158 @@
|
||||
/* Copyright (C) 2013-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _IMMINTRIN_H_INCLUDED
|
||||
#error "Never use <avx512vbmiintrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AVX512VBMIINTRIN_H_INCLUDED
|
||||
#define _AVX512VBMIINTRIN_H_INCLUDED
|
||||
|
||||
#if !defined (__AVX512VBMI__) || !defined (__EVEX512__)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avx512vbmi,evex512")
|
||||
#define __DISABLE_AVX512VBMI__
|
||||
#endif /* __AVX512VBMI__ */
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_multishift_epi64_epi8 (__m512i __W, __mmask64 __M, __m512i __X, __m512i __Y)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpmultishiftqb512_mask ((__v64qi) __X,
|
||||
(__v64qi) __Y,
|
||||
(__v64qi) __W,
|
||||
(__mmask64) __M);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_multishift_epi64_epi8 (__mmask64 __M, __m512i __X, __m512i __Y)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpmultishiftqb512_mask ((__v64qi) __X,
|
||||
(__v64qi) __Y,
|
||||
(__v64qi)
|
||||
_mm512_setzero_si512 (),
|
||||
(__mmask64) __M);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_multishift_epi64_epi8 (__m512i __X, __m512i __Y)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpmultishiftqb512_mask ((__v64qi) __X,
|
||||
(__v64qi) __Y,
|
||||
(__v64qi)
|
||||
_mm512_undefined_epi32 (),
|
||||
(__mmask64) -1);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_permutexvar_epi8 (__m512i __A, __m512i __B)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_permvarqi512_mask ((__v64qi) __B,
|
||||
(__v64qi) __A,
|
||||
(__v64qi)
|
||||
_mm512_undefined_epi32 (),
|
||||
(__mmask64) -1);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_permutexvar_epi8 (__mmask64 __M, __m512i __A,
|
||||
__m512i __B)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_permvarqi512_mask ((__v64qi) __B,
|
||||
(__v64qi) __A,
|
||||
(__v64qi)
|
||||
_mm512_setzero_si512(),
|
||||
(__mmask64) __M);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_permutexvar_epi8 (__m512i __W, __mmask64 __M, __m512i __A,
|
||||
__m512i __B)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_permvarqi512_mask ((__v64qi) __B,
|
||||
(__v64qi) __A,
|
||||
(__v64qi) __W,
|
||||
(__mmask64) __M);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_permutex2var_epi8 (__m512i __A, __m512i __I, __m512i __B)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpermt2varqi512_mask ((__v64qi) __I
|
||||
/* idx */ ,
|
||||
(__v64qi) __A,
|
||||
(__v64qi) __B,
|
||||
(__mmask64) -1);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_permutex2var_epi8 (__m512i __A, __mmask64 __U,
|
||||
__m512i __I, __m512i __B)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpermt2varqi512_mask ((__v64qi) __I
|
||||
/* idx */ ,
|
||||
(__v64qi) __A,
|
||||
(__v64qi) __B,
|
||||
(__mmask64)
|
||||
__U);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask2_permutex2var_epi8 (__m512i __A, __m512i __I,
|
||||
__mmask64 __U, __m512i __B)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpermi2varqi512_mask ((__v64qi) __A,
|
||||
(__v64qi) __I
|
||||
/* idx */ ,
|
||||
(__v64qi) __B,
|
||||
(__mmask64)
|
||||
__U);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_permutex2var_epi8 (__mmask64 __U, __m512i __A,
|
||||
__m512i __I, __m512i __B)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpermt2varqi512_maskz ((__v64qi) __I
|
||||
/* idx */ ,
|
||||
(__v64qi) __A,
|
||||
(__v64qi) __B,
|
||||
(__mmask64)
|
||||
__U);
|
||||
}
|
||||
|
||||
#ifdef __DISABLE_AVX512VBMI__
|
||||
#undef __DISABLE_AVX512VBMI__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVX512VBMI__ */
|
||||
|
||||
#endif /* _AVX512VBMIINTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,273 @@
|
||||
/* Copyright (C) 2013-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _IMMINTRIN_H_INCLUDED
|
||||
#error "Never use <avx512vbmivlintrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AVX512VBMIVLINTRIN_H_INCLUDED
|
||||
#define _AVX512VBMIVLINTRIN_H_INCLUDED
|
||||
|
||||
#if !defined(__AVX512VL__) || !defined(__AVX512VBMI__) || defined (__EVEX512__)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avx512vbmi,avx512vl,no-evex512")
|
||||
#define __DISABLE_AVX512VBMIVL__
|
||||
#endif /* __AVX512VBMIVL__ */
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_mask_multishift_epi64_epi8 (__m256i __W, __mmask32 __M, __m256i __X, __m256i __Y)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpmultishiftqb256_mask ((__v32qi) __X,
|
||||
(__v32qi) __Y,
|
||||
(__v32qi) __W,
|
||||
(__mmask32) __M);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_maskz_multishift_epi64_epi8 (__mmask32 __M, __m256i __X, __m256i __Y)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpmultishiftqb256_mask ((__v32qi) __X,
|
||||
(__v32qi) __Y,
|
||||
(__v32qi)
|
||||
_mm256_avx512_setzero_si256 (),
|
||||
(__mmask32) __M);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_multishift_epi64_epi8 (__m256i __X, __m256i __Y)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpmultishiftqb256_mask ((__v32qi) __X,
|
||||
(__v32qi) __Y,
|
||||
(__v32qi)
|
||||
_mm256_avx512_undefined_si256 (),
|
||||
(__mmask32) -1);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask_multishift_epi64_epi8 (__m128i __W, __mmask16 __M, __m128i __X, __m128i __Y)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpmultishiftqb128_mask ((__v16qi) __X,
|
||||
(__v16qi) __Y,
|
||||
(__v16qi) __W,
|
||||
(__mmask16) __M);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_maskz_multishift_epi64_epi8 (__mmask16 __M, __m128i __X, __m128i __Y)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpmultishiftqb128_mask ((__v16qi) __X,
|
||||
(__v16qi) __Y,
|
||||
(__v16qi)
|
||||
_mm_avx512_setzero_si128 (),
|
||||
(__mmask16) __M);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_multishift_epi64_epi8 (__m128i __X, __m128i __Y)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpmultishiftqb128_mask ((__v16qi) __X,
|
||||
(__v16qi) __Y,
|
||||
(__v16qi)
|
||||
_mm_avx512_undefined_si128 (),
|
||||
(__mmask16) -1);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_permutexvar_epi8 (__m256i __A, __m256i __B)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_permvarqi256_mask ((__v32qi) __B,
|
||||
(__v32qi) __A,
|
||||
(__v32qi)
|
||||
_mm256_avx512_undefined_si256 (),
|
||||
(__mmask32) -1);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_maskz_permutexvar_epi8 (__mmask32 __M, __m256i __A,
|
||||
__m256i __B)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_permvarqi256_mask ((__v32qi) __B,
|
||||
(__v32qi) __A,
|
||||
(__v32qi)
|
||||
_mm256_avx512_setzero_si256 (),
|
||||
(__mmask32) __M);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_mask_permutexvar_epi8 (__m256i __W, __mmask32 __M, __m256i __A,
|
||||
__m256i __B)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_permvarqi256_mask ((__v32qi) __B,
|
||||
(__v32qi) __A,
|
||||
(__v32qi) __W,
|
||||
(__mmask32) __M);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_permutexvar_epi8 (__m128i __A, __m128i __B)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_permvarqi128_mask ((__v16qi) __B,
|
||||
(__v16qi) __A,
|
||||
(__v16qi)
|
||||
_mm_avx512_undefined_si128 (),
|
||||
(__mmask16) -1);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_maskz_permutexvar_epi8 (__mmask16 __M, __m128i __A, __m128i __B)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_permvarqi128_mask ((__v16qi) __B,
|
||||
(__v16qi) __A,
|
||||
(__v16qi)
|
||||
_mm_avx512_setzero_si128 (),
|
||||
(__mmask16) __M);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask_permutexvar_epi8 (__m128i __W, __mmask16 __M, __m128i __A,
|
||||
__m128i __B)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_permvarqi128_mask ((__v16qi) __B,
|
||||
(__v16qi) __A,
|
||||
(__v16qi) __W,
|
||||
(__mmask16) __M);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_permutex2var_epi8 (__m256i __A, __m256i __I, __m256i __B)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpermt2varqi256_mask ((__v32qi) __I
|
||||
/* idx */ ,
|
||||
(__v32qi) __A,
|
||||
(__v32qi) __B,
|
||||
(__mmask32) -1);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_mask_permutex2var_epi8 (__m256i __A, __mmask32 __U,
|
||||
__m256i __I, __m256i __B)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpermt2varqi256_mask ((__v32qi) __I
|
||||
/* idx */ ,
|
||||
(__v32qi) __A,
|
||||
(__v32qi) __B,
|
||||
(__mmask32)
|
||||
__U);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_mask2_permutex2var_epi8 (__m256i __A, __m256i __I,
|
||||
__mmask32 __U, __m256i __B)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpermi2varqi256_mask ((__v32qi) __A,
|
||||
(__v32qi) __I
|
||||
/* idx */ ,
|
||||
(__v32qi) __B,
|
||||
(__mmask32)
|
||||
__U);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_maskz_permutex2var_epi8 (__mmask32 __U, __m256i __A,
|
||||
__m256i __I, __m256i __B)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpermt2varqi256_maskz ((__v32qi) __I
|
||||
/* idx */ ,
|
||||
(__v32qi) __A,
|
||||
(__v32qi) __B,
|
||||
(__mmask32)
|
||||
__U);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_permutex2var_epi8 (__m128i __A, __m128i __I, __m128i __B)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpermt2varqi128_mask ((__v16qi) __I
|
||||
/* idx */ ,
|
||||
(__v16qi) __A,
|
||||
(__v16qi) __B,
|
||||
(__mmask16) -1);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask_permutex2var_epi8 (__m128i __A, __mmask16 __U, __m128i __I,
|
||||
__m128i __B)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpermt2varqi128_mask ((__v16qi) __I
|
||||
/* idx */ ,
|
||||
(__v16qi) __A,
|
||||
(__v16qi) __B,
|
||||
(__mmask16)
|
||||
__U);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask2_permutex2var_epi8 (__m128i __A, __m128i __I, __mmask16 __U,
|
||||
__m128i __B)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpermi2varqi128_mask ((__v16qi) __A,
|
||||
(__v16qi) __I
|
||||
/* idx */ ,
|
||||
(__v16qi) __B,
|
||||
(__mmask16)
|
||||
__U);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_maskz_permutex2var_epi8 (__mmask16 __U, __m128i __A, __m128i __I,
|
||||
__m128i __B)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpermt2varqi128_maskz ((__v16qi) __I
|
||||
/* idx */ ,
|
||||
(__v16qi) __A,
|
||||
(__v16qi) __B,
|
||||
(__mmask16)
|
||||
__U);
|
||||
}
|
||||
|
||||
#ifdef __DISABLE_AVX512VBMIVL__
|
||||
#undef __DISABLE_AVX512VBMIVL__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVX512VBMIVL__ */
|
||||
|
||||
#endif /* _AVX512VBMIVLINTRIN_H_INCLUDED */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,144 @@
|
||||
/* Copyright (C) 2013-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _IMMINTRIN_H_INCLUDED
|
||||
#error "Never use <avx512vnniintrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef __AVX512VNNIINTRIN_H_INCLUDED
|
||||
#define __AVX512VNNIINTRIN_H_INCLUDED
|
||||
|
||||
#if !defined(__AVX512VNNI__) || !defined (__EVEX512__)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avx512vnni,evex512")
|
||||
#define __DISABLE_AVX512VNNI__
|
||||
#endif /* __AVX512VNNI__ */
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_dpbusd_epi32 (__m512i __A, __m512i __B, __m512i __C)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpdpbusd_v16si ((__v16si)__A, (__v16si) __B,
|
||||
(__v16si) __C);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_dpbusd_epi32 (__m512i __A, __mmask16 __B, __m512i __C, __m512i __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpdpbusd_v16si_mask ((__v16si)__A,
|
||||
(__v16si) __C, (__v16si) __D, (__mmask16)__B);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_dpbusd_epi32 (__mmask16 __A, __m512i __B, __m512i __C,
|
||||
__m512i __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpdpbusd_v16si_maskz ((__v16si)__B,
|
||||
(__v16si) __C, (__v16si) __D, (__mmask16)__A);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_dpbusds_epi32 (__m512i __A, __m512i __B, __m512i __C)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpdpbusds_v16si ((__v16si)__A, (__v16si) __B,
|
||||
(__v16si) __C);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_dpbusds_epi32 (__m512i __A, __mmask16 __B, __m512i __C,
|
||||
__m512i __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpdpbusds_v16si_mask ((__v16si)__A,
|
||||
(__v16si) __C, (__v16si) __D, (__mmask16)__B);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_dpbusds_epi32 (__mmask16 __A, __m512i __B, __m512i __C,
|
||||
__m512i __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpdpbusds_v16si_maskz ((__v16si)__B,
|
||||
(__v16si) __C, (__v16si) __D, (__mmask16)__A);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_dpwssd_epi32 (__m512i __A, __m512i __B, __m512i __C)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpdpwssd_v16si ((__v16si)__A, (__v16si) __B,
|
||||
(__v16si) __C);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_dpwssd_epi32 (__m512i __A, __mmask16 __B, __m512i __C, __m512i __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpdpwssd_v16si_mask ((__v16si)__A,
|
||||
(__v16si) __C, (__v16si) __D, (__mmask16)__B);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_dpwssd_epi32 (__mmask16 __A, __m512i __B, __m512i __C,
|
||||
__m512i __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpdpwssd_v16si_maskz ((__v16si)__B,
|
||||
(__v16si) __C, (__v16si) __D, (__mmask16)__A);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_dpwssds_epi32 (__m512i __A, __m512i __B, __m512i __C)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpdpwssds_v16si ((__v16si)__A, (__v16si) __B,
|
||||
(__v16si) __C);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_dpwssds_epi32 (__m512i __A, __mmask16 __B, __m512i __C,
|
||||
__m512i __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpdpwssds_v16si_mask ((__v16si)__A,
|
||||
(__v16si) __C, (__v16si) __D, (__mmask16)__B);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_dpwssds_epi32 (__mmask16 __A, __m512i __B, __m512i __C,
|
||||
__m512i __D)
|
||||
{
|
||||
return (__m512i)__builtin_ia32_vpdpwssds_v16si_maskz ((__v16si)__B,
|
||||
(__v16si) __C, (__v16si) __D, (__mmask16)__A);
|
||||
}
|
||||
|
||||
#ifdef __DISABLE_AVX512VNNI__
|
||||
#undef __DISABLE_AVX512VNNI__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVX512VNNI__ */
|
||||
|
||||
#endif /* __AVX512VNNIINTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,210 @@
|
||||
/* Copyright (C) 2013-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _IMMINTRIN_H_INCLUDED
|
||||
#error "Never use <avx512vnnivlintrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AVX512VNNIVLINTRIN_H_INCLUDED
|
||||
#define _AVX512VNNIVLINTRIN_H_INCLUDED
|
||||
|
||||
#if !defined(__AVX512VL__) || !defined(__AVX512VNNI__) || defined (__EVEX512__)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avx512vnni,avx512vl,no-evex512")
|
||||
#define __DISABLE_AVX512VNNIVL__
|
||||
#endif /* __AVX512VNNIVL__ */
|
||||
|
||||
#define _mm256_dpbusd_epi32(A, B, C) \
|
||||
((__m256i) __builtin_ia32_vpdpbusd_v8si ((__v8si) (A), \
|
||||
(__v8si) (B), \
|
||||
(__v8si) (C)))
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_mask_dpbusd_epi32 (__m256i __A, __mmask8 __B, __m256i __C, __m256i __D)
|
||||
{
|
||||
return (__m256i)__builtin_ia32_vpdpbusd_v8si_mask ((__v8si)__A, (__v8si) __C,
|
||||
(__v8si) __D, (__mmask8)__B);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_maskz_dpbusd_epi32 (__mmask8 __A, __m256i __B, __m256i __C, __m256i __D)
|
||||
{
|
||||
return (__m256i)__builtin_ia32_vpdpbusd_v8si_maskz ((__v8si)__B,
|
||||
(__v8si) __C, (__v8si) __D, (__mmask8)__A);
|
||||
}
|
||||
|
||||
#define _mm_dpbusd_epi32(A, B, C) \
|
||||
((__m128i) __builtin_ia32_vpdpbusd_v4si ((__v4si) (A), \
|
||||
(__v4si) (B), \
|
||||
(__v4si) (C)))
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask_dpbusd_epi32 (__m128i __A, __mmask8 __B, __m128i __C, __m128i __D)
|
||||
{
|
||||
return (__m128i)__builtin_ia32_vpdpbusd_v4si_mask ((__v4si)__A, (__v4si) __C,
|
||||
(__v4si) __D, (__mmask8)__B);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_maskz_dpbusd_epi32 (__mmask8 __A, __m128i __B, __m128i __C, __m128i __D)
|
||||
{
|
||||
return (__m128i)__builtin_ia32_vpdpbusd_v4si_maskz ((__v4si)__B,
|
||||
(__v4si) __C, (__v4si) __D, (__mmask8)__A);
|
||||
}
|
||||
|
||||
#define _mm256_dpbusds_epi32(A, B, C) \
|
||||
((__m256i) __builtin_ia32_vpdpbusds_v8si ((__v8si) (A), \
|
||||
(__v8si) (B), \
|
||||
(__v8si) (C)))
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_mask_dpbusds_epi32 (__m256i __A, __mmask8 __B, __m256i __C, __m256i __D)
|
||||
{
|
||||
return (__m256i)__builtin_ia32_vpdpbusds_v8si_mask ((__v8si)__A,
|
||||
(__v8si) __C, (__v8si) __D, (__mmask8)__B);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_maskz_dpbusds_epi32 (__mmask8 __A, __m256i __B, __m256i __C,
|
||||
__m256i __D)
|
||||
{
|
||||
return (__m256i)__builtin_ia32_vpdpbusds_v8si_maskz ((__v8si)__B,
|
||||
(__v8si) __C, (__v8si) __D, (__mmask8)__A);
|
||||
}
|
||||
|
||||
#define _mm_dpbusds_epi32(A, B, C) \
|
||||
((__m128i) __builtin_ia32_vpdpbusds_v4si ((__v4si) (A), \
|
||||
(__v4si) (B), \
|
||||
(__v4si) (C)))
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask_dpbusds_epi32 (__m128i __A, __mmask8 __B, __m128i __C, __m128i __D)
|
||||
{
|
||||
return (__m128i)__builtin_ia32_vpdpbusds_v4si_mask ((__v4si)__A,
|
||||
(__v4si) __C, (__v4si) __D, (__mmask8)__B);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_maskz_dpbusds_epi32 (__mmask8 __A, __m128i __B, __m128i __C, __m128i __D)
|
||||
{
|
||||
return (__m128i)__builtin_ia32_vpdpbusds_v4si_maskz ((__v4si)__B,
|
||||
(__v4si) __C, (__v4si) __D, (__mmask8)__A);
|
||||
}
|
||||
|
||||
#define _mm256_dpwssd_epi32(A, B, C) \
|
||||
((__m256i) __builtin_ia32_vpdpwssd_v8si ((__v8si) (A), \
|
||||
(__v8si) (B), \
|
||||
(__v8si) (C)))
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_mask_dpwssd_epi32 (__m256i __A, __mmask8 __B, __m256i __C, __m256i __D)
|
||||
{
|
||||
return (__m256i)__builtin_ia32_vpdpwssd_v8si_mask ((__v8si)__A, (__v8si) __C,
|
||||
(__v8si) __D, (__mmask8)__B);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_maskz_dpwssd_epi32 (__mmask8 __A, __m256i __B, __m256i __C, __m256i __D)
|
||||
{
|
||||
return (__m256i)__builtin_ia32_vpdpwssd_v8si_maskz ((__v8si)__B,
|
||||
(__v8si) __C, (__v8si) __D, (__mmask8)__A);
|
||||
}
|
||||
|
||||
#define _mm_dpwssd_epi32(A, B, C) \
|
||||
((__m128i) __builtin_ia32_vpdpwssd_v4si ((__v4si) (A), \
|
||||
(__v4si) (B), \
|
||||
(__v4si) (C)))
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask_dpwssd_epi32 (__m128i __A, __mmask8 __B, __m128i __C, __m128i __D)
|
||||
{
|
||||
return (__m128i)__builtin_ia32_vpdpwssd_v4si_mask ((__v4si)__A, (__v4si) __C,
|
||||
(__v4si) __D, (__mmask8)__B);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_maskz_dpwssd_epi32 (__mmask8 __A, __m128i __B, __m128i __C, __m128i __D)
|
||||
{
|
||||
return (__m128i)__builtin_ia32_vpdpwssd_v4si_maskz ((__v4si)__B,
|
||||
(__v4si) __C, (__v4si) __D, (__mmask8)__A);
|
||||
}
|
||||
|
||||
#define _mm256_dpwssds_epi32(A, B, C) \
|
||||
((__m256i) __builtin_ia32_vpdpwssds_v8si ((__v8si) (A), \
|
||||
(__v8si) (B), \
|
||||
(__v8si) (C)))
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_mask_dpwssds_epi32 (__m256i __A, __mmask8 __B, __m256i __C, __m256i __D)
|
||||
{
|
||||
return (__m256i)__builtin_ia32_vpdpwssds_v8si_mask ((__v8si)__A,
|
||||
(__v8si) __C, (__v8si) __D, (__mmask8)__B);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_maskz_dpwssds_epi32 (__mmask8 __A, __m256i __B, __m256i __C,
|
||||
__m256i __D)
|
||||
{
|
||||
return (__m256i)__builtin_ia32_vpdpwssds_v8si_maskz ((__v8si)__B,
|
||||
(__v8si) __C, (__v8si) __D, (__mmask8)__A);
|
||||
}
|
||||
|
||||
#define _mm_dpwssds_epi32(A, B, C) \
|
||||
((__m128i) __builtin_ia32_vpdpwssds_v4si ((__v4si) (A), \
|
||||
(__v4si) (B), \
|
||||
(__v4si) (C)))
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask_dpwssds_epi32 (__m128i __A, __mmask8 __B, __m128i __C, __m128i __D)
|
||||
{
|
||||
return (__m128i)__builtin_ia32_vpdpwssds_v4si_mask ((__v4si)__A,
|
||||
(__v4si) __C, (__v4si) __D, (__mmask8)__B);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_maskz_dpwssds_epi32 (__mmask8 __A, __m128i __B, __m128i __C, __m128i __D)
|
||||
{
|
||||
return (__m128i)__builtin_ia32_vpdpwssds_v4si_maskz ((__v4si)__B,
|
||||
(__v4si) __C, (__v4si) __D, (__mmask8)__A);
|
||||
}
|
||||
#ifdef __DISABLE_AVX512VNNIVL__
|
||||
#undef __DISABLE_AVX512VNNIVL__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVX512VNNIVL__ */
|
||||
#endif /* __DISABLE_AVX512VNNIVL__ */
|
||||
@@ -0,0 +1,58 @@
|
||||
/* Copyright (C) 2019-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#if !defined _IMMINTRIN_H_INCLUDED
|
||||
#error "Never use <avx512vp2intersectintrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AVX512VP2INTERSECTINTRIN_H_INCLUDED
|
||||
#define _AVX512VP2INTERSECTINTRIN_H_INCLUDED
|
||||
|
||||
#if !defined(__AVX512VP2INTERSECT__) || !defined (__EVEX512__)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avx512vp2intersect,evex512")
|
||||
#define __DISABLE_AVX512VP2INTERSECT__
|
||||
#endif /* __AVX512VP2INTERSECT__ */
|
||||
|
||||
extern __inline void
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_2intersect_epi32 (__m512i __A, __m512i __B, __mmask16 *__U,
|
||||
__mmask16 *__M)
|
||||
{
|
||||
__builtin_ia32_2intersectd512 (__U, __M, (__v16si) __A, (__v16si) __B);
|
||||
}
|
||||
|
||||
extern __inline void
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_2intersect_epi64 (__m512i __A, __m512i __B, __mmask8 *__U,
|
||||
__mmask8 *__M)
|
||||
{
|
||||
__builtin_ia32_2intersectq512 (__U, __M, (__v8di) __A, (__v8di) __B);
|
||||
}
|
||||
|
||||
#ifdef __DISABLE_AVX512VP2INTERSECT__
|
||||
#undef __DISABLE_AVX512VP2INTERSECT__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVX512VP2INTERSECT__ */
|
||||
|
||||
#endif /* _AVX512VP2INTERSECTINTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,73 @@
|
||||
/* Copyright (C) 2019-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#if !defined _IMMINTRIN_H_INCLUDED
|
||||
#error "Never use <avx512vp2intersectintrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AVX512VP2INTERSECTVLINTRIN_H_INCLUDED
|
||||
#define _AVX512VP2INTERSECTVLINTRIN_H_INCLUDED
|
||||
|
||||
#if !defined(__AVX512VP2INTERSECT__) || !defined(__AVX512VL__) \
|
||||
|| defined (__EVEX512__)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avx512vp2intersect,avx512vl,no-evex512")
|
||||
#define __DISABLE_AVX512VP2INTERSECTVL__
|
||||
#endif /* __AVX512VP2INTERSECTVL__ */
|
||||
|
||||
extern __inline void
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_2intersect_epi32 (__m128i __A, __m128i __B, __mmask8 *__U, __mmask8 *__M)
|
||||
{
|
||||
__builtin_ia32_2intersectd128 (__U, __M, (__v4si) __A, (__v4si) __B);
|
||||
}
|
||||
|
||||
extern __inline void
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_2intersect_epi32 (__m256i __A, __m256i __B, __mmask8 *__U,
|
||||
__mmask8 *__M)
|
||||
{
|
||||
__builtin_ia32_2intersectd256 (__U, __M, (__v8si) __A, (__v8si) __B);
|
||||
}
|
||||
|
||||
extern __inline void
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_2intersect_epi64 (__m128i __A, __m128i __B, __mmask8 *__U, __mmask8 *__M)
|
||||
{
|
||||
__builtin_ia32_2intersectq128 (__U, __M, (__v2di) __A, (__v2di) __B);
|
||||
}
|
||||
|
||||
extern __inline void
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_2intersect_epi64 (__m256i __A, __m256i __B, __mmask8 *__U,
|
||||
__mmask8 *__M)
|
||||
{
|
||||
__builtin_ia32_2intersectq256 (__U, __M, (__v4di) __A, (__v4di) __B);
|
||||
}
|
||||
|
||||
#ifdef __DISABLE_AVX512VP2INTERSECTVL__
|
||||
#undef __DISABLE_AVX512VP2INTERSECTVL__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVX512VP2INTERSECTVL__ */
|
||||
|
||||
#endif /* _AVX512VP2INTERSECTVLINTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,94 @@
|
||||
/* Copyright (C) 2017-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#if !defined _IMMINTRIN_H_INCLUDED
|
||||
# error "Never use <avx512vpopcntdqintrin.h> directly; include <x86intrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AVX512VPOPCNTDQINTRIN_H_INCLUDED
|
||||
#define _AVX512VPOPCNTDQINTRIN_H_INCLUDED
|
||||
|
||||
#if !defined (__AVX512VPOPCNTDQ__) || !defined (__EVEX512__)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avx512vpopcntdq,evex512")
|
||||
#define __DISABLE_AVX512VPOPCNTDQ__
|
||||
#endif /* __AVX512VPOPCNTDQ__ */
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_popcnt_epi32 (__m512i __A)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpopcountd_v16si ((__v16si) __A);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_popcnt_epi32 (__m512i __W, __mmask16 __U, __m512i __A)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpopcountd_v16si_mask ((__v16si) __A,
|
||||
(__v16si) __W,
|
||||
(__mmask16) __U);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_popcnt_epi32 (__mmask16 __U, __m512i __A)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpopcountd_v16si_mask ((__v16si) __A,
|
||||
(__v16si)
|
||||
_mm512_setzero_si512 (),
|
||||
(__mmask16) __U);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_popcnt_epi64 (__m512i __A)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpopcountq_v8di ((__v8di) __A);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_mask_popcnt_epi64 (__m512i __W, __mmask8 __U, __m512i __A)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpopcountq_v8di_mask ((__v8di) __A,
|
||||
(__v8di) __W,
|
||||
(__mmask8) __U);
|
||||
}
|
||||
|
||||
extern __inline __m512i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm512_maskz_popcnt_epi64 (__mmask8 __U, __m512i __A)
|
||||
{
|
||||
return (__m512i) __builtin_ia32_vpopcountq_v8di_mask ((__v8di) __A,
|
||||
(__v8di)
|
||||
_mm512_setzero_si512 (),
|
||||
(__mmask8) __U);
|
||||
}
|
||||
|
||||
#ifdef __DISABLE_AVX512VPOPCNTDQ__
|
||||
#undef __DISABLE_AVX512VPOPCNTDQ__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVX512VPOPCNTDQ__ */
|
||||
|
||||
#endif /* _AVX512VPOPCNTDQINTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,147 @@
|
||||
/* Copyright (C) 2017-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#if !defined _IMMINTRIN_H_INCLUDED
|
||||
# error "Never use <avx512vpopcntdqvlintrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AVX512VPOPCNTDQVLINTRIN_H_INCLUDED
|
||||
#define _AVX512VPOPCNTDQVLINTRIN_H_INCLUDED
|
||||
|
||||
#if !defined(__AVX512VPOPCNTDQ__) || !defined(__AVX512VL__) \
|
||||
|| defined (__EVEX512__)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avx512vpopcntdq,avx512vl,no-evex512")
|
||||
#define __DISABLE_AVX512VPOPCNTDQVL__
|
||||
#endif /* __AVX512VPOPCNTDQVL__ */
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_popcnt_epi32 (__m128i __A)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpopcountd_v4si ((__v4si) __A);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask_popcnt_epi32 (__m128i __W, __mmask16 __U, __m128i __A)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpopcountd_v4si_mask ((__v4si) __A,
|
||||
(__v4si) __W,
|
||||
(__mmask16) __U);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_maskz_popcnt_epi32 (__mmask16 __U, __m128i __A)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpopcountd_v4si_mask ((__v4si) __A,
|
||||
(__v4si)
|
||||
_mm_avx512_setzero_si128 (),
|
||||
(__mmask16) __U);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_popcnt_epi32 (__m256i __A)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpopcountd_v8si ((__v8si) __A);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_mask_popcnt_epi32 (__m256i __W, __mmask16 __U, __m256i __A)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpopcountd_v8si_mask ((__v8si) __A,
|
||||
(__v8si) __W,
|
||||
(__mmask16) __U);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_maskz_popcnt_epi32 (__mmask16 __U, __m256i __A)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpopcountd_v8si_mask ((__v8si) __A,
|
||||
(__v8si)
|
||||
_mm256_avx512_setzero_si256 (),
|
||||
(__mmask16) __U);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_popcnt_epi64 (__m128i __A)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpopcountq_v2di ((__v2di) __A);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mask_popcnt_epi64 (__m128i __W, __mmask8 __U, __m128i __A)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpopcountq_v2di_mask ((__v2di) __A,
|
||||
(__v2di) __W,
|
||||
(__mmask8) __U);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_maskz_popcnt_epi64 (__mmask8 __U, __m128i __A)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpopcountq_v2di_mask ((__v2di) __A,
|
||||
(__v2di)
|
||||
_mm_avx512_setzero_si128 (),
|
||||
(__mmask8) __U);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_popcnt_epi64 (__m256i __A)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpopcountq_v4di ((__v4di) __A);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_mask_popcnt_epi64 (__m256i __W, __mmask8 __U, __m256i __A)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpopcountq_v4di_mask ((__v4di) __A,
|
||||
(__v4di) __W,
|
||||
(__mmask8) __U);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_maskz_popcnt_epi64 (__mmask8 __U, __m256i __A)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpopcountq_v4di_mask ((__v4di) __A,
|
||||
(__v4di)
|
||||
_mm256_avx512_setzero_si256 (),
|
||||
(__mmask8) __U);
|
||||
}
|
||||
|
||||
#ifdef __DISABLE_AVX512VPOPCNTDQVL__
|
||||
#undef __DISABLE_AVX512VPOPCNTDQVL__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVX512VPOPCNTDQVL__ */
|
||||
|
||||
#endif /* _AVX512VPOPCNTDQVLINTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,78 @@
|
||||
/* Copyright (C) 2020-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _IMMINTRIN_H_INCLUDED
|
||||
#error "Never use <avxifmaintrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AVXIFMAINTRIN_H_INCLUDED
|
||||
#define _AVXIFMAINTRIN_H_INCLUDED
|
||||
|
||||
#ifndef __AVXIFMA__
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avxifma")
|
||||
#define __DISABLE_AVXIFMA__
|
||||
#endif /* __AVXIFMA__ */
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_madd52lo_avx_epu64 (__m128i __X, __m128i __Y, __m128i __Z)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpmadd52luq128 ((__v2di) __X,
|
||||
(__v2di) __Y,
|
||||
(__v2di) __Z);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_madd52hi_avx_epu64 (__m128i __X, __m128i __Y, __m128i __Z)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpmadd52huq128 ((__v2di) __X,
|
||||
(__v2di) __Y,
|
||||
(__v2di) __Z);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_madd52lo_avx_epu64 (__m256i __X, __m256i __Y, __m256i __Z)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpmadd52luq256 ((__v4di) __X,
|
||||
(__v4di) __Y,
|
||||
(__v4di) __Z);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_madd52hi_avx_epu64 (__m256i __X, __m256i __Y, __m256i __Z)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpmadd52huq256 ((__v4di) __X,
|
||||
(__v4di) __Y,
|
||||
(__v4di) __Z);
|
||||
}
|
||||
|
||||
#ifdef __DISABLE_AVXIFMA__
|
||||
#undef __DISABLE_AVXIFMA__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVXIFMA__ */
|
||||
|
||||
#endif /* _AVXIFMAINTRIN_H_INCLUDED */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,140 @@
|
||||
/* Copyright (C) 2021-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _IMMINTRIN_H_INCLUDED
|
||||
#error "Never use <avxneconvertintrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AVXNECONVERTINTRIN_H_INCLUDED
|
||||
#define _AVXNECONVERTINTRIN_H_INCLUDED
|
||||
|
||||
#ifndef __AVXNECONVERT__
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target ("avxneconvert")
|
||||
#define __DISABLE_AVXNECONVERT__
|
||||
#endif /* __AVXNECONVERT__ */
|
||||
|
||||
extern __inline __m128
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_bcstnebf16_ps (const void *__P)
|
||||
{
|
||||
return (__m128) __builtin_ia32_vbcstnebf162ps128 ((const __bf16 *) __P);
|
||||
}
|
||||
|
||||
extern __inline __m256
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_bcstnebf16_ps (const void *__P)
|
||||
{
|
||||
return (__m256) __builtin_ia32_vbcstnebf162ps256 ((const __bf16 *) __P);
|
||||
}
|
||||
|
||||
extern __inline __m128
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_bcstnesh_ps (const void *__P)
|
||||
{
|
||||
return (__m128) __builtin_ia32_vbcstnesh2ps128 ((const _Float16 *) __P);
|
||||
}
|
||||
|
||||
extern __inline __m256
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_bcstnesh_ps (const void *__P)
|
||||
{
|
||||
return (__m256) __builtin_ia32_vbcstnesh2ps256 ((const _Float16 *) __P);
|
||||
}
|
||||
|
||||
extern __inline __m128
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_cvtneebf16_ps (const __m128bh *__A)
|
||||
{
|
||||
return (__m128) __builtin_ia32_vcvtneebf162ps128 ((const __v8bf *) __A);
|
||||
}
|
||||
|
||||
extern __inline __m256
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_cvtneebf16_ps (const __m256bh *__A)
|
||||
{
|
||||
return (__m256) __builtin_ia32_vcvtneebf162ps256 ((const __v16bf *) __A);
|
||||
}
|
||||
|
||||
extern __inline __m128
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_cvtneeph_ps (const __m128h *__A)
|
||||
{
|
||||
return (__m128) __builtin_ia32_vcvtneeph2ps128 ((const __v8hf *) __A);
|
||||
}
|
||||
|
||||
extern __inline __m256
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_cvtneeph_ps (const __m256h *__A)
|
||||
{
|
||||
return (__m256) __builtin_ia32_vcvtneeph2ps256 ((const __v16hf *) __A);
|
||||
}
|
||||
|
||||
extern __inline __m128
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_cvtneobf16_ps (const __m128bh *__A)
|
||||
{
|
||||
return (__m128) __builtin_ia32_vcvtneobf162ps128 ((const __v8bf *) __A);
|
||||
}
|
||||
|
||||
extern __inline __m256
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_cvtneobf16_ps (const __m256bh *__A)
|
||||
{
|
||||
return (__m256) __builtin_ia32_vcvtneobf162ps256 ((const __v16bf *) __A);
|
||||
}
|
||||
|
||||
extern __inline __m128
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_cvtneoph_ps (const __m128h *__A)
|
||||
{
|
||||
return (__m128) __builtin_ia32_vcvtneoph2ps128 ((const __v8hf *) __A);
|
||||
}
|
||||
|
||||
extern __inline __m256
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_cvtneoph_ps (const __m256h *__A)
|
||||
{
|
||||
return (__m256) __builtin_ia32_vcvtneoph2ps256 ((const __v16hf *) __A);
|
||||
}
|
||||
|
||||
extern __inline __m128bh
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_cvtneps_avx_pbh (__m128 __A)
|
||||
{
|
||||
return (__m128bh) __builtin_ia32_cvtneps2bf16_v4sf (__A);
|
||||
}
|
||||
|
||||
extern __inline __m128bh
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_cvtneps_avx_pbh (__m256 __A)
|
||||
{
|
||||
return (__m128bh) __builtin_ia32_cvtneps2bf16_v8sf (__A);
|
||||
}
|
||||
|
||||
#ifdef __DISABLE_AVXNECONVERT__
|
||||
#undef __DISABLE_AVXNECONVERT__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVXNECONVERT__ */
|
||||
|
||||
#endif /* _AVXNECONVERTINTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,138 @@
|
||||
/* Copyright (C) 2023-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#if !defined _IMMINTRIN_H_INCLUDED
|
||||
#error "Never use <avxvnniint16intrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AVXVNNIINT16INTRIN_H_INCLUDED
|
||||
#define _AVXVNNIINT16INTRIN_H_INCLUDED
|
||||
|
||||
#if !defined(__AVXVNNIINT16__)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avxvnniint16")
|
||||
#define __DISABLE_AVXVNNIINT16__
|
||||
#endif /* __AVXVNNIINT16__ */
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_dpwsud_avx_epi32 (__m128i __W, __m128i __A, __m128i __B)
|
||||
{
|
||||
return (__m128i)
|
||||
__builtin_ia32_vpdpwsud128 ((__v4si) __W, (__v4si) __A, (__v4si) __B);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_dpwsuds_avx_epi32 (__m128i __W, __m128i __A, __m128i __B)
|
||||
{
|
||||
return (__m128i)
|
||||
__builtin_ia32_vpdpwsuds128 ((__v4si) __W, (__v4si) __A, (__v4si) __B);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_dpwusd_avx_epi32 (__m128i __W, __m128i __A, __m128i __B)
|
||||
{
|
||||
return (__m128i)
|
||||
__builtin_ia32_vpdpwusd128 ((__v4si) __W, (__v4si) __A, (__v4si) __B);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_dpwusds_avx_epi32 (__m128i __W, __m128i __A, __m128i __B)
|
||||
{
|
||||
return (__m128i)
|
||||
__builtin_ia32_vpdpwusds128 ((__v4si) __W, (__v4si) __A, (__v4si) __B);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_dpwuud_avx_epi32 (__m128i __W, __m128i __A, __m128i __B)
|
||||
{
|
||||
return (__m128i)
|
||||
__builtin_ia32_vpdpwuud128 ((__v4si) __W, (__v4si) __A, (__v4si) __B);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_dpwuuds_avx_epi32 (__m128i __W, __m128i __A, __m128i __B)
|
||||
{
|
||||
return (__m128i)
|
||||
__builtin_ia32_vpdpwuuds128 ((__v4si) __W, (__v4si) __A, (__v4si) __B);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_dpwsud_avx_epi32 (__m256i __W, __m256i __A, __m256i __B)
|
||||
{
|
||||
return (__m256i)
|
||||
__builtin_ia32_vpdpwsud256 ((__v8si) __W, (__v8si) __A, (__v8si) __B);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_dpwsuds_avx_epi32 (__m256i __W, __m256i __A, __m256i __B)
|
||||
{
|
||||
return (__m256i)
|
||||
__builtin_ia32_vpdpwsuds256 ((__v8si) __W, (__v8si) __A, (__v8si) __B);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_dpwusd_avx_epi32 (__m256i __W, __m256i __A, __m256i __B)
|
||||
{
|
||||
return (__m256i)
|
||||
__builtin_ia32_vpdpwusd256 ((__v8si) __W, (__v8si) __A, (__v8si) __B);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_dpwusds_avx_epi32 (__m256i __W, __m256i __A, __m256i __B)
|
||||
{
|
||||
return (__m256i)
|
||||
__builtin_ia32_vpdpwusds256 ((__v8si) __W, (__v8si) __A, (__v8si) __B);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_dpwuud_avx_epi32 (__m256i __W, __m256i __A, __m256i __B)
|
||||
{
|
||||
return (__m256i)
|
||||
__builtin_ia32_vpdpwuud256 ((__v8si) __W, (__v8si) __A, (__v8si) __B);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_dpwuuds_avx_epi32 (__m256i __W, __m256i __A, __m256i __B)
|
||||
{
|
||||
return (__m256i)
|
||||
__builtin_ia32_vpdpwuuds256 ((__v8si) __W, (__v8si) __A, (__v8si) __B);
|
||||
}
|
||||
|
||||
#ifdef __DISABLE_AVXVNNIINT16__
|
||||
#undef __DISABLE_AVXVNNIINT16__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVXVNNIINT16__ */
|
||||
|
||||
#endif /* __AVXVNNIINT16INTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,138 @@
|
||||
/* Copyright (C) 2020-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#if !defined _IMMINTRIN_H_INCLUDED
|
||||
#error "Never use <avxvnniint8vlintrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AVXVNNIINT8INTRIN_H_INCLUDED
|
||||
#define _AVXVNNIINT8INTRIN_H_INCLUDED
|
||||
|
||||
#if !defined(__AVXVNNIINT8__)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avxvnniint8")
|
||||
#define __DISABLE_AVXVNNIINT8__
|
||||
#endif /* __AVXVNNIINT8__ */
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_dpbssd_epi32 (__m128i __W, __m128i __A, __m128i __B)
|
||||
{
|
||||
return (__m128i)
|
||||
__builtin_ia32_vpdpbssd128 ((__v4si) __W, (__v4si) __A, (__v4si) __B);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_dpbssds_epi32 (__m128i __W, __m128i __A, __m128i __B)
|
||||
{
|
||||
return (__m128i)
|
||||
__builtin_ia32_vpdpbssds128 ((__v4si) __W, (__v4si) __A, (__v4si) __B);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_dpbsud_epi32 (__m128i __W, __m128i __A, __m128i __B)
|
||||
{
|
||||
return (__m128i)
|
||||
__builtin_ia32_vpdpbsud128 ((__v4si) __W, (__v4si) __A, (__v4si) __B);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_dpbsuds_epi32 (__m128i __W, __m128i __A, __m128i __B)
|
||||
{
|
||||
return (__m128i)
|
||||
__builtin_ia32_vpdpbsuds128 ((__v4si) __W, (__v4si) __A, (__v4si) __B);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_dpbuud_epi32 (__m128i __W, __m128i __A, __m128i __B)
|
||||
{
|
||||
return (__m128i)
|
||||
__builtin_ia32_vpdpbuud128 ((__v4si) __W, (__v4si) __A, (__v4si) __B);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_dpbuuds_epi32 (__m128i __W, __m128i __A, __m128i __B)
|
||||
{
|
||||
return (__m128i)
|
||||
__builtin_ia32_vpdpbuuds128 ((__v4si) __W, (__v4si) __A, (__v4si) __B);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_dpbssd_epi32 (__m256i __W, __m256i __A, __m256i __B)
|
||||
{
|
||||
return (__m256i)
|
||||
__builtin_ia32_vpdpbssd256 ((__v8si) __W, (__v8si) __A, (__v8si) __B);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_dpbssds_epi32 (__m256i __W, __m256i __A, __m256i __B)
|
||||
{
|
||||
return (__m256i)
|
||||
__builtin_ia32_vpdpbssds256 ((__v8si) __W, (__v8si) __A, (__v8si) __B);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_dpbsud_epi32 (__m256i __W, __m256i __A, __m256i __B)
|
||||
{
|
||||
return (__m256i)
|
||||
__builtin_ia32_vpdpbsud256 ((__v8si) __W, (__v8si) __A, (__v8si) __B);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_dpbsuds_epi32 (__m256i __W, __m256i __A, __m256i __B)
|
||||
{
|
||||
return (__m256i)
|
||||
__builtin_ia32_vpdpbsuds256 ((__v8si) __W, (__v8si) __A, (__v8si) __B);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_dpbuud_epi32 (__m256i __W, __m256i __A, __m256i __B)
|
||||
{
|
||||
return (__m256i)
|
||||
__builtin_ia32_vpdpbuud256 ((__v8si) __W, (__v8si) __A, (__v8si) __B);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_dpbuuds_epi32 (__m256i __W, __m256i __A, __m256i __B)
|
||||
{
|
||||
return (__m256i)
|
||||
__builtin_ia32_vpdpbuuds256 ((__v8si) __W, (__v8si) __A, (__v8si) __B);
|
||||
}
|
||||
|
||||
#ifdef __DISABLE_AVXVNNIINT8__
|
||||
#undef __DISABLE_AVXVNNIINT8__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVXVNNIINT8__ */
|
||||
|
||||
#endif /* __AVXVNNIINT8INTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,113 @@
|
||||
/* Copyright (C) 2020-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _IMMINTRIN_H_INCLUDED
|
||||
#error "Never use <avxvnniintrin.h> directly; include <immintrin.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef _AVXVNNIINTRIN_H_INCLUDED
|
||||
#define _AVXVNNIINTRIN_H_INCLUDED
|
||||
|
||||
#if !defined(__AVXVNNI__)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("avxvnni")
|
||||
#define __DISABLE_AVXVNNIVL__
|
||||
#endif /* __AVXVNNIVL__ */
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_dpbusd_avx_epi32(__m256i __A, __m256i __B, __m256i __C)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpdpbusd_v8si ((__v8si) __A,
|
||||
(__v8si) __B,
|
||||
(__v8si) __C);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_dpbusd_avx_epi32(__m128i __A, __m128i __B, __m128i __C)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpdpbusd_v4si ((__v4si) __A,
|
||||
(__v4si) __B,
|
||||
(__v4si) __C);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_dpbusds_avx_epi32(__m256i __A, __m256i __B, __m256i __C)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpdpbusds_v8si ((__v8si) __A,
|
||||
(__v8si) __B,
|
||||
(__v8si) __C);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_dpbusds_avx_epi32(__m128i __A,__m128i __B,__m128i __C)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpdpbusds_v4si ((__v4si) __A,
|
||||
(__v4si) __B,
|
||||
(__v4si) __C);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_dpwssd_avx_epi32(__m256i __A,__m256i __B,__m256i __C)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpdpwssd_v8si ((__v8si) __A,
|
||||
(__v8si) __B,
|
||||
(__v8si) __C);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_dpwssd_avx_epi32(__m128i __A,__m128i __B,__m128i __C)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpdpwssd_v4si ((__v4si) __A,
|
||||
(__v4si) __B,
|
||||
(__v4si) __C);
|
||||
}
|
||||
|
||||
extern __inline __m256i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm256_dpwssds_avx_epi32(__m256i __A,__m256i __B,__m256i __C)
|
||||
{
|
||||
return (__m256i) __builtin_ia32_vpdpwssds_v8si ((__v8si) __A,
|
||||
(__v8si) __B,
|
||||
(__v8si) __C);
|
||||
}
|
||||
|
||||
extern __inline __m128i
|
||||
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_dpwssds_avx_epi32(__m128i __A,__m128i __B,__m128i __C)
|
||||
{
|
||||
return (__m128i) __builtin_ia32_vpdpwssds_v4si ((__v4si) __A,
|
||||
(__v4si) __B,
|
||||
(__v4si) __C);
|
||||
}
|
||||
|
||||
#ifdef __DISABLE_AVXVNNIVL__
|
||||
#undef __DISABLE_AVXVNNIVL__
|
||||
#pragma GCC pop_options
|
||||
#endif /* __DISABLE_AVXVNNIVL__ */
|
||||
#endif /* _AVXVNNIINTRIN_H_INCLUDED */
|
||||
@@ -0,0 +1,343 @@
|
||||
// auto_ptr implementation -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007-2024 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file backward/auto_ptr.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{memory}
|
||||
*/
|
||||
|
||||
#ifndef _BACKWARD_AUTO_PTR_H
|
||||
#define _BACKWARD_AUTO_PTR_H 1
|
||||
|
||||
#include <bits/c++config.h>
|
||||
#include <debug/debug.h>
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* A wrapper class to provide auto_ptr with reference semantics.
|
||||
* For example, an auto_ptr can be assigned (or constructed from)
|
||||
* the result of a function which returns an auto_ptr by value.
|
||||
*
|
||||
* All the auto_ptr_ref stuff should happen behind the scenes.
|
||||
*/
|
||||
template<typename _Tp1>
|
||||
struct auto_ptr_ref
|
||||
{
|
||||
_Tp1* _M_ptr;
|
||||
|
||||
explicit
|
||||
auto_ptr_ref(_Tp1* __p): _M_ptr(__p) { }
|
||||
} _GLIBCXX11_DEPRECATED;
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
/**
|
||||
* @brief A simple smart pointer providing strict ownership semantics.
|
||||
*
|
||||
* The Standard says:
|
||||
* <pre>
|
||||
* An @c auto_ptr owns the object it holds a pointer to. Copying
|
||||
* an @c auto_ptr copies the pointer and transfers ownership to the
|
||||
* destination. If more than one @c auto_ptr owns the same object
|
||||
* at the same time the behavior of the program is undefined.
|
||||
*
|
||||
* The uses of @c auto_ptr include providing temporary
|
||||
* exception-safety for dynamically allocated memory, passing
|
||||
* ownership of dynamically allocated memory to a function, and
|
||||
* returning dynamically allocated memory from a function. @c
|
||||
* auto_ptr does not meet the CopyConstructible and Assignable
|
||||
* requirements for Standard Library <a
|
||||
* href="tables.html#65">container</a> elements and thus
|
||||
* instantiating a Standard Library container with an @c auto_ptr
|
||||
* results in undefined behavior.
|
||||
* </pre>
|
||||
* Quoted from [20.4.5]/3.
|
||||
*
|
||||
* Good examples of what can and cannot be done with auto_ptr can
|
||||
* be found in the libstdc++ testsuite.
|
||||
*
|
||||
* _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
* 127. auto_ptr<> conversion issues
|
||||
* These resolutions have all been incorporated.
|
||||
*
|
||||
* @headerfile memory
|
||||
* @deprecated Deprecated in C++11, no longer in the standard since C++17.
|
||||
* Use `unique_ptr` instead.
|
||||
*/
|
||||
template<typename _Tp>
|
||||
class auto_ptr
|
||||
{
|
||||
private:
|
||||
_Tp* _M_ptr;
|
||||
|
||||
public:
|
||||
/// The pointed-to type.
|
||||
typedef _Tp element_type;
|
||||
|
||||
/**
|
||||
* @brief An %auto_ptr is usually constructed from a raw pointer.
|
||||
* @param __p A pointer (defaults to NULL).
|
||||
*
|
||||
* This object now @e owns the object pointed to by @a __p.
|
||||
*/
|
||||
explicit
|
||||
auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { }
|
||||
|
||||
/**
|
||||
* @brief An %auto_ptr can be constructed from another %auto_ptr.
|
||||
* @param __a Another %auto_ptr of the same type.
|
||||
*
|
||||
* This object now @e owns the object previously owned by @a __a,
|
||||
* which has given up ownership.
|
||||
*/
|
||||
auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) { }
|
||||
|
||||
/**
|
||||
* @brief An %auto_ptr can be constructed from another %auto_ptr.
|
||||
* @param __a Another %auto_ptr of a different but related type.
|
||||
*
|
||||
* A pointer-to-Tp1 must be convertible to a
|
||||
* pointer-to-Tp/element_type.
|
||||
*
|
||||
* This object now @e owns the object previously owned by @a __a,
|
||||
* which has given up ownership.
|
||||
*/
|
||||
template<typename _Tp1>
|
||||
auto_ptr(auto_ptr<_Tp1>& __a) throw() : _M_ptr(__a.release()) { }
|
||||
|
||||
/**
|
||||
* @brief %auto_ptr assignment operator.
|
||||
* @param __a Another %auto_ptr of the same type.
|
||||
*
|
||||
* This object now @e owns the object previously owned by @a __a,
|
||||
* which has given up ownership. The object that this one @e
|
||||
* used to own and track has been deleted.
|
||||
*/
|
||||
auto_ptr&
|
||||
operator=(auto_ptr& __a) throw()
|
||||
{
|
||||
reset(__a.release());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief %auto_ptr assignment operator.
|
||||
* @param __a Another %auto_ptr of a different but related type.
|
||||
*
|
||||
* A pointer-to-Tp1 must be convertible to a pointer-to-Tp/element_type.
|
||||
*
|
||||
* This object now @e owns the object previously owned by @a __a,
|
||||
* which has given up ownership. The object that this one @e
|
||||
* used to own and track has been deleted.
|
||||
*/
|
||||
template<typename _Tp1>
|
||||
auto_ptr&
|
||||
operator=(auto_ptr<_Tp1>& __a) throw()
|
||||
{
|
||||
reset(__a.release());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* When the %auto_ptr goes out of scope, the object it owns is
|
||||
* deleted. If it no longer owns anything (i.e., @c get() is
|
||||
* @c NULL), then this has no effect.
|
||||
*
|
||||
* The C++ standard says there is supposed to be an empty throw
|
||||
* specification here, but omitting it is standard conforming. Its
|
||||
* presence can be detected only if _Tp::~_Tp() throws, but this is
|
||||
* prohibited. [17.4.3.6]/2
|
||||
*/
|
||||
~auto_ptr() { delete _M_ptr; }
|
||||
|
||||
/**
|
||||
* @brief Smart pointer dereferencing.
|
||||
*
|
||||
* If this %auto_ptr no longer owns anything, then this
|
||||
* operation will crash. (For a smart pointer, <em>no longer owns
|
||||
* anything</em> is the same as being a null pointer, and you know
|
||||
* what happens when you dereference one of those...)
|
||||
*/
|
||||
element_type&
|
||||
operator*() const throw()
|
||||
{
|
||||
__glibcxx_assert(_M_ptr != 0);
|
||||
return *_M_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Smart pointer dereferencing.
|
||||
*
|
||||
* This returns the pointer itself, which the language then will
|
||||
* automatically cause to be dereferenced.
|
||||
*/
|
||||
element_type*
|
||||
operator->() const throw()
|
||||
{
|
||||
__glibcxx_assert(_M_ptr != 0);
|
||||
return _M_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Bypassing the smart pointer.
|
||||
* @return The raw pointer being managed.
|
||||
*
|
||||
* You can get a copy of the pointer that this object owns, for
|
||||
* situations such as passing to a function which only accepts
|
||||
* a raw pointer.
|
||||
*
|
||||
* @note This %auto_ptr still owns the memory.
|
||||
*/
|
||||
element_type*
|
||||
get() const throw() { return _M_ptr; }
|
||||
|
||||
/**
|
||||
* @brief Bypassing the smart pointer.
|
||||
* @return The raw pointer being managed.
|
||||
*
|
||||
* You can get a copy of the pointer that this object owns, for
|
||||
* situations such as passing to a function which only accepts
|
||||
* a raw pointer.
|
||||
*
|
||||
* @note This %auto_ptr no longer owns the memory. When this object
|
||||
* goes out of scope, nothing will happen.
|
||||
*/
|
||||
element_type*
|
||||
release() throw()
|
||||
{
|
||||
element_type* __tmp = _M_ptr;
|
||||
_M_ptr = 0;
|
||||
return __tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Forcibly deletes the managed object.
|
||||
* @param __p A pointer (defaults to NULL).
|
||||
*
|
||||
* This object now @e owns the object pointed to by @a __p. The
|
||||
* previous object has been deleted.
|
||||
*/
|
||||
void
|
||||
reset(element_type* __p = 0) throw()
|
||||
{
|
||||
if (__p != _M_ptr)
|
||||
{
|
||||
delete _M_ptr;
|
||||
_M_ptr = __p;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Automatic conversions
|
||||
*
|
||||
* These operations are supposed to convert an %auto_ptr into and from
|
||||
* an auto_ptr_ref automatically as needed. This would allow
|
||||
* constructs such as
|
||||
* @code
|
||||
* auto_ptr<Derived> func_returning_auto_ptr(.....);
|
||||
* ...
|
||||
* auto_ptr<Base> ptr = func_returning_auto_ptr(.....);
|
||||
* @endcode
|
||||
*
|
||||
* But it doesn't work, and won't be fixed. For further details see
|
||||
* http://cplusplus.github.io/LWG/lwg-closed.html#463
|
||||
*/
|
||||
auto_ptr(auto_ptr_ref<element_type> __ref) throw()
|
||||
: _M_ptr(__ref._M_ptr) { }
|
||||
|
||||
auto_ptr&
|
||||
operator=(auto_ptr_ref<element_type> __ref) throw()
|
||||
{
|
||||
if (__ref._M_ptr != this->get())
|
||||
{
|
||||
delete _M_ptr;
|
||||
_M_ptr = __ref._M_ptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename _Tp1>
|
||||
operator auto_ptr_ref<_Tp1>() throw()
|
||||
{ return auto_ptr_ref<_Tp1>(this->release()); }
|
||||
|
||||
template<typename _Tp1>
|
||||
operator auto_ptr<_Tp1>() throw()
|
||||
{ return auto_ptr<_Tp1>(this->release()); }
|
||||
} _GLIBCXX11_DEPRECATED_SUGGEST("std::unique_ptr");
|
||||
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 541. shared_ptr template assignment and void
|
||||
template<>
|
||||
class auto_ptr<void>
|
||||
{
|
||||
public:
|
||||
typedef void element_type;
|
||||
} _GLIBCXX11_DEPRECATED;
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
#if _GLIBCXX_HOSTED
|
||||
template<_Lock_policy _Lp>
|
||||
template<typename _Tp>
|
||||
inline
|
||||
__shared_count<_Lp>::__shared_count(std::auto_ptr<_Tp>&& __r)
|
||||
: _M_pi(new _Sp_counted_ptr<_Tp*, _Lp>(__r.get()))
|
||||
{ __r.release(); }
|
||||
|
||||
template<typename _Tp, _Lock_policy _Lp>
|
||||
template<typename _Tp1, typename>
|
||||
inline
|
||||
__shared_ptr<_Tp, _Lp>::__shared_ptr(std::auto_ptr<_Tp1>&& __r)
|
||||
: _M_ptr(__r.get()), _M_refcount()
|
||||
{
|
||||
__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
|
||||
static_assert( sizeof(_Tp1) > 0, "incomplete type" );
|
||||
_Tp1* __tmp = __r.get();
|
||||
_M_refcount = __shared_count<_Lp>(std::move(__r));
|
||||
_M_enable_shared_from_this_with(__tmp);
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
template<typename _Tp1, typename>
|
||||
inline
|
||||
shared_ptr<_Tp>::shared_ptr(std::auto_ptr<_Tp1>&& __r)
|
||||
: __shared_ptr<_Tp>(std::move(__r)) { }
|
||||
#endif // HOSTED
|
||||
|
||||
template<typename _Tp, typename _Dp>
|
||||
template<typename _Up, typename>
|
||||
inline
|
||||
unique_ptr<_Tp, _Dp>::unique_ptr(auto_ptr<_Up>&& __u) noexcept
|
||||
: _M_t(__u.release(), deleter_type()) { }
|
||||
#endif // C++11
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#endif /* _BACKWARD_AUTO_PTR_H */
|
||||
@@ -0,0 +1,184 @@
|
||||
// Functor implementations -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2024 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1994
|
||||
* Hewlett-Packard Company
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Hewlett-Packard Company makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1996-1998
|
||||
* Silicon Graphics Computer Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Silicon Graphics makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
/** @file backward/binders.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{functional}
|
||||
*/
|
||||
|
||||
#ifndef _BACKWARD_BINDERS_H
|
||||
#define _BACKWARD_BINDERS_H 1
|
||||
|
||||
// Suppress deprecated warning for this file.
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
// 20.3.6 binders
|
||||
/** @defgroup binders Binder Classes
|
||||
* @ingroup functors
|
||||
*
|
||||
* Binders turn functions/functors with two arguments into functors
|
||||
* with a single argument, storing an argument to be applied later.
|
||||
* For example, a variable @c B of type @c binder1st is constructed
|
||||
* from a functor @c f and an argument @c x. Later, B's @c
|
||||
* operator() is called with a single argument @c y. The return
|
||||
* value is the value of @c f(x,y). @c B can be @a called with
|
||||
* various arguments (y1, y2, ...) and will in turn call @c
|
||||
* f(x,y1), @c f(x,y2), ...
|
||||
*
|
||||
* The function @c bind1st is provided to save some typing. It takes the
|
||||
* function and an argument as parameters, and returns an instance of
|
||||
* @c binder1st.
|
||||
*
|
||||
* The type @c binder2nd and its creator function @c bind2nd do the same
|
||||
* thing, but the stored argument is passed as the second parameter instead
|
||||
* of the first, e.g., @c bind2nd(std::minus<float>(),1.3) will create a
|
||||
* functor whose @c operator() accepts a floating-point number, subtracts
|
||||
* 1.3 from it, and returns the result. (If @c bind1st had been used,
|
||||
* the functor would perform <em>1.3 - x</em> instead.
|
||||
*
|
||||
* Creator-wrapper functions like @c bind1st are intended to be used in
|
||||
* calling algorithms. Their return values will be temporary objects.
|
||||
* (The goal is to not require you to type names like
|
||||
* @c std::binder1st<std::plus<int>> for declaring a variable to hold the
|
||||
* return value from @c bind1st(std::plus<int>(),5).
|
||||
*
|
||||
* These become more useful when combined with the composition functions.
|
||||
*
|
||||
* These functions are deprecated in C++11 and can be replaced by
|
||||
* @c std::bind (or @c std::tr1::bind) which is more powerful and flexible,
|
||||
* supporting functions with any number of arguments. Uses of @c bind1st
|
||||
* can be replaced by @c std::bind(f, x, std::placeholders::_1) and
|
||||
* @c bind2nd by @c std::bind(f, std::placeholders::_1, x).
|
||||
* @{
|
||||
*/
|
||||
/// One of the @link binders binder functors@endlink.
|
||||
template<typename _Operation>
|
||||
class binder1st
|
||||
: public unary_function<typename _Operation::second_argument_type,
|
||||
typename _Operation::result_type>
|
||||
{
|
||||
protected:
|
||||
_Operation op;
|
||||
typename _Operation::first_argument_type value;
|
||||
|
||||
public:
|
||||
binder1st(const _Operation& __x,
|
||||
const typename _Operation::first_argument_type& __y)
|
||||
: op(__x), value(__y) { }
|
||||
|
||||
typename _Operation::result_type
|
||||
operator()(const typename _Operation::second_argument_type& __x) const
|
||||
{ return op(value, __x); }
|
||||
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 109. Missing binders for non-const sequence elements
|
||||
typename _Operation::result_type
|
||||
operator()(typename _Operation::second_argument_type& __x) const
|
||||
{ return op(value, __x); }
|
||||
} _GLIBCXX11_DEPRECATED_SUGGEST("std::bind");
|
||||
|
||||
/// One of the @link binders binder functors@endlink.
|
||||
template<typename _Operation, typename _Tp>
|
||||
_GLIBCXX11_DEPRECATED_SUGGEST("std::bind")
|
||||
inline binder1st<_Operation>
|
||||
bind1st(const _Operation& __fn, const _Tp& __x)
|
||||
{
|
||||
typedef typename _Operation::first_argument_type _Arg1_type;
|
||||
return binder1st<_Operation>(__fn, _Arg1_type(__x));
|
||||
}
|
||||
|
||||
/// One of the @link binders binder functors@endlink.
|
||||
template<typename _Operation>
|
||||
class binder2nd
|
||||
: public unary_function<typename _Operation::first_argument_type,
|
||||
typename _Operation::result_type>
|
||||
{
|
||||
protected:
|
||||
_Operation op;
|
||||
typename _Operation::second_argument_type value;
|
||||
|
||||
public:
|
||||
binder2nd(const _Operation& __x,
|
||||
const typename _Operation::second_argument_type& __y)
|
||||
: op(__x), value(__y) { }
|
||||
|
||||
typename _Operation::result_type
|
||||
operator()(const typename _Operation::first_argument_type& __x) const
|
||||
{ return op(__x, value); }
|
||||
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 109. Missing binders for non-const sequence elements
|
||||
typename _Operation::result_type
|
||||
operator()(typename _Operation::first_argument_type& __x) const
|
||||
{ return op(__x, value); }
|
||||
} _GLIBCXX11_DEPRECATED_SUGGEST("std::bind");
|
||||
|
||||
/// One of the @link binders binder functors@endlink.
|
||||
template<typename _Operation, typename _Tp>
|
||||
_GLIBCXX11_DEPRECATED_SUGGEST("std::bind")
|
||||
inline binder2nd<_Operation>
|
||||
bind2nd(const _Operation& __fn, const _Tp& __x)
|
||||
{
|
||||
typedef typename _Operation::second_argument_type _Arg2_type;
|
||||
return binder2nd<_Operation>(__fn, _Arg2_type(__x));
|
||||
}
|
||||
/** @} */
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#endif /* _BACKWARD_BINDERS_H */
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BR_BEARSSL_H__
|
||||
#define BR_BEARSSL_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/** \mainpage BearSSL API
|
||||
*
|
||||
* # API Layout
|
||||
*
|
||||
* The functions and structures defined by the BearSSL API are located
|
||||
* in various header files:
|
||||
*
|
||||
* | Header file | Elements |
|
||||
* | :-------------- | :------------------------------------------------ |
|
||||
* | bearssl_hash.h | Hash functions |
|
||||
* | bearssl_hmac.h | HMAC |
|
||||
* | bearssl_kdf.h | Key Derivation Functions |
|
||||
* | bearssl_rand.h | Pseudorandom byte generators |
|
||||
* | bearssl_prf.h | PRF implementations (for SSL/TLS) |
|
||||
* | bearssl_block.h | Symmetric encryption |
|
||||
* | bearssl_aead.h | AEAD algorithms (combined encryption + MAC) |
|
||||
* | bearssl_rsa.h | RSA encryption and signatures |
|
||||
* | bearssl_ec.h | Elliptic curves support (including ECDSA) |
|
||||
* | bearssl_ssl.h | SSL/TLS engine interface |
|
||||
* | bearssl_x509.h | X.509 certificate decoding and validation |
|
||||
* | bearssl_pem.h | Base64/PEM decoding support functions |
|
||||
*
|
||||
* Applications using BearSSL are supposed to simply include `bearssl.h`
|
||||
* as follows:
|
||||
*
|
||||
* #include <bearssl.h>
|
||||
*
|
||||
* The `bearssl.h` file itself includes all the other header files. It is
|
||||
* possible to include specific header files, but it has no practical
|
||||
* advantage for the application. The API is separated into separate
|
||||
* header files only for documentation convenience.
|
||||
*
|
||||
*
|
||||
* # Conventions
|
||||
*
|
||||
* ## MUST and SHALL
|
||||
*
|
||||
* In all descriptions, the usual "MUST", "SHALL", "MAY",... terminology
|
||||
* is used. Failure to meet requirements expressed with a "MUST" or
|
||||
* "SHALL" implies undefined behaviour, which means that segmentation
|
||||
* faults, buffer overflows, and other similar adverse events, may occur.
|
||||
*
|
||||
* In general, BearSSL is not very forgiving of programming errors, and
|
||||
* does not include much failsafes or error reporting when the problem
|
||||
* does not arise from external transient conditions, and can be fixed
|
||||
* only in the application code. This is done so in order to make the
|
||||
* total code footprint lighter.
|
||||
*
|
||||
*
|
||||
* ## `NULL` values
|
||||
*
|
||||
* Function parameters with a pointer type shall not be `NULL` unless
|
||||
* explicitly authorised by the documentation. As an exception, when
|
||||
* the pointer aims at a sequence of bytes and is accompanied with
|
||||
* a length parameter, and the length is zero (meaning that there is
|
||||
* no byte at all to retrieve), then the pointer may be `NULL` even if
|
||||
* not explicitly allowed.
|
||||
*
|
||||
*
|
||||
* ## Memory Allocation
|
||||
*
|
||||
* BearSSL does not perform dynamic memory allocation. This implies that
|
||||
* for any functionality that requires a non-transient state, the caller
|
||||
* is responsible for allocating the relevant context structure. Such
|
||||
* allocation can be done in any appropriate area, including static data
|
||||
* segments, the heap, and the stack, provided that proper alignment is
|
||||
* respected. The header files define these context structures
|
||||
* (including size and contents), so the C compiler should handle
|
||||
* alignment automatically.
|
||||
*
|
||||
* Since there is no dynamic resource allocation, there is also nothing to
|
||||
* release. When the calling code is done with a BearSSL feature, it
|
||||
* may simple release the context structures it allocated itself, with
|
||||
* no "close function" to call. If the context structures were allocated
|
||||
* on the stack (as local variables), then even that release operation is
|
||||
* implicit.
|
||||
*
|
||||
*
|
||||
* ## Structure Contents
|
||||
*
|
||||
* Except when explicitly indicated, structure contents are opaque: they
|
||||
* are included in the header files so that calling code may know the
|
||||
* structure sizes and alignment requirements, but callers SHALL NOT
|
||||
* access individual fields directly. For fields that are supposed to
|
||||
* be read from or written to, the API defines accessor functions (the
|
||||
* simplest of these accessor functions are defined as `static inline`
|
||||
* functions, and the C compiler will optimise them away).
|
||||
*
|
||||
*
|
||||
* # API Usage
|
||||
*
|
||||
* BearSSL usage for running a SSL/TLS client or server is described
|
||||
* on the [BearSSL Web site](https://www.bearssl.org/api1.html). The
|
||||
* BearSSL source archive also comes with sample code.
|
||||
*/
|
||||
|
||||
#include "bearssl_hash.h"
|
||||
#include "bearssl_hmac.h"
|
||||
#include "bearssl_kdf.h"
|
||||
#include "bearssl_rand.h"
|
||||
#include "bearssl_prf.h"
|
||||
#include "bearssl_block.h"
|
||||
#include "bearssl_aead.h"
|
||||
#include "bearssl_rsa.h"
|
||||
#include "bearssl_ec.h"
|
||||
#include "bearssl_ssl.h"
|
||||
#include "bearssl_x509.h"
|
||||
#include "bearssl_pem.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \brief Type for a configuration option.
|
||||
*
|
||||
* A "configuration option" is a value that is selected when the BearSSL
|
||||
* library itself is compiled. Most options are boolean; their value is
|
||||
* then either 1 (option is enabled) or 0 (option is disabled). Some
|
||||
* values have other integer values. Option names correspond to macro
|
||||
* names. Some of the options can be explicitly set in the internal
|
||||
* `"config.h"` file.
|
||||
*/
|
||||
typedef struct {
|
||||
/** \brief Configurable option name. */
|
||||
const char *name;
|
||||
/** \brief Configurable option value. */
|
||||
long value;
|
||||
} br_config_option;
|
||||
|
||||
/** \brief Get configuration report.
|
||||
*
|
||||
* This function returns compiled configuration options, each as a
|
||||
* 'long' value. Names match internal macro names, in particular those
|
||||
* that can be set in the `"config.h"` inner file. For boolean options,
|
||||
* the numerical value is 1 if enabled, 0 if disabled. For maximum
|
||||
* key sizes, values are expressed in bits.
|
||||
*
|
||||
* The returned array is terminated by an entry whose `name` is `NULL`.
|
||||
*
|
||||
* \return the configuration report.
|
||||
*/
|
||||
const br_config_option *br_get_config(void);
|
||||
|
||||
/* ======================================================================= */
|
||||
|
||||
/** \brief Version feature: support for time callback. */
|
||||
#define BR_FEATURE_X509_TIME_CALLBACK 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BR_BEARSSL_H__
|
||||
#define BR_BEARSSL_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/** \mainpage BearSSL API
|
||||
*
|
||||
* # API Layout
|
||||
*
|
||||
* The functions and structures defined by the BearSSL API are located
|
||||
* in various header files:
|
||||
*
|
||||
* | Header file | Elements |
|
||||
* | :-------------- | :------------------------------------------------ |
|
||||
* | bearssl_hash.h | Hash functions |
|
||||
* | bearssl_hmac.h | HMAC |
|
||||
* | bearssl_kdf.h | Key Derivation Functions |
|
||||
* | bearssl_rand.h | Pseudorandom byte generators |
|
||||
* | bearssl_prf.h | PRF implementations (for SSL/TLS) |
|
||||
* | bearssl_block.h | Symmetric encryption |
|
||||
* | bearssl_aead.h | AEAD algorithms (combined encryption + MAC) |
|
||||
* | bearssl_rsa.h | RSA encryption and signatures |
|
||||
* | bearssl_ec.h | Elliptic curves support (including ECDSA) |
|
||||
* | bearssl_ssl.h | SSL/TLS engine interface |
|
||||
* | bearssl_x509.h | X.509 certificate decoding and validation |
|
||||
* | bearssl_pem.h | Base64/PEM decoding support functions |
|
||||
*
|
||||
* Applications using BearSSL are supposed to simply include `bearssl.h`
|
||||
* as follows:
|
||||
*
|
||||
* #include <bearssl.h>
|
||||
*
|
||||
* The `bearssl.h` file itself includes all the other header files. It is
|
||||
* possible to include specific header files, but it has no practical
|
||||
* advantage for the application. The API is separated into separate
|
||||
* header files only for documentation convenience.
|
||||
*
|
||||
*
|
||||
* # Conventions
|
||||
*
|
||||
* ## MUST and SHALL
|
||||
*
|
||||
* In all descriptions, the usual "MUST", "SHALL", "MAY",... terminology
|
||||
* is used. Failure to meet requirements expressed with a "MUST" or
|
||||
* "SHALL" implies undefined behaviour, which means that segmentation
|
||||
* faults, buffer overflows, and other similar adverse events, may occur.
|
||||
*
|
||||
* In general, BearSSL is not very forgiving of programming errors, and
|
||||
* does not include much failsafes or error reporting when the problem
|
||||
* does not arise from external transient conditions, and can be fixed
|
||||
* only in the application code. This is done so in order to make the
|
||||
* total code footprint lighter.
|
||||
*
|
||||
*
|
||||
* ## `NULL` values
|
||||
*
|
||||
* Function parameters with a pointer type shall not be `NULL` unless
|
||||
* explicitly authorised by the documentation. As an exception, when
|
||||
* the pointer aims at a sequence of bytes and is accompanied with
|
||||
* a length parameter, and the length is zero (meaning that there is
|
||||
* no byte at all to retrieve), then the pointer may be `NULL` even if
|
||||
* not explicitly allowed.
|
||||
*
|
||||
*
|
||||
* ## Memory Allocation
|
||||
*
|
||||
* BearSSL does not perform dynamic memory allocation. This implies that
|
||||
* for any functionality that requires a non-transient state, the caller
|
||||
* is responsible for allocating the relevant context structure. Such
|
||||
* allocation can be done in any appropriate area, including static data
|
||||
* segments, the heap, and the stack, provided that proper alignment is
|
||||
* respected. The header files define these context structures
|
||||
* (including size and contents), so the C compiler should handle
|
||||
* alignment automatically.
|
||||
*
|
||||
* Since there is no dynamic resource allocation, there is also nothing to
|
||||
* release. When the calling code is done with a BearSSL feature, it
|
||||
* may simple release the context structures it allocated itself, with
|
||||
* no "close function" to call. If the context structures were allocated
|
||||
* on the stack (as local variables), then even that release operation is
|
||||
* implicit.
|
||||
*
|
||||
*
|
||||
* ## Structure Contents
|
||||
*
|
||||
* Except when explicitly indicated, structure contents are opaque: they
|
||||
* are included in the header files so that calling code may know the
|
||||
* structure sizes and alignment requirements, but callers SHALL NOT
|
||||
* access individual fields directly. For fields that are supposed to
|
||||
* be read from or written to, the API defines accessor functions (the
|
||||
* simplest of these accessor functions are defined as `static inline`
|
||||
* functions, and the C compiler will optimise them away).
|
||||
*
|
||||
*
|
||||
* # API Usage
|
||||
*
|
||||
* BearSSL usage for running a SSL/TLS client or server is described
|
||||
* on the [BearSSL Web site](https://www.bearssl.org/api1.html). The
|
||||
* BearSSL source archive also comes with sample code.
|
||||
*/
|
||||
|
||||
#include "bearssl_hash.h"
|
||||
#include "bearssl_hmac.h"
|
||||
#include "bearssl_kdf.h"
|
||||
#include "bearssl_rand.h"
|
||||
#include "bearssl_prf.h"
|
||||
#include "bearssl_block.h"
|
||||
#include "bearssl_aead.h"
|
||||
#include "bearssl_rsa.h"
|
||||
#include "bearssl_ec.h"
|
||||
#include "bearssl_ssl.h"
|
||||
#include "bearssl_x509.h"
|
||||
#include "bearssl_pem.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \brief Type for a configuration option.
|
||||
*
|
||||
* A "configuration option" is a value that is selected when the BearSSL
|
||||
* library itself is compiled. Most options are boolean; their value is
|
||||
* then either 1 (option is enabled) or 0 (option is disabled). Some
|
||||
* values have other integer values. Option names correspond to macro
|
||||
* names. Some of the options can be explicitly set in the internal
|
||||
* `"config.h"` file.
|
||||
*/
|
||||
typedef struct {
|
||||
/** \brief Configurable option name. */
|
||||
const char *name;
|
||||
/** \brief Configurable option value. */
|
||||
long value;
|
||||
} br_config_option;
|
||||
|
||||
/** \brief Get configuration report.
|
||||
*
|
||||
* This function returns compiled configuration options, each as a
|
||||
* 'long' value. Names match internal macro names, in particular those
|
||||
* that can be set in the `"config.h"` inner file. For boolean options,
|
||||
* the numerical value is 1 if enabled, 0 if disabled. For maximum
|
||||
* key sizes, values are expressed in bits.
|
||||
*
|
||||
* The returned array is terminated by an entry whose `name` is `NULL`.
|
||||
*
|
||||
* \return the configuration report.
|
||||
*/
|
||||
const br_config_option *br_get_config(void);
|
||||
|
||||
/* ======================================================================= */
|
||||
|
||||
/** \brief Version feature: support for time callback. */
|
||||
#define BR_FEATURE_X509_TIME_CALLBACK 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,967 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BR_BEARSSL_EC_H__
|
||||
#define BR_BEARSSL_EC_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bearssl_rand.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file bearssl_ec.h
|
||||
*
|
||||
* # Elliptic Curves
|
||||
*
|
||||
* This file documents the EC implementations provided with BearSSL, and
|
||||
* ECDSA.
|
||||
*
|
||||
* ## Elliptic Curve API
|
||||
*
|
||||
* Only "named curves" are supported. Each EC implementation supports
|
||||
* one or several named curves, identified by symbolic identifiers.
|
||||
* These identifiers are small integers, that correspond to the values
|
||||
* registered by the
|
||||
* [IANA](http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8).
|
||||
*
|
||||
* Since all currently defined elliptic curve identifiers are in the 0..31
|
||||
* range, it is convenient to encode support of some curves in a 32-bit
|
||||
* word, such that bit x corresponds to curve of identifier x.
|
||||
*
|
||||
* An EC implementation is incarnated by a `br_ec_impl` instance, that
|
||||
* offers the following fields:
|
||||
*
|
||||
* - `supported_curves`
|
||||
*
|
||||
* A 32-bit word that documents the identifiers of the curves supported
|
||||
* by this implementation.
|
||||
*
|
||||
* - `generator()`
|
||||
*
|
||||
* Callback method that returns a pointer to the conventional generator
|
||||
* point for that curve.
|
||||
*
|
||||
* - `order()`
|
||||
*
|
||||
* Callback method that returns a pointer to the subgroup order for
|
||||
* that curve. That value uses unsigned big-endian encoding.
|
||||
*
|
||||
* - `xoff()`
|
||||
*
|
||||
* Callback method that returns the offset and length of the X
|
||||
* coordinate in an encoded point.
|
||||
*
|
||||
* - `mul()`
|
||||
*
|
||||
* Multiply a curve point with an integer.
|
||||
*
|
||||
* - `mulgen()`
|
||||
*
|
||||
* Multiply the curve generator with an integer. This may be faster
|
||||
* than the generic `mul()`.
|
||||
*
|
||||
* - `muladd()`
|
||||
*
|
||||
* Multiply two curve points by two integers, and return the sum of
|
||||
* the two products.
|
||||
*
|
||||
* All curve points are represented in uncompressed format. The `mul()`
|
||||
* and `muladd()` methods take care to validate that the provided points
|
||||
* are really part of the relevant curve subgroup.
|
||||
*
|
||||
* For all point multiplication functions, the following holds:
|
||||
*
|
||||
* - Functions validate that the provided points are valid members
|
||||
* of the relevant curve subgroup. An error is reported if that is
|
||||
* not the case.
|
||||
*
|
||||
* - Processing is constant-time, even if the point operands are not
|
||||
* valid. This holds for both the source and resulting points, and
|
||||
* the multipliers (integers). Only the byte length of the provided
|
||||
* multiplier arrays (not their actual value length in bits) may
|
||||
* leak through timing-based side channels.
|
||||
*
|
||||
* - The multipliers (integers) MUST be lower than the subgroup order.
|
||||
* If this property is not met, then the result is indeterminate,
|
||||
* but an error value is not necessarily returned.
|
||||
*
|
||||
*
|
||||
* ## ECDSA
|
||||
*
|
||||
* ECDSA signatures have two standard formats, called "raw" and "asn1".
|
||||
* Internally, such a signature is a pair of modular integers `(r,s)`.
|
||||
* The "raw" format is the concatenation of the unsigned big-endian
|
||||
* encodings of these two integers, possibly left-padded with zeros so
|
||||
* that they have the same encoded length. The "asn1" format is the
|
||||
* DER encoding of an ASN.1 structure that contains the two integer
|
||||
* values:
|
||||
*
|
||||
* ECDSASignature ::= SEQUENCE {
|
||||
* r INTEGER,
|
||||
* s INTEGER
|
||||
* }
|
||||
*
|
||||
* In general, in all of X.509 and SSL/TLS, the "asn1" format is used.
|
||||
* BearSSL offers ECDSA implementations for both formats; conversion
|
||||
* functions between the two formats are also provided. Conversion of a
|
||||
* "raw" format signature into "asn1" may enlarge a signature by no more
|
||||
* than 9 bytes for all supported curves; conversely, conversion of an
|
||||
* "asn1" signature to "raw" may expand the signature but the "raw"
|
||||
* length will never be more than twice the length of the "asn1" length
|
||||
* (and usually it will be shorter).
|
||||
*
|
||||
* Note that for a given signature, the "raw" format is not fully
|
||||
* deterministic, in that it does not enforce a minimal common length.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Standard curve ID. These ID are equal to the assigned numerical
|
||||
* identifiers assigned to these curves for TLS:
|
||||
* http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
|
||||
*/
|
||||
|
||||
/** \brief Identifier for named curve sect163k1. */
|
||||
#define BR_EC_sect163k1 1
|
||||
|
||||
/** \brief Identifier for named curve sect163r1. */
|
||||
#define BR_EC_sect163r1 2
|
||||
|
||||
/** \brief Identifier for named curve sect163r2. */
|
||||
#define BR_EC_sect163r2 3
|
||||
|
||||
/** \brief Identifier for named curve sect193r1. */
|
||||
#define BR_EC_sect193r1 4
|
||||
|
||||
/** \brief Identifier for named curve sect193r2. */
|
||||
#define BR_EC_sect193r2 5
|
||||
|
||||
/** \brief Identifier for named curve sect233k1. */
|
||||
#define BR_EC_sect233k1 6
|
||||
|
||||
/** \brief Identifier for named curve sect233r1. */
|
||||
#define BR_EC_sect233r1 7
|
||||
|
||||
/** \brief Identifier for named curve sect239k1. */
|
||||
#define BR_EC_sect239k1 8
|
||||
|
||||
/** \brief Identifier for named curve sect283k1. */
|
||||
#define BR_EC_sect283k1 9
|
||||
|
||||
/** \brief Identifier for named curve sect283r1. */
|
||||
#define BR_EC_sect283r1 10
|
||||
|
||||
/** \brief Identifier for named curve sect409k1. */
|
||||
#define BR_EC_sect409k1 11
|
||||
|
||||
/** \brief Identifier for named curve sect409r1. */
|
||||
#define BR_EC_sect409r1 12
|
||||
|
||||
/** \brief Identifier for named curve sect571k1. */
|
||||
#define BR_EC_sect571k1 13
|
||||
|
||||
/** \brief Identifier for named curve sect571r1. */
|
||||
#define BR_EC_sect571r1 14
|
||||
|
||||
/** \brief Identifier for named curve secp160k1. */
|
||||
#define BR_EC_secp160k1 15
|
||||
|
||||
/** \brief Identifier for named curve secp160r1. */
|
||||
#define BR_EC_secp160r1 16
|
||||
|
||||
/** \brief Identifier for named curve secp160r2. */
|
||||
#define BR_EC_secp160r2 17
|
||||
|
||||
/** \brief Identifier for named curve secp192k1. */
|
||||
#define BR_EC_secp192k1 18
|
||||
|
||||
/** \brief Identifier for named curve secp192r1. */
|
||||
#define BR_EC_secp192r1 19
|
||||
|
||||
/** \brief Identifier for named curve secp224k1. */
|
||||
#define BR_EC_secp224k1 20
|
||||
|
||||
/** \brief Identifier for named curve secp224r1. */
|
||||
#define BR_EC_secp224r1 21
|
||||
|
||||
/** \brief Identifier for named curve secp256k1. */
|
||||
#define BR_EC_secp256k1 22
|
||||
|
||||
/** \brief Identifier for named curve secp256r1. */
|
||||
#define BR_EC_secp256r1 23
|
||||
|
||||
/** \brief Identifier for named curve secp384r1. */
|
||||
#define BR_EC_secp384r1 24
|
||||
|
||||
/** \brief Identifier for named curve secp521r1. */
|
||||
#define BR_EC_secp521r1 25
|
||||
|
||||
/** \brief Identifier for named curve brainpoolP256r1. */
|
||||
#define BR_EC_brainpoolP256r1 26
|
||||
|
||||
/** \brief Identifier for named curve brainpoolP384r1. */
|
||||
#define BR_EC_brainpoolP384r1 27
|
||||
|
||||
/** \brief Identifier for named curve brainpoolP512r1. */
|
||||
#define BR_EC_brainpoolP512r1 28
|
||||
|
||||
/** \brief Identifier for named curve Curve25519. */
|
||||
#define BR_EC_curve25519 29
|
||||
|
||||
/** \brief Identifier for named curve Curve448. */
|
||||
#define BR_EC_curve448 30
|
||||
|
||||
/**
|
||||
* \brief Structure for an EC public key.
|
||||
*/
|
||||
typedef struct {
|
||||
/** \brief Identifier for the curve used by this key. */
|
||||
int curve;
|
||||
/** \brief Public curve point (uncompressed format). */
|
||||
unsigned char *q;
|
||||
/** \brief Length of public curve point (in bytes). */
|
||||
size_t qlen;
|
||||
} br_ec_public_key;
|
||||
|
||||
/**
|
||||
* \brief Structure for an EC private key.
|
||||
*
|
||||
* The private key is an integer modulo the curve subgroup order. The
|
||||
* encoding below tolerates extra leading zeros. In general, it is
|
||||
* recommended that the private key has the same length as the curve
|
||||
* subgroup order.
|
||||
*/
|
||||
typedef struct {
|
||||
/** \brief Identifier for the curve used by this key. */
|
||||
int curve;
|
||||
/** \brief Private key (integer, unsigned big-endian encoding). */
|
||||
unsigned char *x;
|
||||
/** \brief Private key length (in bytes). */
|
||||
size_t xlen;
|
||||
} br_ec_private_key;
|
||||
|
||||
/**
|
||||
* \brief Type for an EC implementation.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Supported curves.
|
||||
*
|
||||
* This word is a bitfield: bit `x` is set if the curve of ID `x`
|
||||
* is supported. E.g. an implementation supporting both NIST P-256
|
||||
* (secp256r1, ID 23) and NIST P-384 (secp384r1, ID 24) will have
|
||||
* value `0x01800000` in this field.
|
||||
*/
|
||||
uint32_t supported_curves;
|
||||
|
||||
/**
|
||||
* \brief Get the conventional generator.
|
||||
*
|
||||
* This function returns the conventional generator (encoded
|
||||
* curve point) for the specified curve. This function MUST NOT
|
||||
* be called if the curve is not supported.
|
||||
*
|
||||
* \param curve curve identifier.
|
||||
* \param len receiver for the encoded generator length (in bytes).
|
||||
* \return the encoded generator.
|
||||
*/
|
||||
const unsigned char *(*generator)(int curve, size_t *len);
|
||||
|
||||
/**
|
||||
* \brief Get the subgroup order.
|
||||
*
|
||||
* This function returns the order of the subgroup generated by
|
||||
* the conventional generator, for the specified curve. Unsigned
|
||||
* big-endian encoding is used. This function MUST NOT be called
|
||||
* if the curve is not supported.
|
||||
*
|
||||
* \param curve curve identifier.
|
||||
* \param len receiver for the encoded order length (in bytes).
|
||||
* \return the encoded order.
|
||||
*/
|
||||
const unsigned char *(*order)(int curve, size_t *len);
|
||||
|
||||
/**
|
||||
* \brief Get the offset and length for the X coordinate.
|
||||
*
|
||||
* This function returns the offset and length (in bytes) of
|
||||
* the X coordinate in an encoded non-zero point.
|
||||
*
|
||||
* \param curve curve identifier.
|
||||
* \param len receiver for the X coordinate length (in bytes).
|
||||
* \return the offset for the X coordinate (in bytes).
|
||||
*/
|
||||
size_t (*xoff)(int curve, size_t *len);
|
||||
|
||||
/**
|
||||
* \brief Multiply a curve point by an integer.
|
||||
*
|
||||
* The source point is provided in array `G` (of size `Glen` bytes);
|
||||
* the multiplication result is written over it. The multiplier
|
||||
* `x` (of size `xlen` bytes) uses unsigned big-endian encoding.
|
||||
*
|
||||
* Rules:
|
||||
*
|
||||
* - The specified curve MUST be supported.
|
||||
*
|
||||
* - The source point must be a valid point on the relevant curve
|
||||
* subgroup (and not the "point at infinity" either). If this is
|
||||
* not the case, then this function returns an error (0).
|
||||
*
|
||||
* - The multiplier integer MUST be non-zero and less than the
|
||||
* curve subgroup order. If this property does not hold, then
|
||||
* the result is indeterminate and an error code is not
|
||||
* guaranteed.
|
||||
*
|
||||
* Returned value is 1 on success, 0 on error. On error, the
|
||||
* contents of `G` are indeterminate.
|
||||
*
|
||||
* \param G point to multiply.
|
||||
* \param Glen length of the encoded point (in bytes).
|
||||
* \param x multiplier (unsigned big-endian).
|
||||
* \param xlen multiplier length (in bytes).
|
||||
* \param curve curve identifier.
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t (*mul)(unsigned char *G, size_t Glen,
|
||||
const unsigned char *x, size_t xlen, int curve);
|
||||
|
||||
/**
|
||||
* \brief Multiply the generator by an integer.
|
||||
*
|
||||
* The multiplier MUST be non-zero and less than the curve
|
||||
* subgroup order. Results are indeterminate if this property
|
||||
* does not hold.
|
||||
*
|
||||
* \param R output buffer for the point.
|
||||
* \param x multiplier (unsigned big-endian).
|
||||
* \param xlen multiplier length (in bytes).
|
||||
* \param curve curve identifier.
|
||||
* \return encoded result point length (in bytes).
|
||||
*/
|
||||
size_t (*mulgen)(unsigned char *R,
|
||||
const unsigned char *x, size_t xlen, int curve);
|
||||
|
||||
/**
|
||||
* \brief Multiply two points by two integers and add the
|
||||
* results.
|
||||
*
|
||||
* The point `x*A + y*B` is computed and written back in the `A`
|
||||
* array.
|
||||
*
|
||||
* Rules:
|
||||
*
|
||||
* - The specified curve MUST be supported.
|
||||
*
|
||||
* - The source points (`A` and `B`) must be valid points on
|
||||
* the relevant curve subgroup (and not the "point at
|
||||
* infinity" either). If this is not the case, then this
|
||||
* function returns an error (0).
|
||||
*
|
||||
* - If the `B` pointer is `NULL`, then the conventional
|
||||
* subgroup generator is used. With some implementations,
|
||||
* this may be faster than providing a pointer to the
|
||||
* generator.
|
||||
*
|
||||
* - The multiplier integers (`x` and `y`) MUST be non-zero
|
||||
* and less than the curve subgroup order. If either integer
|
||||
* is zero, then an error is reported, but if one of them is
|
||||
* not lower than the subgroup order, then the result is
|
||||
* indeterminate and an error code is not guaranteed.
|
||||
*
|
||||
* - If the final result is the point at infinity, then an
|
||||
* error is returned.
|
||||
*
|
||||
* Returned value is 1 on success, 0 on error. On error, the
|
||||
* contents of `A` are indeterminate.
|
||||
*
|
||||
* \param A first point to multiply.
|
||||
* \param B second point to multiply (`NULL` for the generator).
|
||||
* \param len common length of the encoded points (in bytes).
|
||||
* \param x multiplier for `A` (unsigned big-endian).
|
||||
* \param xlen length of multiplier for `A` (in bytes).
|
||||
* \param y multiplier for `A` (unsigned big-endian).
|
||||
* \param ylen length of multiplier for `A` (in bytes).
|
||||
* \param curve curve identifier.
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t (*muladd)(unsigned char *A, const unsigned char *B, size_t len,
|
||||
const unsigned char *x, size_t xlen,
|
||||
const unsigned char *y, size_t ylen, int curve);
|
||||
} br_ec_impl;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "i31".
|
||||
*
|
||||
* This implementation internally uses generic code for modular integers,
|
||||
* with a representation as sequences of 31-bit words. It supports secp256r1,
|
||||
* secp384r1 and secp521r1 (aka NIST curves P-256, P-384 and P-521).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_prime_i31;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "i15".
|
||||
*
|
||||
* This implementation internally uses generic code for modular integers,
|
||||
* with a representation as sequences of 15-bit words. It supports secp256r1,
|
||||
* secp384r1 and secp521r1 (aka NIST curves P-256, P-384 and P-521).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_prime_i15;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m15" for P-256.
|
||||
*
|
||||
* This implementation uses specialised code for curve secp256r1 (also
|
||||
* known as NIST P-256), with optional Karatsuba decomposition, and fast
|
||||
* modular reduction thanks to the field modulus special format. Only
|
||||
* 32-bit multiplications are used (with 32-bit results, not 64-bit).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_p256_m15;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m31" for P-256.
|
||||
*
|
||||
* This implementation uses specialised code for curve secp256r1 (also
|
||||
* known as NIST P-256), relying on multiplications of 31-bit values
|
||||
* (MUL31).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_p256_m31;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m62" (specialised code) for P-256.
|
||||
*
|
||||
* This implementation uses custom code relying on multiplication of
|
||||
* integers up to 64 bits, with a 128-bit result. This implementation is
|
||||
* defined only on platforms that offer the 64x64->128 multiplication
|
||||
* support; use `br_ec_p256_m62_get()` to dynamically obtain a pointer
|
||||
* to that implementation.
|
||||
*/
|
||||
extern const br_ec_impl br_ec_p256_m62;
|
||||
|
||||
/**
|
||||
* \brief Get the "m62" implementation of P-256, if available.
|
||||
*
|
||||
* \return the implementation, or 0.
|
||||
*/
|
||||
const br_ec_impl *br_ec_p256_m62_get(void);
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m64" (specialised code) for P-256.
|
||||
*
|
||||
* This implementation uses custom code relying on multiplication of
|
||||
* integers up to 64 bits, with a 128-bit result. This implementation is
|
||||
* defined only on platforms that offer the 64x64->128 multiplication
|
||||
* support; use `br_ec_p256_m64_get()` to dynamically obtain a pointer
|
||||
* to that implementation.
|
||||
*/
|
||||
extern const br_ec_impl br_ec_p256_m64;
|
||||
|
||||
/**
|
||||
* \brief Get the "m64" implementation of P-256, if available.
|
||||
*
|
||||
* \return the implementation, or 0.
|
||||
*/
|
||||
const br_ec_impl *br_ec_p256_m64_get(void);
|
||||
|
||||
/**
|
||||
* \brief EC implementation "i15" (generic code) for Curve25519.
|
||||
*
|
||||
* This implementation uses the generic code for modular integers (with
|
||||
* 15-bit words) to support Curve25519. Due to the specificities of the
|
||||
* curve definition, the following applies:
|
||||
*
|
||||
* - `muladd()` is not implemented (the function returns 0 systematically).
|
||||
* - `order()` returns 2^255-1, since the point multiplication algorithm
|
||||
* accepts any 32-bit integer as input (it clears the top bit and low
|
||||
* three bits systematically).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_c25519_i15;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "i31" (generic code) for Curve25519.
|
||||
*
|
||||
* This implementation uses the generic code for modular integers (with
|
||||
* 31-bit words) to support Curve25519. Due to the specificities of the
|
||||
* curve definition, the following applies:
|
||||
*
|
||||
* - `muladd()` is not implemented (the function returns 0 systematically).
|
||||
* - `order()` returns 2^255-1, since the point multiplication algorithm
|
||||
* accepts any 32-bit integer as input (it clears the top bit and low
|
||||
* three bits systematically).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_c25519_i31;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m15" (specialised code) for Curve25519.
|
||||
*
|
||||
* This implementation uses custom code relying on multiplication of
|
||||
* integers up to 15 bits. Due to the specificities of the curve
|
||||
* definition, the following applies:
|
||||
*
|
||||
* - `muladd()` is not implemented (the function returns 0 systematically).
|
||||
* - `order()` returns 2^255-1, since the point multiplication algorithm
|
||||
* accepts any 32-bit integer as input (it clears the top bit and low
|
||||
* three bits systematically).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_c25519_m15;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m31" (specialised code) for Curve25519.
|
||||
*
|
||||
* This implementation uses custom code relying on multiplication of
|
||||
* integers up to 31 bits. Due to the specificities of the curve
|
||||
* definition, the following applies:
|
||||
*
|
||||
* - `muladd()` is not implemented (the function returns 0 systematically).
|
||||
* - `order()` returns 2^255-1, since the point multiplication algorithm
|
||||
* accepts any 32-bit integer as input (it clears the top bit and low
|
||||
* three bits systematically).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_c25519_m31;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m62" (specialised code) for Curve25519.
|
||||
*
|
||||
* This implementation uses custom code relying on multiplication of
|
||||
* integers up to 62 bits, with a 124-bit result. This implementation is
|
||||
* defined only on platforms that offer the 64x64->128 multiplication
|
||||
* support; use `br_ec_c25519_m62_get()` to dynamically obtain a pointer
|
||||
* to that implementation. Due to the specificities of the curve
|
||||
* definition, the following applies:
|
||||
*
|
||||
* - `muladd()` is not implemented (the function returns 0 systematically).
|
||||
* - `order()` returns 2^255-1, since the point multiplication algorithm
|
||||
* accepts any 32-bit integer as input (it clears the top bit and low
|
||||
* three bits systematically).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_c25519_m62;
|
||||
|
||||
/**
|
||||
* \brief Get the "m62" implementation of Curve25519, if available.
|
||||
*
|
||||
* \return the implementation, or 0.
|
||||
*/
|
||||
const br_ec_impl *br_ec_c25519_m62_get(void);
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m64" (specialised code) for Curve25519.
|
||||
*
|
||||
* This implementation uses custom code relying on multiplication of
|
||||
* integers up to 64 bits, with a 128-bit result. This implementation is
|
||||
* defined only on platforms that offer the 64x64->128 multiplication
|
||||
* support; use `br_ec_c25519_m64_get()` to dynamically obtain a pointer
|
||||
* to that implementation. Due to the specificities of the curve
|
||||
* definition, the following applies:
|
||||
*
|
||||
* - `muladd()` is not implemented (the function returns 0 systematically).
|
||||
* - `order()` returns 2^255-1, since the point multiplication algorithm
|
||||
* accepts any 32-bit integer as input (it clears the top bit and low
|
||||
* three bits systematically).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_c25519_m64;
|
||||
|
||||
/**
|
||||
* \brief Get the "m64" implementation of Curve25519, if available.
|
||||
*
|
||||
* \return the implementation, or 0.
|
||||
*/
|
||||
const br_ec_impl *br_ec_c25519_m64_get(void);
|
||||
|
||||
/**
|
||||
* \brief Aggregate EC implementation "m15".
|
||||
*
|
||||
* This implementation is a wrapper for:
|
||||
*
|
||||
* - `br_ec_c25519_m15` for Curve25519
|
||||
* - `br_ec_p256_m15` for NIST P-256
|
||||
* - `br_ec_prime_i15` for other curves (NIST P-384 and NIST-P512)
|
||||
*/
|
||||
extern const br_ec_impl br_ec_all_m15;
|
||||
|
||||
/**
|
||||
* \brief Aggregate EC implementation "m31".
|
||||
*
|
||||
* This implementation is a wrapper for:
|
||||
*
|
||||
* - `br_ec_c25519_m31` for Curve25519
|
||||
* - `br_ec_p256_m31` for NIST P-256
|
||||
* - `br_ec_prime_i31` for other curves (NIST P-384 and NIST-P512)
|
||||
*/
|
||||
extern const br_ec_impl br_ec_all_m31;
|
||||
|
||||
/**
|
||||
* \brief Get the "default" EC implementation for the current system.
|
||||
*
|
||||
* This returns a pointer to the preferred implementation on the
|
||||
* current system.
|
||||
*
|
||||
* \return the default EC implementation.
|
||||
*/
|
||||
const br_ec_impl *br_ec_get_default(void);
|
||||
|
||||
/**
|
||||
* \brief Convert a signature from "raw" to "asn1".
|
||||
*
|
||||
* Conversion is done "in place" and the new length is returned.
|
||||
* Conversion may enlarge the signature, but by no more than 9 bytes at
|
||||
* most. On error, 0 is returned (error conditions include an odd raw
|
||||
* signature length, or an oversized integer).
|
||||
*
|
||||
* \param sig signature to convert.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return the new signature length, or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_raw_to_asn1(void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief Convert a signature from "asn1" to "raw".
|
||||
*
|
||||
* Conversion is done "in place" and the new length is returned.
|
||||
* Conversion may enlarge the signature, but the new signature length
|
||||
* will be less than twice the source length at most. On error, 0 is
|
||||
* returned (error conditions include an invalid ASN.1 structure or an
|
||||
* oversized integer).
|
||||
*
|
||||
* \param sig signature to convert.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return the new signature length, or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_asn1_to_raw(void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief Type for an ECDSA signer function.
|
||||
*
|
||||
* A pointer to the EC implementation is provided. The hash value is
|
||||
* assumed to have the length inferred from the designated hash function
|
||||
* class.
|
||||
*
|
||||
* Signature is written in the buffer pointed to by `sig`, and the length
|
||||
* (in bytes) is returned. On error, nothing is written in the buffer,
|
||||
* and 0 is returned. This function returns 0 if the specified curve is
|
||||
* not supported by the provided EC implementation.
|
||||
*
|
||||
* The signature format is either "raw" or "asn1", depending on the
|
||||
* implementation; maximum length is predictable from the implemented
|
||||
* curve:
|
||||
*
|
||||
* | curve | raw | asn1 |
|
||||
* | :--------- | --: | ---: |
|
||||
* | NIST P-256 | 64 | 72 |
|
||||
* | NIST P-384 | 96 | 104 |
|
||||
* | NIST P-521 | 132 | 139 |
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hf hash function used to process the data.
|
||||
* \param hash_value signed data (hashed).
|
||||
* \param sk EC private key.
|
||||
* \param sig destination buffer.
|
||||
* \return the signature length (in bytes), or 0 on error.
|
||||
*/
|
||||
typedef size_t (*br_ecdsa_sign)(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig);
|
||||
|
||||
/**
|
||||
* \brief Type for an ECDSA signature verification function.
|
||||
*
|
||||
* A pointer to the EC implementation is provided. The hashed value,
|
||||
* computed over the purportedly signed data, is also provided with
|
||||
* its length.
|
||||
*
|
||||
* The signature format is either "raw" or "asn1", depending on the
|
||||
* implementation.
|
||||
*
|
||||
* Returned value is 1 on success (valid signature), 0 on error. This
|
||||
* function returns 0 if the specified curve is not supported by the
|
||||
* provided EC implementation.
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hash signed data (hashed).
|
||||
* \param hash_len hash value length (in bytes).
|
||||
* \param pk EC public key.
|
||||
* \param sig signature.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
typedef uint32_t (*br_ecdsa_vrfy)(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk, const void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature generator, "i31" implementation, "asn1" format.
|
||||
*
|
||||
* \see br_ecdsa_sign()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hf hash function used to process the data.
|
||||
* \param hash_value signed data (hashed).
|
||||
* \param sk EC private key.
|
||||
* \param sig destination buffer.
|
||||
* \return the signature length (in bytes), or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_i31_sign_asn1(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature generator, "i31" implementation, "raw" format.
|
||||
*
|
||||
* \see br_ecdsa_sign()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hf hash function used to process the data.
|
||||
* \param hash_value signed data (hashed).
|
||||
* \param sk EC private key.
|
||||
* \param sig destination buffer.
|
||||
* \return the signature length (in bytes), or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_i31_sign_raw(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature verifier, "i31" implementation, "asn1" format.
|
||||
*
|
||||
* \see br_ecdsa_vrfy()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hash signed data (hashed).
|
||||
* \param hash_len hash value length (in bytes).
|
||||
* \param pk EC public key.
|
||||
* \param sig signature.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t br_ecdsa_i31_vrfy_asn1(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk, const void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature verifier, "i31" implementation, "raw" format.
|
||||
*
|
||||
* \see br_ecdsa_vrfy()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hash signed data (hashed).
|
||||
* \param hash_len hash value length (in bytes).
|
||||
* \param pk EC public key.
|
||||
* \param sig signature.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t br_ecdsa_i31_vrfy_raw(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk, const void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature generator, "i15" implementation, "asn1" format.
|
||||
*
|
||||
* \see br_ecdsa_sign()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hf hash function used to process the data.
|
||||
* \param hash_value signed data (hashed).
|
||||
* \param sk EC private key.
|
||||
* \param sig destination buffer.
|
||||
* \return the signature length (in bytes), or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_i15_sign_asn1(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature generator, "i15" implementation, "raw" format.
|
||||
*
|
||||
* \see br_ecdsa_sign()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hf hash function used to process the data.
|
||||
* \param hash_value signed data (hashed).
|
||||
* \param sk EC private key.
|
||||
* \param sig destination buffer.
|
||||
* \return the signature length (in bytes), or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_i15_sign_raw(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature verifier, "i15" implementation, "asn1" format.
|
||||
*
|
||||
* \see br_ecdsa_vrfy()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hash signed data (hashed).
|
||||
* \param hash_len hash value length (in bytes).
|
||||
* \param pk EC public key.
|
||||
* \param sig signature.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t br_ecdsa_i15_vrfy_asn1(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk, const void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature verifier, "i15" implementation, "raw" format.
|
||||
*
|
||||
* \see br_ecdsa_vrfy()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hash signed data (hashed).
|
||||
* \param hash_len hash value length (in bytes).
|
||||
* \param pk EC public key.
|
||||
* \param sig signature.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t br_ecdsa_i15_vrfy_raw(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk, const void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief Get "default" ECDSA implementation (signer, asn1 format).
|
||||
*
|
||||
* This returns the preferred implementation of ECDSA signature generation
|
||||
* ("asn1" output format) on the current system.
|
||||
*
|
||||
* \return the default implementation.
|
||||
*/
|
||||
br_ecdsa_sign br_ecdsa_sign_asn1_get_default(void);
|
||||
|
||||
/**
|
||||
* \brief Get "default" ECDSA implementation (signer, raw format).
|
||||
*
|
||||
* This returns the preferred implementation of ECDSA signature generation
|
||||
* ("raw" output format) on the current system.
|
||||
*
|
||||
* \return the default implementation.
|
||||
*/
|
||||
br_ecdsa_sign br_ecdsa_sign_raw_get_default(void);
|
||||
|
||||
/**
|
||||
* \brief Get "default" ECDSA implementation (verifier, asn1 format).
|
||||
*
|
||||
* This returns the preferred implementation of ECDSA signature verification
|
||||
* ("asn1" output format) on the current system.
|
||||
*
|
||||
* \return the default implementation.
|
||||
*/
|
||||
br_ecdsa_vrfy br_ecdsa_vrfy_asn1_get_default(void);
|
||||
|
||||
/**
|
||||
* \brief Get "default" ECDSA implementation (verifier, raw format).
|
||||
*
|
||||
* This returns the preferred implementation of ECDSA signature verification
|
||||
* ("raw" output format) on the current system.
|
||||
*
|
||||
* \return the default implementation.
|
||||
*/
|
||||
br_ecdsa_vrfy br_ecdsa_vrfy_raw_get_default(void);
|
||||
|
||||
/**
|
||||
* \brief Maximum size for EC private key element buffer.
|
||||
*
|
||||
* This is the largest number of bytes that `br_ec_keygen()` may need or
|
||||
* ever return.
|
||||
*/
|
||||
#define BR_EC_KBUF_PRIV_MAX_SIZE 72
|
||||
|
||||
/**
|
||||
* \brief Maximum size for EC public key element buffer.
|
||||
*
|
||||
* This is the largest number of bytes that `br_ec_compute_public()` may
|
||||
* need or ever return.
|
||||
*/
|
||||
#define BR_EC_KBUF_PUB_MAX_SIZE 145
|
||||
|
||||
/**
|
||||
* \brief Generate a new EC private key.
|
||||
*
|
||||
* If the specified `curve` is not supported by the elliptic curve
|
||||
* implementation (`impl`), then this function returns zero.
|
||||
*
|
||||
* The `sk` structure fields are set to the new private key data. In
|
||||
* particular, `sk.x` is made to point to the provided key buffer (`kbuf`),
|
||||
* in which the actual private key data is written. That buffer is assumed
|
||||
* to be large enough. The `BR_EC_KBUF_PRIV_MAX_SIZE` defines the maximum
|
||||
* size for all supported curves.
|
||||
*
|
||||
* The number of bytes used in `kbuf` is returned. If `kbuf` is `NULL`, then
|
||||
* the private key is not actually generated, and `sk` may also be `NULL`;
|
||||
* the minimum length for `kbuf` is still computed and returned.
|
||||
*
|
||||
* If `sk` is `NULL` but `kbuf` is not `NULL`, then the private key is
|
||||
* still generated and stored in `kbuf`.
|
||||
*
|
||||
* \param rng_ctx source PRNG context (already initialized).
|
||||
* \param impl the elliptic curve implementation.
|
||||
* \param sk the private key structure to fill, or `NULL`.
|
||||
* \param kbuf the key element buffer, or `NULL`.
|
||||
* \param curve the curve identifier.
|
||||
* \return the key data length (in bytes), or zero.
|
||||
*/
|
||||
size_t br_ec_keygen(const br_prng_class **rng_ctx,
|
||||
const br_ec_impl *impl, br_ec_private_key *sk,
|
||||
void *kbuf, int curve);
|
||||
|
||||
/**
|
||||
* \brief Compute EC public key from EC private key.
|
||||
*
|
||||
* This function uses the provided elliptic curve implementation (`impl`)
|
||||
* to compute the public key corresponding to the private key held in `sk`.
|
||||
* The public key point is written into `kbuf`, which is then linked from
|
||||
* the `*pk` structure. The size of the public key point, i.e. the number
|
||||
* of bytes used in `kbuf`, is returned.
|
||||
*
|
||||
* If `kbuf` is `NULL`, then the public key point is NOT computed, and
|
||||
* the public key structure `*pk` is unmodified (`pk` may be `NULL` in
|
||||
* that case). The size of the public key point is still returned.
|
||||
*
|
||||
* If `pk` is `NULL` but `kbuf` is not `NULL`, then the public key
|
||||
* point is computed and stored in `kbuf`, and its size is returned.
|
||||
*
|
||||
* If the curve used by the private key is not supported by the curve
|
||||
* implementation, then this function returns zero.
|
||||
*
|
||||
* The private key MUST be valid. An off-range private key value is not
|
||||
* necessarily detected, and leads to unpredictable results.
|
||||
*
|
||||
* \param impl the elliptic curve implementation.
|
||||
* \param pk the public key structure to fill (or `NULL`).
|
||||
* \param kbuf the public key point buffer (or `NULL`).
|
||||
* \param sk the source private key.
|
||||
* \return the public key point length (in bytes), or zero.
|
||||
*/
|
||||
size_t br_ec_compute_pub(const br_ec_impl *impl, br_ec_public_key *pk,
|
||||
void *kbuf, const br_ec_private_key *sk);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BR_BEARSSL_HMAC_H__
|
||||
#define BR_BEARSSL_HMAC_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bearssl_hash.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file bearssl_hmac.h
|
||||
*
|
||||
* # HMAC
|
||||
*
|
||||
* HMAC is initialized with a key and an underlying hash function; it
|
||||
* then fills a "key context". That context contains the processed
|
||||
* key.
|
||||
*
|
||||
* With the key context, a HMAC context can be initialized to process
|
||||
* the input bytes and obtain the MAC output. The key context is not
|
||||
* modified during that process, and can be reused.
|
||||
*
|
||||
* IMPORTANT: HMAC shall be used only with functions that have the
|
||||
* following properties:
|
||||
*
|
||||
* - hash output size does not exceed 64 bytes;
|
||||
* - hash internal state size does not exceed 64 bytes;
|
||||
* - internal block length is a power of 2 between 16 and 256 bytes.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief HMAC key context.
|
||||
*
|
||||
* The HMAC key context is initialised with a hash function implementation
|
||||
* and a secret key. Contents are opaque (callers should not access them
|
||||
* directly). The caller is responsible for allocating the context where
|
||||
* appropriate. Context initialisation and usage incurs no dynamic
|
||||
* allocation, so there is no release function.
|
||||
*/
|
||||
typedef struct {
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
const br_hash_class *dig_vtable;
|
||||
unsigned char ksi[64], kso[64];
|
||||
#endif
|
||||
} br_hmac_key_context;
|
||||
|
||||
/**
|
||||
* \brief HMAC key context initialisation.
|
||||
*
|
||||
* Initialise the key context with the provided key, using the hash function
|
||||
* identified by `digest_vtable`. This supports arbitrary key lengths.
|
||||
*
|
||||
* \param kc HMAC key context to initialise.
|
||||
* \param digest_vtable pointer to the hash function implementation vtable.
|
||||
* \param key pointer to the HMAC secret key.
|
||||
* \param key_len HMAC secret key length (in bytes).
|
||||
*/
|
||||
void br_hmac_key_init(br_hmac_key_context *kc,
|
||||
const br_hash_class *digest_vtable, const void *key, size_t key_len);
|
||||
|
||||
/*
|
||||
* \brief Get the underlying hash function.
|
||||
*
|
||||
* This function returns a pointer to the implementation vtable of the
|
||||
* hash function used for this HMAC key context.
|
||||
*
|
||||
* \param kc HMAC key context.
|
||||
* \return the hash function implementation.
|
||||
*/
|
||||
static inline const br_hash_class *br_hmac_key_get_digest(
|
||||
const br_hmac_key_context *kc)
|
||||
{
|
||||
return kc->dig_vtable;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief HMAC computation context.
|
||||
*
|
||||
* The HMAC computation context maintains the state for a single HMAC
|
||||
* computation. It is modified as input bytes are injected. The context
|
||||
* is caller-allocated and has no release function since it does not
|
||||
* dynamically allocate external resources. Its contents are opaque.
|
||||
*/
|
||||
typedef struct {
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
br_hash_compat_context dig;
|
||||
unsigned char kso[64];
|
||||
size_t out_len;
|
||||
#endif
|
||||
} br_hmac_context;
|
||||
|
||||
/**
|
||||
* \brief HMAC computation initialisation.
|
||||
*
|
||||
* Initialise a HMAC context with a key context. The key context is
|
||||
* unmodified. Relevant data from the key context is immediately copied;
|
||||
* the key context can thus be independently reused, modified or released
|
||||
* without impacting this HMAC computation.
|
||||
*
|
||||
* An explicit output length can be specified; the actual output length
|
||||
* will be the minimum of that value and the natural HMAC output length.
|
||||
* If `out_len` is 0, then the natural HMAC output length is selected. The
|
||||
* "natural output length" is the output length of the underlying hash
|
||||
* function.
|
||||
*
|
||||
* \param ctx HMAC context to initialise.
|
||||
* \param kc HMAC key context (already initialised with the key).
|
||||
* \param out_len HMAC output length (0 to select "natural length").
|
||||
*/
|
||||
void br_hmac_init(br_hmac_context *ctx,
|
||||
const br_hmac_key_context *kc, size_t out_len);
|
||||
|
||||
/**
|
||||
* \brief Get the HMAC output size.
|
||||
*
|
||||
* The HMAC output size is the number of bytes that will actually be
|
||||
* produced with `br_hmac_out()` with the provided context. This function
|
||||
* MUST NOT be called on a non-initialised HMAC computation context.
|
||||
* The returned value is the minimum of the HMAC natural length (output
|
||||
* size of the underlying hash function) and the `out_len` parameter which
|
||||
* was used with the last `br_hmac_init()` call on that context (if the
|
||||
* initialisation `out_len` parameter was 0, then this function will
|
||||
* return the HMAC natural length).
|
||||
*
|
||||
* \param ctx the (already initialised) HMAC computation context.
|
||||
* \return the HMAC actual output size.
|
||||
*/
|
||||
static inline size_t
|
||||
br_hmac_size(br_hmac_context *ctx)
|
||||
{
|
||||
return ctx->out_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* \brief Get the underlying hash function.
|
||||
*
|
||||
* This function returns a pointer to the implementation vtable of the
|
||||
* hash function used for this HMAC context.
|
||||
*
|
||||
* \param hc HMAC context.
|
||||
* \return the hash function implementation.
|
||||
*/
|
||||
static inline const br_hash_class *br_hmac_get_digest(
|
||||
const br_hmac_context *hc)
|
||||
{
|
||||
return hc->dig.vtable;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Inject some bytes in HMAC.
|
||||
*
|
||||
* The provided `len` bytes are injected as extra input in the HMAC
|
||||
* computation incarnated by the `ctx` HMAC context. It is acceptable
|
||||
* that `len` is zero, in which case `data` is ignored (and may be
|
||||
* `NULL`) and this function does nothing.
|
||||
*/
|
||||
void br_hmac_update(br_hmac_context *ctx, const void *data, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Compute the HMAC output.
|
||||
*
|
||||
* The destination buffer MUST be large enough to accommodate the result;
|
||||
* its length is at most the "natural length" of HMAC (i.e. the output
|
||||
* length of the underlying hash function). The context is NOT modified;
|
||||
* further bytes may be processed. Thus, "partial HMAC" values can be
|
||||
* efficiently obtained.
|
||||
*
|
||||
* Returned value is the output length (in bytes).
|
||||
*
|
||||
* \param ctx HMAC computation context.
|
||||
* \param out destination buffer for the HMAC output.
|
||||
* \return the produced value length (in bytes).
|
||||
*/
|
||||
size_t br_hmac_out(const br_hmac_context *ctx, void *out);
|
||||
|
||||
/**
|
||||
* \brief Constant-time HMAC computation.
|
||||
*
|
||||
* This function compute the HMAC output in constant time. Some extra
|
||||
* input bytes are processed, then the output is computed. The extra
|
||||
* input consists in the `len` bytes pointed to by `data`. The `len`
|
||||
* parameter must lie between `min_len` and `max_len` (inclusive);
|
||||
* `max_len` bytes are actually read from `data`. Computing time (and
|
||||
* memory access pattern) will not depend upon the data byte contents or
|
||||
* the value of `len`.
|
||||
*
|
||||
* The output is written in the `out` buffer, that MUST be large enough
|
||||
* to receive it.
|
||||
*
|
||||
* The difference `max_len - min_len` MUST be less than 2<sup>30</sup>
|
||||
* (i.e. about one gigabyte).
|
||||
*
|
||||
* This function computes the output properly only if the underlying
|
||||
* hash function uses MD padding (i.e. MD5, SHA-1, SHA-224, SHA-256,
|
||||
* SHA-384 or SHA-512).
|
||||
*
|
||||
* The provided context is NOT modified.
|
||||
*
|
||||
* \param ctx the (already initialised) HMAC computation context.
|
||||
* \param data the extra input bytes.
|
||||
* \param len the extra input length (in bytes).
|
||||
* \param min_len minimum extra input length (in bytes).
|
||||
* \param max_len maximum extra input length (in bytes).
|
||||
* \param out destination buffer for the HMAC output.
|
||||
* \return the produced value length (in bytes).
|
||||
*/
|
||||
size_t br_hmac_outCT(const br_hmac_context *ctx,
|
||||
const void *data, size_t len, size_t min_len, size_t max_len,
|
||||
void *out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BR_BEARSSL_KDF_H__
|
||||
#define BR_BEARSSL_KDF_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bearssl_hash.h"
|
||||
#include "bearssl_hmac.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file bearssl_kdf.h
|
||||
*
|
||||
* # Key Derivation Functions
|
||||
*
|
||||
* KDF are functions that takes a variable length input, and provide a
|
||||
* variable length output, meant to be used to derive subkeys from a
|
||||
* master key.
|
||||
*
|
||||
* ## HKDF
|
||||
*
|
||||
* HKDF is a KDF defined by [RFC 5869](https://tools.ietf.org/html/rfc5869).
|
||||
* It is based on HMAC, itself using an underlying hash function. Any
|
||||
* hash function can be used, as long as it is compatible with the rules
|
||||
* for the HMAC implementation (i.e. output size is 64 bytes or less, hash
|
||||
* internal state size is 64 bytes or less, and the internal block length is
|
||||
* a power of 2 between 16 and 256 bytes). HKDF has two phases:
|
||||
*
|
||||
* - HKDF-Extract: the input data in ingested, along with a "salt" value.
|
||||
*
|
||||
* - HKDF-Expand: the output is produced, from the result of processing
|
||||
* the input and salt, and using an extra non-secret parameter called
|
||||
* "info".
|
||||
*
|
||||
* The "salt" and "info" strings are non-secret and can be empty. Their role
|
||||
* is normally to bind the input and output, respectively, to conventional
|
||||
* identifiers that qualifu them within the used protocol or application.
|
||||
*
|
||||
* The implementation defined in this file uses the following functions:
|
||||
*
|
||||
* - `br_hkdf_init()`: initialize an HKDF context, with a hash function,
|
||||
* and the salt. This starts the HKDF-Extract process.
|
||||
*
|
||||
* - `br_hkdf_inject()`: inject more input bytes. This function may be
|
||||
* called repeatedly if the input data is provided by chunks.
|
||||
*
|
||||
* - `br_hkdf_flip()`: end the HKDF-Extract process, and start the
|
||||
* HKDF-Expand process.
|
||||
*
|
||||
* - `br_hkdf_produce()`: get the next bytes of output. This function
|
||||
* may be called several times to obtain the full output by chunks.
|
||||
* For correct HKDF processing, the same "info" string must be
|
||||
* provided for each call.
|
||||
*
|
||||
* Note that the HKDF total output size (the number of bytes that
|
||||
* HKDF-Expand is willing to produce) is limited: if the hash output size
|
||||
* is _n_ bytes, then the maximum output size is _255*n_.
|
||||
*
|
||||
* ## SHAKE
|
||||
*
|
||||
* SHAKE is defined in
|
||||
* [FIPS 202](https://csrc.nist.gov/publications/detail/fips/202/final)
|
||||
* under two versions: SHAKE128 and SHAKE256, offering an alleged
|
||||
* "security level" of 128 and 256 bits, respectively (SHAKE128 is
|
||||
* about 20 to 25% faster than SHAKE256). SHAKE internally relies on
|
||||
* the Keccak family of sponge functions, not on any externally provided
|
||||
* hash function. Contrary to HKDF, SHAKE does not have a concept of
|
||||
* either a "salt" or an "info" string. The API consists in four
|
||||
* functions:
|
||||
*
|
||||
* - `br_shake_init()`: initialize a SHAKE context for a given
|
||||
* security level.
|
||||
*
|
||||
* - `br_shake_inject()`: inject more input bytes. This function may be
|
||||
* called repeatedly if the input data is provided by chunks.
|
||||
*
|
||||
* - `br_shake_flip()`: end the data injection process, and start the
|
||||
* data production process.
|
||||
*
|
||||
* - `br_shake_produce()`: get the next bytes of output. This function
|
||||
* may be called several times to obtain the full output by chunks.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief HKDF context.
|
||||
*
|
||||
* The HKDF context is initialized with a hash function implementation
|
||||
* and a salt value. Contents are opaque (callers should not access them
|
||||
* directly). The caller is responsible for allocating the context where
|
||||
* appropriate. Context initialisation and usage incurs no dynamic
|
||||
* allocation, so there is no release function.
|
||||
*/
|
||||
typedef struct {
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
union {
|
||||
br_hmac_context hmac_ctx;
|
||||
br_hmac_key_context prk_ctx;
|
||||
} u;
|
||||
unsigned char buf[64];
|
||||
size_t ptr;
|
||||
size_t dig_len;
|
||||
unsigned chunk_num;
|
||||
#endif
|
||||
} br_hkdf_context;
|
||||
|
||||
/**
|
||||
* \brief HKDF context initialization.
|
||||
*
|
||||
* The underlying hash function and salt value are provided. Arbitrary
|
||||
* salt lengths can be used.
|
||||
*
|
||||
* HKDF makes a difference between a salt of length zero, and an
|
||||
* absent salt (the latter being equivalent to a salt consisting of
|
||||
* bytes of value zero, of the same length as the hash function output).
|
||||
* If `salt_len` is zero, then this function assumes that the salt is
|
||||
* present but of length zero. To specify an _absent_ salt, use
|
||||
* `BR_HKDF_NO_SALT` as `salt` parameter (`salt_len` is then ignored).
|
||||
*
|
||||
* \param hc HKDF context to initialise.
|
||||
* \param digest_vtable pointer to the hash function implementation vtable.
|
||||
* \param salt HKDF-Extract salt.
|
||||
* \param salt_len HKDF-Extract salt length (in bytes).
|
||||
*/
|
||||
void br_hkdf_init(br_hkdf_context *hc, const br_hash_class *digest_vtable,
|
||||
const void *salt, size_t salt_len);
|
||||
|
||||
/**
|
||||
* \brief The special "absent salt" value for HKDF.
|
||||
*/
|
||||
#define BR_HKDF_NO_SALT (&br_hkdf_no_salt)
|
||||
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
extern const unsigned char br_hkdf_no_salt;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief HKDF input injection (HKDF-Extract).
|
||||
*
|
||||
* This function injects some more input bytes ("key material") into
|
||||
* HKDF. This function may be called several times, after `br_hkdf_init()`
|
||||
* but before `br_hkdf_flip()`.
|
||||
*
|
||||
* \param hc HKDF context.
|
||||
* \param ikm extra input bytes.
|
||||
* \param ikm_len number of extra input bytes.
|
||||
*/
|
||||
void br_hkdf_inject(br_hkdf_context *hc, const void *ikm, size_t ikm_len);
|
||||
|
||||
/**
|
||||
* \brief HKDF switch to the HKDF-Expand phase.
|
||||
*
|
||||
* This call terminates the HKDF-Extract process (input injection), and
|
||||
* starts the HKDF-Expand process (output production).
|
||||
*
|
||||
* \param hc HKDF context.
|
||||
*/
|
||||
void br_hkdf_flip(br_hkdf_context *hc);
|
||||
|
||||
/**
|
||||
* \brief HKDF output production (HKDF-Expand).
|
||||
*
|
||||
* Produce more output bytes from the current state. This function may be
|
||||
* called several times, but only after `br_hkdf_flip()`.
|
||||
*
|
||||
* Returned value is the number of actually produced bytes. The total
|
||||
* output length is limited to 255 times the output length of the
|
||||
* underlying hash function.
|
||||
*
|
||||
* \param hc HKDF context.
|
||||
* \param info application specific information string.
|
||||
* \param info_len application specific information string length (in bytes).
|
||||
* \param out destination buffer for the HKDF output.
|
||||
* \param out_len the length of the requested output (in bytes).
|
||||
* \return the produced output length (in bytes).
|
||||
*/
|
||||
size_t br_hkdf_produce(br_hkdf_context *hc,
|
||||
const void *info, size_t info_len, void *out, size_t out_len);
|
||||
|
||||
/**
|
||||
* \brief SHAKE context.
|
||||
*
|
||||
* The HKDF context is initialized with a "security level". The internal
|
||||
* notion is called "capacity"; the capacity is twice the security level
|
||||
* (for instance, SHAKE128 has capacity 256).
|
||||
*
|
||||
* The caller is responsible for allocating the context where
|
||||
* appropriate. Context initialisation and usage incurs no dynamic
|
||||
* allocation, so there is no release function.
|
||||
*/
|
||||
typedef struct {
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
unsigned char dbuf[200];
|
||||
size_t dptr;
|
||||
size_t rate;
|
||||
uint64_t A[25];
|
||||
#endif
|
||||
} br_shake_context;
|
||||
|
||||
/**
|
||||
* \brief SHAKE context initialization.
|
||||
*
|
||||
* The context is initialized for the provided "security level".
|
||||
* Internally, this sets the "capacity" to twice the security level;
|
||||
* thus, for SHAKE128, the `security_level` parameter should be 128,
|
||||
* which corresponds to a 256-bit capacity.
|
||||
*
|
||||
* Allowed security levels are all multiples of 32, from 32 to 768,
|
||||
* inclusive. Larger security levels imply lower performance; levels
|
||||
* beyond 256 bits don't make much sense. Standard levels are 128
|
||||
* and 256 bits (for SHAKE128 and SHAKE256, respectively).
|
||||
*
|
||||
* \param sc SHAKE context to initialise.
|
||||
* \param security_level security level (in bits).
|
||||
*/
|
||||
void br_shake_init(br_shake_context *sc, int security_level);
|
||||
|
||||
/**
|
||||
* \brief SHAKE input injection.
|
||||
*
|
||||
* This function injects some more input bytes ("key material") into
|
||||
* SHAKE. This function may be called several times, after `br_shake_init()`
|
||||
* but before `br_shake_flip()`.
|
||||
*
|
||||
* \param sc SHAKE context.
|
||||
* \param data extra input bytes.
|
||||
* \param len number of extra input bytes.
|
||||
*/
|
||||
void br_shake_inject(br_shake_context *sc, const void *data, size_t len);
|
||||
|
||||
/**
|
||||
* \brief SHAKE switch to production phase.
|
||||
*
|
||||
* This call terminates the input injection process, and starts the
|
||||
* output production process.
|
||||
*
|
||||
* \param sc SHAKE context.
|
||||
*/
|
||||
void br_shake_flip(br_shake_context *hc);
|
||||
|
||||
/**
|
||||
* \brief SHAKE output production.
|
||||
*
|
||||
* Produce more output bytes from the current state. This function may be
|
||||
* called several times, but only after `br_shake_flip()`.
|
||||
*
|
||||
* There is no practical limit to the number of bytes that may be produced.
|
||||
*
|
||||
* \param sc SHAKE context.
|
||||
* \param out destination buffer for the SHAKE output.
|
||||
* \param len the length of the requested output (in bytes).
|
||||
*/
|
||||
void br_shake_produce(br_shake_context *sc, void *out, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BR_BEARSSL_PEM_H__
|
||||
#define BR_BEARSSL_PEM_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file bearssl_pem.h
|
||||
*
|
||||
* # PEM Support
|
||||
*
|
||||
* PEM is a traditional encoding layer use to store binary objects (in
|
||||
* particular X.509 certificates, and private keys) in text files. While
|
||||
* the acronym comes from an old, defunct standard ("Privacy Enhanced
|
||||
* Mail"), the format has been reused, with some variations, by many
|
||||
* systems, and is a _de facto_ standard, even though it is not, actually,
|
||||
* specified in all clarity anywhere.
|
||||
*
|
||||
* ## Format Details
|
||||
*
|
||||
* BearSSL contains a generic, streamed PEM decoder, which handles the
|
||||
* following format:
|
||||
*
|
||||
* - The input source (a sequence of bytes) is assumed to be the
|
||||
* encoding of a text file in an ASCII-compatible charset. This
|
||||
* includes ISO-8859-1, Windows-1252, and UTF-8 encodings. Each
|
||||
* line ends on a newline character (U+000A LINE FEED). The
|
||||
* U+000D CARRIAGE RETURN characters are ignored, so the code
|
||||
* accepts both Windows-style and Unix-style line endings.
|
||||
*
|
||||
* - Each object begins with a banner that occurs at the start of
|
||||
* a line; the first banner characters are "`-----BEGIN `" (five
|
||||
* dashes, the word "BEGIN", and a space). The banner matching is
|
||||
* not case-sensitive.
|
||||
*
|
||||
* - The _object name_ consists in the characters that follow the
|
||||
* banner start sequence, up to the end of the line, but without
|
||||
* trailing dashes (in "normal" PEM, there are five trailing
|
||||
* dashes, but this implementation is not picky about these dashes).
|
||||
* The BearSSL decoder normalises the name characters to uppercase
|
||||
* (for ASCII letters only) and accepts names up to 127 characters.
|
||||
*
|
||||
* - The object ends with a banner that again occurs at the start of
|
||||
* a line, and starts with "`-----END `" (again case-insensitive).
|
||||
*
|
||||
* - Between that start and end banner, only Base64 data shall occur.
|
||||
* Base64 converts each sequence of three bytes into four
|
||||
* characters; the four characters are ASCII letters, digits, "`+`"
|
||||
* or "`-`" signs, and one or two "`=`" signs may occur in the last
|
||||
* quartet. Whitespace is ignored (whitespace is any ASCII character
|
||||
* of code 32 or less, so control characters are whitespace) and
|
||||
* lines may have arbitrary length; the only restriction is that the
|
||||
* four characters of a quartet must appear on the same line (no
|
||||
* line break inside a quartet).
|
||||
*
|
||||
* - A single file may contain more than one PEM object. Bytes that
|
||||
* occur between objects are ignored.
|
||||
*
|
||||
*
|
||||
* ## PEM Decoder API
|
||||
*
|
||||
* The PEM decoder offers a state-machine API. The caller allocates a
|
||||
* decoder context, then injects source bytes. Source bytes are pushed
|
||||
* with `br_pem_decoder_push()`. The decoder stops accepting bytes when
|
||||
* it reaches an "event", which is either the start of an object, the
|
||||
* end of an object, or a decoding error within an object.
|
||||
*
|
||||
* The `br_pem_decoder_event()` function is used to obtain the current
|
||||
* event; it also clears it, thus allowing the decoder to accept more
|
||||
* bytes. When a object start event is raised, the decoder context
|
||||
* offers the found object name (normalised to ASCII uppercase).
|
||||
*
|
||||
* When an object is reached, the caller must set an appropriate callback
|
||||
* function, which will receive (by chunks) the decoded object data.
|
||||
*
|
||||
* Since the decoder context makes no dynamic allocation, it requires
|
||||
* no explicit deallocation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief PEM decoder context.
|
||||
*
|
||||
* Contents are opaque (they should not be accessed directly).
|
||||
*/
|
||||
typedef struct {
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
/* CPU for the T0 virtual machine. */
|
||||
struct {
|
||||
uint32_t *dp;
|
||||
uint32_t *rp;
|
||||
const unsigned char *ip;
|
||||
} cpu;
|
||||
uint32_t dp_stack[32];
|
||||
uint32_t rp_stack[32];
|
||||
int err;
|
||||
|
||||
const unsigned char *hbuf;
|
||||
size_t hlen;
|
||||
|
||||
void (*dest)(void *dest_ctx, const void *src, size_t len);
|
||||
void *dest_ctx;
|
||||
|
||||
unsigned char event;
|
||||
char name[128];
|
||||
unsigned char buf[255];
|
||||
size_t ptr;
|
||||
#endif
|
||||
} br_pem_decoder_context;
|
||||
|
||||
/**
|
||||
* \brief Initialise a PEM decoder structure.
|
||||
*
|
||||
* \param ctx decoder context to initialise.
|
||||
*/
|
||||
void br_pem_decoder_init(br_pem_decoder_context *ctx);
|
||||
|
||||
/**
|
||||
* \brief Push some bytes into the decoder.
|
||||
*
|
||||
* Returned value is the number of bytes actually consumed; this may be
|
||||
* less than the number of provided bytes if an event is raised. When an
|
||||
* event is raised, it must be read (with `br_pem_decoder_event()`);
|
||||
* until the event is read, this function will return 0.
|
||||
*
|
||||
* \param ctx decoder context.
|
||||
* \param data new data bytes.
|
||||
* \param len number of new data bytes.
|
||||
* \return the number of bytes actually received (may be less than `len`).
|
||||
*/
|
||||
size_t br_pem_decoder_push(br_pem_decoder_context *ctx,
|
||||
const void *data, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Set the receiver for decoded data.
|
||||
*
|
||||
* When an object is entered, the provided function (with opaque context
|
||||
* pointer) will be called repeatedly with successive chunks of decoded
|
||||
* data for that object. If `dest` is set to 0, then decoded data is
|
||||
* simply ignored. The receiver can be set at any time, but, in practice,
|
||||
* it should be called immediately after receiving a "start of object"
|
||||
* event.
|
||||
*
|
||||
* \param ctx decoder context.
|
||||
* \param dest callback for receiving decoded data.
|
||||
* \param dest_ctx opaque context pointer for the `dest` callback.
|
||||
*/
|
||||
static inline void
|
||||
br_pem_decoder_setdest(br_pem_decoder_context *ctx,
|
||||
void (*dest)(void *dest_ctx, const void *src, size_t len),
|
||||
void *dest_ctx)
|
||||
{
|
||||
ctx->dest = dest;
|
||||
ctx->dest_ctx = dest_ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the last event.
|
||||
*
|
||||
* If an event was raised, then this function returns the event value, and
|
||||
* also clears it, thereby allowing the decoder to proceed. If no event
|
||||
* was raised since the last call to `br_pem_decoder_event()`, then this
|
||||
* function returns 0.
|
||||
*
|
||||
* \param ctx decoder context.
|
||||
* \return the raised event, or 0.
|
||||
*/
|
||||
int br_pem_decoder_event(br_pem_decoder_context *ctx);
|
||||
|
||||
/**
|
||||
* \brief Event: start of object.
|
||||
*
|
||||
* This event is raised when the start of a new object has been detected.
|
||||
* The object name (normalised to uppercase) can be accessed with
|
||||
* `br_pem_decoder_name()`.
|
||||
*/
|
||||
#define BR_PEM_BEGIN_OBJ 1
|
||||
|
||||
/**
|
||||
* \brief Event: end of object.
|
||||
*
|
||||
* This event is raised when the end of the current object is reached
|
||||
* (normally, i.e. with no decoding error).
|
||||
*/
|
||||
#define BR_PEM_END_OBJ 2
|
||||
|
||||
/**
|
||||
* \brief Event: decoding error.
|
||||
*
|
||||
* This event is raised when decoding fails within an object.
|
||||
* This formally closes the current object and brings the decoder back
|
||||
* to the "out of any object" state. The offending line in the source
|
||||
* is consumed.
|
||||
*/
|
||||
#define BR_PEM_ERROR 3
|
||||
|
||||
/**
|
||||
* \brief Get the name of the encountered object.
|
||||
*
|
||||
* The encountered object name is defined only when the "start of object"
|
||||
* event is raised. That name is normalised to uppercase (for ASCII letters
|
||||
* only) and does not include trailing dashes.
|
||||
*
|
||||
* \param ctx decoder context.
|
||||
* \return the current object name.
|
||||
*/
|
||||
static inline const char *
|
||||
br_pem_decoder_name(br_pem_decoder_context *ctx)
|
||||
{
|
||||
return ctx->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Encode an object in PEM.
|
||||
*
|
||||
* This function encodes the provided binary object (`data`, of length `len`
|
||||
* bytes) into PEM. The `banner` text will be included in the header and
|
||||
* footer (e.g. use `"CERTIFICATE"` to get a `"BEGIN CERTIFICATE"` header).
|
||||
*
|
||||
* The length (in characters) of the PEM output is returned; that length
|
||||
* does NOT include the terminating zero, that this function nevertheless
|
||||
* adds. If using the returned value for allocation purposes, the allocated
|
||||
* buffer size MUST be at least one byte larger than the returned size.
|
||||
*
|
||||
* If `dest` is `NULL`, then the encoding does not happen; however, the
|
||||
* length of the encoded object is still computed and returned.
|
||||
*
|
||||
* The `data` pointer may be `NULL` only if `len` is zero (when encoding
|
||||
* an object of length zero, which is not very useful), or when `dest`
|
||||
* is `NULL` (in that case, source data bytes are ignored).
|
||||
*
|
||||
* Some `flags` can be specified to alter the encoding behaviour:
|
||||
*
|
||||
* - If `BR_PEM_LINE64` is set, then line-breaking will occur after
|
||||
* every 64 characters of output, instead of the default of 76.
|
||||
*
|
||||
* - If `BR_PEM_CRLF` is set, then end-of-line sequence will use
|
||||
* CR+LF instead of a single LF.
|
||||
*
|
||||
* The `data` and `dest` buffers may overlap, in which case the source
|
||||
* binary data is destroyed in the process. Note that the PEM-encoded output
|
||||
* is always larger than the source binary.
|
||||
*
|
||||
* \param dest the destination buffer (or `NULL`).
|
||||
* \param data the source buffer (can be `NULL` in some cases).
|
||||
* \param len the source length (in bytes).
|
||||
* \param banner the PEM banner expression.
|
||||
* \param flags the behavioural flags.
|
||||
* \return the PEM object length (in characters), EXCLUDING the final zero.
|
||||
*/
|
||||
size_t br_pem_encode(void *dest, const void *data, size_t len,
|
||||
const char *banner, unsigned flags);
|
||||
|
||||
/**
|
||||
* \brief PEM encoding flag: split lines at 64 characters.
|
||||
*/
|
||||
#define BR_PEM_LINE64 0x0001
|
||||
|
||||
/**
|
||||
* \brief PEM encoding flag: use CR+LF line endings.
|
||||
*/
|
||||
#define BR_PEM_CRLF 0x0002
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BR_BEARSSL_PRF_H__
|
||||
#define BR_BEARSSL_PRF_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file bearssl_prf.h
|
||||
*
|
||||
* # The TLS PRF
|
||||
*
|
||||
* The "PRF" is the pseudorandom function used internally during the
|
||||
* SSL/TLS handshake, notably to expand negotiated shared secrets into
|
||||
* the symmetric encryption keys that will be used to process the
|
||||
* application data.
|
||||
*
|
||||
* TLS 1.0 and 1.1 define a PRF that is based on both MD5 and SHA-1. This
|
||||
* is implemented by the `br_tls10_prf()` function.
|
||||
*
|
||||
* TLS 1.2 redefines the PRF, using an explicit hash function. The
|
||||
* `br_tls12_sha256_prf()` and `br_tls12_sha384_prf()` functions apply that
|
||||
* PRF with, respectively, SHA-256 and SHA-384. Most standard cipher suites
|
||||
* rely on the SHA-256 based PRF, but some use SHA-384.
|
||||
*
|
||||
* The PRF always uses as input three parameters: a "secret" (some
|
||||
* bytes), a "label" (ASCII string), and a "seed" (again some bytes). An
|
||||
* arbitrary output length can be produced. The "seed" is provided as an
|
||||
* arbitrary number of binary chunks, that gets internally concatenated.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Type for a seed chunk.
|
||||
*
|
||||
* Each chunk may have an arbitrary length, and may be empty (no byte at
|
||||
* all). If the chunk length is zero, then the pointer to the chunk data
|
||||
* may be `NULL`.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Pointer to the chunk data.
|
||||
*/
|
||||
const void *data;
|
||||
|
||||
/**
|
||||
* \brief Chunk length (in bytes).
|
||||
*/
|
||||
size_t len;
|
||||
} br_tls_prf_seed_chunk;
|
||||
|
||||
/**
|
||||
* \brief PRF implementation for TLS 1.0 and 1.1.
|
||||
*
|
||||
* This PRF is the one specified by TLS 1.0 and 1.1. It internally uses
|
||||
* MD5 and SHA-1.
|
||||
*
|
||||
* \param dst destination buffer.
|
||||
* \param len output length (in bytes).
|
||||
* \param secret secret value (key) for this computation.
|
||||
* \param secret_len length of "secret" (in bytes).
|
||||
* \param label PRF label (zero-terminated ASCII string).
|
||||
* \param seed_num number of seed chunks.
|
||||
* \param seed seed chnks for this computation (usually non-secret).
|
||||
*/
|
||||
void br_tls10_prf(void *dst, size_t len,
|
||||
const void *secret, size_t secret_len, const char *label,
|
||||
size_t seed_num, const br_tls_prf_seed_chunk *seed);
|
||||
|
||||
/**
|
||||
* \brief PRF implementation for TLS 1.2, with SHA-256.
|
||||
*
|
||||
* This PRF is the one specified by TLS 1.2, when the underlying hash
|
||||
* function is SHA-256.
|
||||
*
|
||||
* \param dst destination buffer.
|
||||
* \param len output length (in bytes).
|
||||
* \param secret secret value (key) for this computation.
|
||||
* \param secret_len length of "secret" (in bytes).
|
||||
* \param label PRF label (zero-terminated ASCII string).
|
||||
* \param seed_num number of seed chunks.
|
||||
* \param seed seed chnks for this computation (usually non-secret).
|
||||
*/
|
||||
void br_tls12_sha256_prf(void *dst, size_t len,
|
||||
const void *secret, size_t secret_len, const char *label,
|
||||
size_t seed_num, const br_tls_prf_seed_chunk *seed);
|
||||
|
||||
/**
|
||||
* \brief PRF implementation for TLS 1.2, with SHA-384.
|
||||
*
|
||||
* This PRF is the one specified by TLS 1.2, when the underlying hash
|
||||
* function is SHA-384.
|
||||
*
|
||||
* \param dst destination buffer.
|
||||
* \param len output length (in bytes).
|
||||
* \param secret secret value (key) for this computation.
|
||||
* \param secret_len length of "secret" (in bytes).
|
||||
* \param label PRF label (zero-terminated ASCII string).
|
||||
* \param seed_num number of seed chunks.
|
||||
* \param seed seed chnks for this computation (usually non-secret).
|
||||
*/
|
||||
void br_tls12_sha384_prf(void *dst, size_t len,
|
||||
const void *secret, size_t secret_len, const char *label,
|
||||
size_t seed_num, const br_tls_prf_seed_chunk *seed);
|
||||
|
||||
/**
|
||||
* brief A convenient type name for a PRF implementation.
|
||||
*
|
||||
* \param dst destination buffer.
|
||||
* \param len output length (in bytes).
|
||||
* \param secret secret value (key) for this computation.
|
||||
* \param secret_len length of "secret" (in bytes).
|
||||
* \param label PRF label (zero-terminated ASCII string).
|
||||
* \param seed_num number of seed chunks.
|
||||
* \param seed seed chnks for this computation (usually non-secret).
|
||||
*/
|
||||
typedef void (*br_tls_prf_impl)(void *dst, size_t len,
|
||||
const void *secret, size_t secret_len, const char *label,
|
||||
size_t seed_num, const br_tls_prf_seed_chunk *seed);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,397 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BR_BEARSSL_RAND_H__
|
||||
#define BR_BEARSSL_RAND_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bearssl_block.h"
|
||||
#include "bearssl_hash.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file bearssl_rand.h
|
||||
*
|
||||
* # Pseudo-Random Generators
|
||||
*
|
||||
* A PRNG is a state-based engine that outputs pseudo-random bytes on
|
||||
* demand. It is initialized with an initial seed, and additional seed
|
||||
* bytes can be added afterwards. Bytes produced depend on the seeds and
|
||||
* also on the exact sequence of calls (including sizes requested for
|
||||
* each call).
|
||||
*
|
||||
*
|
||||
* ## Procedural and OOP API
|
||||
*
|
||||
* For the PRNG of name "`xxx`", two API are provided. The _procedural_
|
||||
* API defined a context structure `br_xxx_context` and three functions:
|
||||
*
|
||||
* - `br_xxx_init()`
|
||||
*
|
||||
* Initialise the context with an initial seed.
|
||||
*
|
||||
* - `br_xxx_generate()`
|
||||
*
|
||||
* Produce some pseudo-random bytes.
|
||||
*
|
||||
* - `br_xxx_update()`
|
||||
*
|
||||
* Inject some additional seed.
|
||||
*
|
||||
* The initialisation function sets the first context field (`vtable`)
|
||||
* to a pointer to the vtable that supports the OOP API. The OOP API
|
||||
* provides access to the same functions through function pointers,
|
||||
* named `init()`, `generate()` and `update()`.
|
||||
*
|
||||
* Note that the context initialisation method may accept additional
|
||||
* parameters, provided as a 'const void *' pointer at API level. These
|
||||
* additional parameters depend on the implemented PRNG.
|
||||
*
|
||||
*
|
||||
* ## HMAC_DRBG
|
||||
*
|
||||
* HMAC_DRBG is defined in [NIST SP 800-90A Revision
|
||||
* 1](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf).
|
||||
* It uses HMAC repeatedly, over some configurable underlying hash
|
||||
* function. In BearSSL, it is implemented under the "`hmac_drbg`" name.
|
||||
* The "extra parameters" pointer for context initialisation should be
|
||||
* set to a pointer to the vtable for the underlying hash function (e.g.
|
||||
* pointer to `br_sha256_vtable` to use HMAC_DRBG with SHA-256).
|
||||
*
|
||||
* According to the NIST standard, each request shall produce up to
|
||||
* 2<sup>19</sup> bits (i.e. 64 kB of data); moreover, the context shall
|
||||
* be reseeded at least once every 2<sup>48</sup> requests. This
|
||||
* implementation does not maintain the reseed counter (the threshold is
|
||||
* too high to be reached in practice) and does not object to producing
|
||||
* more than 64 kB in a single request; thus, the code cannot fail,
|
||||
* which corresponds to the fact that the API has no room for error
|
||||
* codes. However, this implies that requesting more than 64 kB in one
|
||||
* `generate()` request, or making more than 2<sup>48</sup> requests
|
||||
* without reseeding, is formally out of NIST specification. There is
|
||||
* no currently known security penalty for exceeding the NIST limits,
|
||||
* and, in any case, HMAC_DRBG usage in implementing SSL/TLS always
|
||||
* stays much below these thresholds.
|
||||
*
|
||||
*
|
||||
* ## AESCTR_DRBG
|
||||
*
|
||||
* AESCTR_DRBG is a custom PRNG based on AES-128 in CTR mode. This is
|
||||
* meant to be used only in situations where you are desperate for
|
||||
* speed, and have an hardware-optimized AES/CTR implementation. Whether
|
||||
* this will yield perceptible improvements depends on what you use the
|
||||
* pseudorandom bytes for, and how many you want; for instance, RSA key
|
||||
* pair generation uses a substantial amount of randomness, and using
|
||||
* AESCTR_DRBG instead of HMAC_DRBG yields a 15 to 20% increase in key
|
||||
* generation speed on a recent x86 CPU (Intel Core i7-6567U at 3.30 GHz).
|
||||
*
|
||||
* Internally, it uses CTR mode with successive counter values, starting
|
||||
* at zero (counter value expressed over 128 bits, big-endian convention).
|
||||
* The counter is not allowed to reach 32768; thus, every 32768*16 bytes
|
||||
* at most, the `update()` function is run (on an empty seed, if none is
|
||||
* provided). The `update()` function computes the new AES-128 key by
|
||||
* applying a custom hash function to the concatenation of a state-dependent
|
||||
* word (encryption of an all-one block with the current key) and the new
|
||||
* seed. The custom hash function uses Hirose's construction over AES-256;
|
||||
* see the comments in `aesctr_drbg.c` for details.
|
||||
*
|
||||
* This DRBG does not follow an existing standard, and thus should be
|
||||
* considered as inadequate for production use until it has been properly
|
||||
* analysed.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Class type for PRNG implementations.
|
||||
*
|
||||
* A `br_prng_class` instance references the methods implementing a PRNG.
|
||||
* Constant instances of this structure are defined for each implemented
|
||||
* PRNG. Such instances are also called "vtables".
|
||||
*/
|
||||
typedef struct br_prng_class_ br_prng_class;
|
||||
struct br_prng_class_ {
|
||||
/**
|
||||
* \brief Size (in bytes) of the context structure appropriate for
|
||||
* running this PRNG.
|
||||
*/
|
||||
size_t context_size;
|
||||
|
||||
/**
|
||||
* \brief Initialisation method.
|
||||
*
|
||||
* The context to initialise is provided as a pointer to its
|
||||
* first field (the vtable pointer); this function sets that
|
||||
* first field to a pointer to the vtable.
|
||||
*
|
||||
* The extra parameters depend on the implementation; each
|
||||
* implementation defines what kind of extra parameters it
|
||||
* expects (if any).
|
||||
*
|
||||
* Requirements on the initial seed depend on the implemented
|
||||
* PRNG.
|
||||
*
|
||||
* \param ctx PRNG context to initialise.
|
||||
* \param params extra parameters for the PRNG.
|
||||
* \param seed initial seed.
|
||||
* \param seed_len initial seed length (in bytes).
|
||||
*/
|
||||
void (*init)(const br_prng_class **ctx, const void *params,
|
||||
const void *seed, size_t seed_len);
|
||||
|
||||
/**
|
||||
* \brief Random bytes generation.
|
||||
*
|
||||
* This method produces `len` pseudorandom bytes, in the `out`
|
||||
* buffer. The context is updated accordingly.
|
||||
*
|
||||
* \param ctx PRNG context.
|
||||
* \param out output buffer.
|
||||
* \param len number of pseudorandom bytes to produce.
|
||||
*/
|
||||
void (*generate)(const br_prng_class **ctx, void *out, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Inject additional seed bytes.
|
||||
*
|
||||
* The provided seed bytes are added into the PRNG internal
|
||||
* entropy pool.
|
||||
*
|
||||
* \param ctx PRNG context.
|
||||
* \param seed additional seed.
|
||||
* \param seed_len additional seed length (in bytes).
|
||||
*/
|
||||
void (*update)(const br_prng_class **ctx,
|
||||
const void *seed, size_t seed_len);
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Context for HMAC_DRBG.
|
||||
*
|
||||
* The context contents are opaque, except the first field, which
|
||||
* supports OOP.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Pointer to the vtable.
|
||||
*
|
||||
* This field is set with the initialisation method/function.
|
||||
*/
|
||||
const br_prng_class *vtable;
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
unsigned char K[64];
|
||||
unsigned char V[64];
|
||||
const br_hash_class *digest_class;
|
||||
#endif
|
||||
} br_hmac_drbg_context;
|
||||
|
||||
/**
|
||||
* \brief Statically allocated, constant vtable for HMAC_DRBG.
|
||||
*/
|
||||
extern const br_prng_class br_hmac_drbg_vtable;
|
||||
|
||||
/**
|
||||
* \brief HMAC_DRBG initialisation.
|
||||
*
|
||||
* The context to initialise is provided as a pointer to its first field
|
||||
* (the vtable pointer); this function sets that first field to a
|
||||
* pointer to the vtable.
|
||||
*
|
||||
* The `seed` value is what is called, in NIST terminology, the
|
||||
* concatenation of the "seed", "nonce" and "personalization string", in
|
||||
* that order.
|
||||
*
|
||||
* The `digest_class` parameter defines the underlying hash function.
|
||||
* Formally, the NIST standard specifies that the hash function shall
|
||||
* be only SHA-1 or one of the SHA-2 functions. This implementation also
|
||||
* works with any other implemented hash function (such as MD5), but
|
||||
* this is non-standard and therefore not recommended.
|
||||
*
|
||||
* \param ctx HMAC_DRBG context to initialise.
|
||||
* \param digest_class vtable for the underlying hash function.
|
||||
* \param seed initial seed.
|
||||
* \param seed_len initial seed length (in bytes).
|
||||
*/
|
||||
void br_hmac_drbg_init(br_hmac_drbg_context *ctx,
|
||||
const br_hash_class *digest_class, const void *seed, size_t seed_len);
|
||||
|
||||
/**
|
||||
* \brief Random bytes generation with HMAC_DRBG.
|
||||
*
|
||||
* This method produces `len` pseudorandom bytes, in the `out`
|
||||
* buffer. The context is updated accordingly. Formally, requesting
|
||||
* more than 65536 bytes in one request falls out of specification
|
||||
* limits (but it won't fail).
|
||||
*
|
||||
* \param ctx HMAC_DRBG context.
|
||||
* \param out output buffer.
|
||||
* \param len number of pseudorandom bytes to produce.
|
||||
*/
|
||||
void br_hmac_drbg_generate(br_hmac_drbg_context *ctx, void *out, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Inject additional seed bytes in HMAC_DRBG.
|
||||
*
|
||||
* The provided seed bytes are added into the HMAC_DRBG internal
|
||||
* entropy pool. The process does not _replace_ existing entropy,
|
||||
* thus pushing non-random bytes (i.e. bytes which are known to the
|
||||
* attackers) does not degrade the overall quality of generated bytes.
|
||||
*
|
||||
* \param ctx HMAC_DRBG context.
|
||||
* \param seed additional seed.
|
||||
* \param seed_len additional seed length (in bytes).
|
||||
*/
|
||||
void br_hmac_drbg_update(br_hmac_drbg_context *ctx,
|
||||
const void *seed, size_t seed_len);
|
||||
|
||||
/**
|
||||
* \brief Get the hash function implementation used by a given instance of
|
||||
* HMAC_DRBG.
|
||||
*
|
||||
* This calls MUST NOT be performed on a context which was not
|
||||
* previously initialised.
|
||||
*
|
||||
* \param ctx HMAC_DRBG context.
|
||||
* \return the hash function vtable.
|
||||
*/
|
||||
static inline const br_hash_class *
|
||||
br_hmac_drbg_get_hash(const br_hmac_drbg_context *ctx)
|
||||
{
|
||||
return ctx->digest_class;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Type for a provider of entropy seeds.
|
||||
*
|
||||
* A "seeder" is a function that is able to obtain random values from
|
||||
* some source and inject them as entropy seed in a PRNG. A seeder
|
||||
* shall guarantee that the total entropy of the injected seed is large
|
||||
* enough to seed a PRNG for purposes of cryptographic key generation
|
||||
* (i.e. at least 128 bits).
|
||||
*
|
||||
* A seeder may report a failure to obtain adequate entropy. Seeders
|
||||
* shall endeavour to fix themselves transient errors by trying again;
|
||||
* thus, callers may consider reported errors as permanent.
|
||||
*
|
||||
* \param ctx PRNG context to seed.
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
typedef int (*br_prng_seeder)(const br_prng_class **ctx);
|
||||
|
||||
/**
|
||||
* \brief Get a seeder backed by the operating system or hardware.
|
||||
*
|
||||
* Get a seeder that feeds on RNG facilities provided by the current
|
||||
* operating system or hardware. If no such facility is known, then 0
|
||||
* is returned.
|
||||
*
|
||||
* If `name` is not `NULL`, then `*name` is set to a symbolic string
|
||||
* that identifies the seeder implementation. If no seeder is returned
|
||||
* and `name` is not `NULL`, then `*name` is set to a pointer to the
|
||||
* constant string `"none"`.
|
||||
*
|
||||
* \param name receiver for seeder name, or `NULL`.
|
||||
* \return the system seeder, if available, or 0.
|
||||
*/
|
||||
br_prng_seeder br_prng_seeder_system(const char **name);
|
||||
|
||||
/**
|
||||
* \brief Context for AESCTR_DRBG.
|
||||
*
|
||||
* The context contents are opaque, except the first field, which
|
||||
* supports OOP.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Pointer to the vtable.
|
||||
*
|
||||
* This field is set with the initialisation method/function.
|
||||
*/
|
||||
const br_prng_class *vtable;
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
br_aes_gen_ctr_keys sk;
|
||||
uint32_t cc;
|
||||
#endif
|
||||
} br_aesctr_drbg_context;
|
||||
|
||||
/**
|
||||
* \brief Statically allocated, constant vtable for AESCTR_DRBG.
|
||||
*/
|
||||
extern const br_prng_class br_aesctr_drbg_vtable;
|
||||
|
||||
/**
|
||||
* \brief AESCTR_DRBG initialisation.
|
||||
*
|
||||
* The context to initialise is provided as a pointer to its first field
|
||||
* (the vtable pointer); this function sets that first field to a
|
||||
* pointer to the vtable.
|
||||
*
|
||||
* The internal AES key is first set to the all-zero key; then, the
|
||||
* `br_aesctr_drbg_update()` function is called with the provided `seed`.
|
||||
* The call is performed even if the seed length (`seed_len`) is zero.
|
||||
*
|
||||
* The `aesctr` parameter defines the underlying AES/CTR implementation.
|
||||
*
|
||||
* \param ctx AESCTR_DRBG context to initialise.
|
||||
* \param aesctr vtable for the AES/CTR implementation.
|
||||
* \param seed initial seed (can be `NULL` if `seed_len` is zero).
|
||||
* \param seed_len initial seed length (in bytes).
|
||||
*/
|
||||
void br_aesctr_drbg_init(br_aesctr_drbg_context *ctx,
|
||||
const br_block_ctr_class *aesctr, const void *seed, size_t seed_len);
|
||||
|
||||
/**
|
||||
* \brief Random bytes generation with AESCTR_DRBG.
|
||||
*
|
||||
* This method produces `len` pseudorandom bytes, in the `out`
|
||||
* buffer. The context is updated accordingly.
|
||||
*
|
||||
* \param ctx AESCTR_DRBG context.
|
||||
* \param out output buffer.
|
||||
* \param len number of pseudorandom bytes to produce.
|
||||
*/
|
||||
void br_aesctr_drbg_generate(br_aesctr_drbg_context *ctx,
|
||||
void *out, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Inject additional seed bytes in AESCTR_DRBG.
|
||||
*
|
||||
* The provided seed bytes are added into the AESCTR_DRBG internal
|
||||
* entropy pool. The process does not _replace_ existing entropy,
|
||||
* thus pushing non-random bytes (i.e. bytes which are known to the
|
||||
* attackers) does not degrade the overall quality of generated bytes.
|
||||
*
|
||||
* \param ctx AESCTR_DRBG context.
|
||||
* \param seed additional seed.
|
||||
* \param seed_len additional seed length (in bytes).
|
||||
*/
|
||||
void br_aesctr_drbg_update(br_aesctr_drbg_context *ctx,
|
||||
const void *seed, size_t seed_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,967 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BR_BEARSSL_EC_H__
|
||||
#define BR_BEARSSL_EC_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bearssl_rand.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file bearssl_ec.h
|
||||
*
|
||||
* # Elliptic Curves
|
||||
*
|
||||
* This file documents the EC implementations provided with BearSSL, and
|
||||
* ECDSA.
|
||||
*
|
||||
* ## Elliptic Curve API
|
||||
*
|
||||
* Only "named curves" are supported. Each EC implementation supports
|
||||
* one or several named curves, identified by symbolic identifiers.
|
||||
* These identifiers are small integers, that correspond to the values
|
||||
* registered by the
|
||||
* [IANA](http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8).
|
||||
*
|
||||
* Since all currently defined elliptic curve identifiers are in the 0..31
|
||||
* range, it is convenient to encode support of some curves in a 32-bit
|
||||
* word, such that bit x corresponds to curve of identifier x.
|
||||
*
|
||||
* An EC implementation is incarnated by a `br_ec_impl` instance, that
|
||||
* offers the following fields:
|
||||
*
|
||||
* - `supported_curves`
|
||||
*
|
||||
* A 32-bit word that documents the identifiers of the curves supported
|
||||
* by this implementation.
|
||||
*
|
||||
* - `generator()`
|
||||
*
|
||||
* Callback method that returns a pointer to the conventional generator
|
||||
* point for that curve.
|
||||
*
|
||||
* - `order()`
|
||||
*
|
||||
* Callback method that returns a pointer to the subgroup order for
|
||||
* that curve. That value uses unsigned big-endian encoding.
|
||||
*
|
||||
* - `xoff()`
|
||||
*
|
||||
* Callback method that returns the offset and length of the X
|
||||
* coordinate in an encoded point.
|
||||
*
|
||||
* - `mul()`
|
||||
*
|
||||
* Multiply a curve point with an integer.
|
||||
*
|
||||
* - `mulgen()`
|
||||
*
|
||||
* Multiply the curve generator with an integer. This may be faster
|
||||
* than the generic `mul()`.
|
||||
*
|
||||
* - `muladd()`
|
||||
*
|
||||
* Multiply two curve points by two integers, and return the sum of
|
||||
* the two products.
|
||||
*
|
||||
* All curve points are represented in uncompressed format. The `mul()`
|
||||
* and `muladd()` methods take care to validate that the provided points
|
||||
* are really part of the relevant curve subgroup.
|
||||
*
|
||||
* For all point multiplication functions, the following holds:
|
||||
*
|
||||
* - Functions validate that the provided points are valid members
|
||||
* of the relevant curve subgroup. An error is reported if that is
|
||||
* not the case.
|
||||
*
|
||||
* - Processing is constant-time, even if the point operands are not
|
||||
* valid. This holds for both the source and resulting points, and
|
||||
* the multipliers (integers). Only the byte length of the provided
|
||||
* multiplier arrays (not their actual value length in bits) may
|
||||
* leak through timing-based side channels.
|
||||
*
|
||||
* - The multipliers (integers) MUST be lower than the subgroup order.
|
||||
* If this property is not met, then the result is indeterminate,
|
||||
* but an error value is not necessarily returned.
|
||||
*
|
||||
*
|
||||
* ## ECDSA
|
||||
*
|
||||
* ECDSA signatures have two standard formats, called "raw" and "asn1".
|
||||
* Internally, such a signature is a pair of modular integers `(r,s)`.
|
||||
* The "raw" format is the concatenation of the unsigned big-endian
|
||||
* encodings of these two integers, possibly left-padded with zeros so
|
||||
* that they have the same encoded length. The "asn1" format is the
|
||||
* DER encoding of an ASN.1 structure that contains the two integer
|
||||
* values:
|
||||
*
|
||||
* ECDSASignature ::= SEQUENCE {
|
||||
* r INTEGER,
|
||||
* s INTEGER
|
||||
* }
|
||||
*
|
||||
* In general, in all of X.509 and SSL/TLS, the "asn1" format is used.
|
||||
* BearSSL offers ECDSA implementations for both formats; conversion
|
||||
* functions between the two formats are also provided. Conversion of a
|
||||
* "raw" format signature into "asn1" may enlarge a signature by no more
|
||||
* than 9 bytes for all supported curves; conversely, conversion of an
|
||||
* "asn1" signature to "raw" may expand the signature but the "raw"
|
||||
* length will never be more than twice the length of the "asn1" length
|
||||
* (and usually it will be shorter).
|
||||
*
|
||||
* Note that for a given signature, the "raw" format is not fully
|
||||
* deterministic, in that it does not enforce a minimal common length.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Standard curve ID. These ID are equal to the assigned numerical
|
||||
* identifiers assigned to these curves for TLS:
|
||||
* http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
|
||||
*/
|
||||
|
||||
/** \brief Identifier for named curve sect163k1. */
|
||||
#define BR_EC_sect163k1 1
|
||||
|
||||
/** \brief Identifier for named curve sect163r1. */
|
||||
#define BR_EC_sect163r1 2
|
||||
|
||||
/** \brief Identifier for named curve sect163r2. */
|
||||
#define BR_EC_sect163r2 3
|
||||
|
||||
/** \brief Identifier for named curve sect193r1. */
|
||||
#define BR_EC_sect193r1 4
|
||||
|
||||
/** \brief Identifier for named curve sect193r2. */
|
||||
#define BR_EC_sect193r2 5
|
||||
|
||||
/** \brief Identifier for named curve sect233k1. */
|
||||
#define BR_EC_sect233k1 6
|
||||
|
||||
/** \brief Identifier for named curve sect233r1. */
|
||||
#define BR_EC_sect233r1 7
|
||||
|
||||
/** \brief Identifier for named curve sect239k1. */
|
||||
#define BR_EC_sect239k1 8
|
||||
|
||||
/** \brief Identifier for named curve sect283k1. */
|
||||
#define BR_EC_sect283k1 9
|
||||
|
||||
/** \brief Identifier for named curve sect283r1. */
|
||||
#define BR_EC_sect283r1 10
|
||||
|
||||
/** \brief Identifier for named curve sect409k1. */
|
||||
#define BR_EC_sect409k1 11
|
||||
|
||||
/** \brief Identifier for named curve sect409r1. */
|
||||
#define BR_EC_sect409r1 12
|
||||
|
||||
/** \brief Identifier for named curve sect571k1. */
|
||||
#define BR_EC_sect571k1 13
|
||||
|
||||
/** \brief Identifier for named curve sect571r1. */
|
||||
#define BR_EC_sect571r1 14
|
||||
|
||||
/** \brief Identifier for named curve secp160k1. */
|
||||
#define BR_EC_secp160k1 15
|
||||
|
||||
/** \brief Identifier for named curve secp160r1. */
|
||||
#define BR_EC_secp160r1 16
|
||||
|
||||
/** \brief Identifier for named curve secp160r2. */
|
||||
#define BR_EC_secp160r2 17
|
||||
|
||||
/** \brief Identifier for named curve secp192k1. */
|
||||
#define BR_EC_secp192k1 18
|
||||
|
||||
/** \brief Identifier for named curve secp192r1. */
|
||||
#define BR_EC_secp192r1 19
|
||||
|
||||
/** \brief Identifier for named curve secp224k1. */
|
||||
#define BR_EC_secp224k1 20
|
||||
|
||||
/** \brief Identifier for named curve secp224r1. */
|
||||
#define BR_EC_secp224r1 21
|
||||
|
||||
/** \brief Identifier for named curve secp256k1. */
|
||||
#define BR_EC_secp256k1 22
|
||||
|
||||
/** \brief Identifier for named curve secp256r1. */
|
||||
#define BR_EC_secp256r1 23
|
||||
|
||||
/** \brief Identifier for named curve secp384r1. */
|
||||
#define BR_EC_secp384r1 24
|
||||
|
||||
/** \brief Identifier for named curve secp521r1. */
|
||||
#define BR_EC_secp521r1 25
|
||||
|
||||
/** \brief Identifier for named curve brainpoolP256r1. */
|
||||
#define BR_EC_brainpoolP256r1 26
|
||||
|
||||
/** \brief Identifier for named curve brainpoolP384r1. */
|
||||
#define BR_EC_brainpoolP384r1 27
|
||||
|
||||
/** \brief Identifier for named curve brainpoolP512r1. */
|
||||
#define BR_EC_brainpoolP512r1 28
|
||||
|
||||
/** \brief Identifier for named curve Curve25519. */
|
||||
#define BR_EC_curve25519 29
|
||||
|
||||
/** \brief Identifier for named curve Curve448. */
|
||||
#define BR_EC_curve448 30
|
||||
|
||||
/**
|
||||
* \brief Structure for an EC public key.
|
||||
*/
|
||||
typedef struct {
|
||||
/** \brief Identifier for the curve used by this key. */
|
||||
int curve;
|
||||
/** \brief Public curve point (uncompressed format). */
|
||||
unsigned char *q;
|
||||
/** \brief Length of public curve point (in bytes). */
|
||||
size_t qlen;
|
||||
} br_ec_public_key;
|
||||
|
||||
/**
|
||||
* \brief Structure for an EC private key.
|
||||
*
|
||||
* The private key is an integer modulo the curve subgroup order. The
|
||||
* encoding below tolerates extra leading zeros. In general, it is
|
||||
* recommended that the private key has the same length as the curve
|
||||
* subgroup order.
|
||||
*/
|
||||
typedef struct {
|
||||
/** \brief Identifier for the curve used by this key. */
|
||||
int curve;
|
||||
/** \brief Private key (integer, unsigned big-endian encoding). */
|
||||
unsigned char *x;
|
||||
/** \brief Private key length (in bytes). */
|
||||
size_t xlen;
|
||||
} br_ec_private_key;
|
||||
|
||||
/**
|
||||
* \brief Type for an EC implementation.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Supported curves.
|
||||
*
|
||||
* This word is a bitfield: bit `x` is set if the curve of ID `x`
|
||||
* is supported. E.g. an implementation supporting both NIST P-256
|
||||
* (secp256r1, ID 23) and NIST P-384 (secp384r1, ID 24) will have
|
||||
* value `0x01800000` in this field.
|
||||
*/
|
||||
uint32_t supported_curves;
|
||||
|
||||
/**
|
||||
* \brief Get the conventional generator.
|
||||
*
|
||||
* This function returns the conventional generator (encoded
|
||||
* curve point) for the specified curve. This function MUST NOT
|
||||
* be called if the curve is not supported.
|
||||
*
|
||||
* \param curve curve identifier.
|
||||
* \param len receiver for the encoded generator length (in bytes).
|
||||
* \return the encoded generator.
|
||||
*/
|
||||
const unsigned char *(*generator)(int curve, size_t *len);
|
||||
|
||||
/**
|
||||
* \brief Get the subgroup order.
|
||||
*
|
||||
* This function returns the order of the subgroup generated by
|
||||
* the conventional generator, for the specified curve. Unsigned
|
||||
* big-endian encoding is used. This function MUST NOT be called
|
||||
* if the curve is not supported.
|
||||
*
|
||||
* \param curve curve identifier.
|
||||
* \param len receiver for the encoded order length (in bytes).
|
||||
* \return the encoded order.
|
||||
*/
|
||||
const unsigned char *(*order)(int curve, size_t *len);
|
||||
|
||||
/**
|
||||
* \brief Get the offset and length for the X coordinate.
|
||||
*
|
||||
* This function returns the offset and length (in bytes) of
|
||||
* the X coordinate in an encoded non-zero point.
|
||||
*
|
||||
* \param curve curve identifier.
|
||||
* \param len receiver for the X coordinate length (in bytes).
|
||||
* \return the offset for the X coordinate (in bytes).
|
||||
*/
|
||||
size_t (*xoff)(int curve, size_t *len);
|
||||
|
||||
/**
|
||||
* \brief Multiply a curve point by an integer.
|
||||
*
|
||||
* The source point is provided in array `G` (of size `Glen` bytes);
|
||||
* the multiplication result is written over it. The multiplier
|
||||
* `x` (of size `xlen` bytes) uses unsigned big-endian encoding.
|
||||
*
|
||||
* Rules:
|
||||
*
|
||||
* - The specified curve MUST be supported.
|
||||
*
|
||||
* - The source point must be a valid point on the relevant curve
|
||||
* subgroup (and not the "point at infinity" either). If this is
|
||||
* not the case, then this function returns an error (0).
|
||||
*
|
||||
* - The multiplier integer MUST be non-zero and less than the
|
||||
* curve subgroup order. If this property does not hold, then
|
||||
* the result is indeterminate and an error code is not
|
||||
* guaranteed.
|
||||
*
|
||||
* Returned value is 1 on success, 0 on error. On error, the
|
||||
* contents of `G` are indeterminate.
|
||||
*
|
||||
* \param G point to multiply.
|
||||
* \param Glen length of the encoded point (in bytes).
|
||||
* \param x multiplier (unsigned big-endian).
|
||||
* \param xlen multiplier length (in bytes).
|
||||
* \param curve curve identifier.
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t (*mul)(unsigned char *G, size_t Glen,
|
||||
const unsigned char *x, size_t xlen, int curve);
|
||||
|
||||
/**
|
||||
* \brief Multiply the generator by an integer.
|
||||
*
|
||||
* The multiplier MUST be non-zero and less than the curve
|
||||
* subgroup order. Results are indeterminate if this property
|
||||
* does not hold.
|
||||
*
|
||||
* \param R output buffer for the point.
|
||||
* \param x multiplier (unsigned big-endian).
|
||||
* \param xlen multiplier length (in bytes).
|
||||
* \param curve curve identifier.
|
||||
* \return encoded result point length (in bytes).
|
||||
*/
|
||||
size_t (*mulgen)(unsigned char *R,
|
||||
const unsigned char *x, size_t xlen, int curve);
|
||||
|
||||
/**
|
||||
* \brief Multiply two points by two integers and add the
|
||||
* results.
|
||||
*
|
||||
* The point `x*A + y*B` is computed and written back in the `A`
|
||||
* array.
|
||||
*
|
||||
* Rules:
|
||||
*
|
||||
* - The specified curve MUST be supported.
|
||||
*
|
||||
* - The source points (`A` and `B`) must be valid points on
|
||||
* the relevant curve subgroup (and not the "point at
|
||||
* infinity" either). If this is not the case, then this
|
||||
* function returns an error (0).
|
||||
*
|
||||
* - If the `B` pointer is `NULL`, then the conventional
|
||||
* subgroup generator is used. With some implementations,
|
||||
* this may be faster than providing a pointer to the
|
||||
* generator.
|
||||
*
|
||||
* - The multiplier integers (`x` and `y`) MUST be non-zero
|
||||
* and less than the curve subgroup order. If either integer
|
||||
* is zero, then an error is reported, but if one of them is
|
||||
* not lower than the subgroup order, then the result is
|
||||
* indeterminate and an error code is not guaranteed.
|
||||
*
|
||||
* - If the final result is the point at infinity, then an
|
||||
* error is returned.
|
||||
*
|
||||
* Returned value is 1 on success, 0 on error. On error, the
|
||||
* contents of `A` are indeterminate.
|
||||
*
|
||||
* \param A first point to multiply.
|
||||
* \param B second point to multiply (`NULL` for the generator).
|
||||
* \param len common length of the encoded points (in bytes).
|
||||
* \param x multiplier for `A` (unsigned big-endian).
|
||||
* \param xlen length of multiplier for `A` (in bytes).
|
||||
* \param y multiplier for `A` (unsigned big-endian).
|
||||
* \param ylen length of multiplier for `A` (in bytes).
|
||||
* \param curve curve identifier.
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t (*muladd)(unsigned char *A, const unsigned char *B, size_t len,
|
||||
const unsigned char *x, size_t xlen,
|
||||
const unsigned char *y, size_t ylen, int curve);
|
||||
} br_ec_impl;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "i31".
|
||||
*
|
||||
* This implementation internally uses generic code for modular integers,
|
||||
* with a representation as sequences of 31-bit words. It supports secp256r1,
|
||||
* secp384r1 and secp521r1 (aka NIST curves P-256, P-384 and P-521).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_prime_i31;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "i15".
|
||||
*
|
||||
* This implementation internally uses generic code for modular integers,
|
||||
* with a representation as sequences of 15-bit words. It supports secp256r1,
|
||||
* secp384r1 and secp521r1 (aka NIST curves P-256, P-384 and P-521).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_prime_i15;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m15" for P-256.
|
||||
*
|
||||
* This implementation uses specialised code for curve secp256r1 (also
|
||||
* known as NIST P-256), with optional Karatsuba decomposition, and fast
|
||||
* modular reduction thanks to the field modulus special format. Only
|
||||
* 32-bit multiplications are used (with 32-bit results, not 64-bit).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_p256_m15;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m31" for P-256.
|
||||
*
|
||||
* This implementation uses specialised code for curve secp256r1 (also
|
||||
* known as NIST P-256), relying on multiplications of 31-bit values
|
||||
* (MUL31).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_p256_m31;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m62" (specialised code) for P-256.
|
||||
*
|
||||
* This implementation uses custom code relying on multiplication of
|
||||
* integers up to 64 bits, with a 128-bit result. This implementation is
|
||||
* defined only on platforms that offer the 64x64->128 multiplication
|
||||
* support; use `br_ec_p256_m62_get()` to dynamically obtain a pointer
|
||||
* to that implementation.
|
||||
*/
|
||||
extern const br_ec_impl br_ec_p256_m62;
|
||||
|
||||
/**
|
||||
* \brief Get the "m62" implementation of P-256, if available.
|
||||
*
|
||||
* \return the implementation, or 0.
|
||||
*/
|
||||
const br_ec_impl *br_ec_p256_m62_get(void);
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m64" (specialised code) for P-256.
|
||||
*
|
||||
* This implementation uses custom code relying on multiplication of
|
||||
* integers up to 64 bits, with a 128-bit result. This implementation is
|
||||
* defined only on platforms that offer the 64x64->128 multiplication
|
||||
* support; use `br_ec_p256_m64_get()` to dynamically obtain a pointer
|
||||
* to that implementation.
|
||||
*/
|
||||
extern const br_ec_impl br_ec_p256_m64;
|
||||
|
||||
/**
|
||||
* \brief Get the "m64" implementation of P-256, if available.
|
||||
*
|
||||
* \return the implementation, or 0.
|
||||
*/
|
||||
const br_ec_impl *br_ec_p256_m64_get(void);
|
||||
|
||||
/**
|
||||
* \brief EC implementation "i15" (generic code) for Curve25519.
|
||||
*
|
||||
* This implementation uses the generic code for modular integers (with
|
||||
* 15-bit words) to support Curve25519. Due to the specificities of the
|
||||
* curve definition, the following applies:
|
||||
*
|
||||
* - `muladd()` is not implemented (the function returns 0 systematically).
|
||||
* - `order()` returns 2^255-1, since the point multiplication algorithm
|
||||
* accepts any 32-bit integer as input (it clears the top bit and low
|
||||
* three bits systematically).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_c25519_i15;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "i31" (generic code) for Curve25519.
|
||||
*
|
||||
* This implementation uses the generic code for modular integers (with
|
||||
* 31-bit words) to support Curve25519. Due to the specificities of the
|
||||
* curve definition, the following applies:
|
||||
*
|
||||
* - `muladd()` is not implemented (the function returns 0 systematically).
|
||||
* - `order()` returns 2^255-1, since the point multiplication algorithm
|
||||
* accepts any 32-bit integer as input (it clears the top bit and low
|
||||
* three bits systematically).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_c25519_i31;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m15" (specialised code) for Curve25519.
|
||||
*
|
||||
* This implementation uses custom code relying on multiplication of
|
||||
* integers up to 15 bits. Due to the specificities of the curve
|
||||
* definition, the following applies:
|
||||
*
|
||||
* - `muladd()` is not implemented (the function returns 0 systematically).
|
||||
* - `order()` returns 2^255-1, since the point multiplication algorithm
|
||||
* accepts any 32-bit integer as input (it clears the top bit and low
|
||||
* three bits systematically).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_c25519_m15;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m31" (specialised code) for Curve25519.
|
||||
*
|
||||
* This implementation uses custom code relying on multiplication of
|
||||
* integers up to 31 bits. Due to the specificities of the curve
|
||||
* definition, the following applies:
|
||||
*
|
||||
* - `muladd()` is not implemented (the function returns 0 systematically).
|
||||
* - `order()` returns 2^255-1, since the point multiplication algorithm
|
||||
* accepts any 32-bit integer as input (it clears the top bit and low
|
||||
* three bits systematically).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_c25519_m31;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m62" (specialised code) for Curve25519.
|
||||
*
|
||||
* This implementation uses custom code relying on multiplication of
|
||||
* integers up to 62 bits, with a 124-bit result. This implementation is
|
||||
* defined only on platforms that offer the 64x64->128 multiplication
|
||||
* support; use `br_ec_c25519_m62_get()` to dynamically obtain a pointer
|
||||
* to that implementation. Due to the specificities of the curve
|
||||
* definition, the following applies:
|
||||
*
|
||||
* - `muladd()` is not implemented (the function returns 0 systematically).
|
||||
* - `order()` returns 2^255-1, since the point multiplication algorithm
|
||||
* accepts any 32-bit integer as input (it clears the top bit and low
|
||||
* three bits systematically).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_c25519_m62;
|
||||
|
||||
/**
|
||||
* \brief Get the "m62" implementation of Curve25519, if available.
|
||||
*
|
||||
* \return the implementation, or 0.
|
||||
*/
|
||||
const br_ec_impl *br_ec_c25519_m62_get(void);
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m64" (specialised code) for Curve25519.
|
||||
*
|
||||
* This implementation uses custom code relying on multiplication of
|
||||
* integers up to 64 bits, with a 128-bit result. This implementation is
|
||||
* defined only on platforms that offer the 64x64->128 multiplication
|
||||
* support; use `br_ec_c25519_m64_get()` to dynamically obtain a pointer
|
||||
* to that implementation. Due to the specificities of the curve
|
||||
* definition, the following applies:
|
||||
*
|
||||
* - `muladd()` is not implemented (the function returns 0 systematically).
|
||||
* - `order()` returns 2^255-1, since the point multiplication algorithm
|
||||
* accepts any 32-bit integer as input (it clears the top bit and low
|
||||
* three bits systematically).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_c25519_m64;
|
||||
|
||||
/**
|
||||
* \brief Get the "m64" implementation of Curve25519, if available.
|
||||
*
|
||||
* \return the implementation, or 0.
|
||||
*/
|
||||
const br_ec_impl *br_ec_c25519_m64_get(void);
|
||||
|
||||
/**
|
||||
* \brief Aggregate EC implementation "m15".
|
||||
*
|
||||
* This implementation is a wrapper for:
|
||||
*
|
||||
* - `br_ec_c25519_m15` for Curve25519
|
||||
* - `br_ec_p256_m15` for NIST P-256
|
||||
* - `br_ec_prime_i15` for other curves (NIST P-384 and NIST-P512)
|
||||
*/
|
||||
extern const br_ec_impl br_ec_all_m15;
|
||||
|
||||
/**
|
||||
* \brief Aggregate EC implementation "m31".
|
||||
*
|
||||
* This implementation is a wrapper for:
|
||||
*
|
||||
* - `br_ec_c25519_m31` for Curve25519
|
||||
* - `br_ec_p256_m31` for NIST P-256
|
||||
* - `br_ec_prime_i31` for other curves (NIST P-384 and NIST-P512)
|
||||
*/
|
||||
extern const br_ec_impl br_ec_all_m31;
|
||||
|
||||
/**
|
||||
* \brief Get the "default" EC implementation for the current system.
|
||||
*
|
||||
* This returns a pointer to the preferred implementation on the
|
||||
* current system.
|
||||
*
|
||||
* \return the default EC implementation.
|
||||
*/
|
||||
const br_ec_impl *br_ec_get_default(void);
|
||||
|
||||
/**
|
||||
* \brief Convert a signature from "raw" to "asn1".
|
||||
*
|
||||
* Conversion is done "in place" and the new length is returned.
|
||||
* Conversion may enlarge the signature, but by no more than 9 bytes at
|
||||
* most. On error, 0 is returned (error conditions include an odd raw
|
||||
* signature length, or an oversized integer).
|
||||
*
|
||||
* \param sig signature to convert.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return the new signature length, or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_raw_to_asn1(void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief Convert a signature from "asn1" to "raw".
|
||||
*
|
||||
* Conversion is done "in place" and the new length is returned.
|
||||
* Conversion may enlarge the signature, but the new signature length
|
||||
* will be less than twice the source length at most. On error, 0 is
|
||||
* returned (error conditions include an invalid ASN.1 structure or an
|
||||
* oversized integer).
|
||||
*
|
||||
* \param sig signature to convert.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return the new signature length, or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_asn1_to_raw(void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief Type for an ECDSA signer function.
|
||||
*
|
||||
* A pointer to the EC implementation is provided. The hash value is
|
||||
* assumed to have the length inferred from the designated hash function
|
||||
* class.
|
||||
*
|
||||
* Signature is written in the buffer pointed to by `sig`, and the length
|
||||
* (in bytes) is returned. On error, nothing is written in the buffer,
|
||||
* and 0 is returned. This function returns 0 if the specified curve is
|
||||
* not supported by the provided EC implementation.
|
||||
*
|
||||
* The signature format is either "raw" or "asn1", depending on the
|
||||
* implementation; maximum length is predictable from the implemented
|
||||
* curve:
|
||||
*
|
||||
* | curve | raw | asn1 |
|
||||
* | :--------- | --: | ---: |
|
||||
* | NIST P-256 | 64 | 72 |
|
||||
* | NIST P-384 | 96 | 104 |
|
||||
* | NIST P-521 | 132 | 139 |
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hf hash function used to process the data.
|
||||
* \param hash_value signed data (hashed).
|
||||
* \param sk EC private key.
|
||||
* \param sig destination buffer.
|
||||
* \return the signature length (in bytes), or 0 on error.
|
||||
*/
|
||||
typedef size_t (*br_ecdsa_sign)(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig);
|
||||
|
||||
/**
|
||||
* \brief Type for an ECDSA signature verification function.
|
||||
*
|
||||
* A pointer to the EC implementation is provided. The hashed value,
|
||||
* computed over the purportedly signed data, is also provided with
|
||||
* its length.
|
||||
*
|
||||
* The signature format is either "raw" or "asn1", depending on the
|
||||
* implementation.
|
||||
*
|
||||
* Returned value is 1 on success (valid signature), 0 on error. This
|
||||
* function returns 0 if the specified curve is not supported by the
|
||||
* provided EC implementation.
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hash signed data (hashed).
|
||||
* \param hash_len hash value length (in bytes).
|
||||
* \param pk EC public key.
|
||||
* \param sig signature.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
typedef uint32_t (*br_ecdsa_vrfy)(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk, const void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature generator, "i31" implementation, "asn1" format.
|
||||
*
|
||||
* \see br_ecdsa_sign()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hf hash function used to process the data.
|
||||
* \param hash_value signed data (hashed).
|
||||
* \param sk EC private key.
|
||||
* \param sig destination buffer.
|
||||
* \return the signature length (in bytes), or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_i31_sign_asn1(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature generator, "i31" implementation, "raw" format.
|
||||
*
|
||||
* \see br_ecdsa_sign()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hf hash function used to process the data.
|
||||
* \param hash_value signed data (hashed).
|
||||
* \param sk EC private key.
|
||||
* \param sig destination buffer.
|
||||
* \return the signature length (in bytes), or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_i31_sign_raw(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature verifier, "i31" implementation, "asn1" format.
|
||||
*
|
||||
* \see br_ecdsa_vrfy()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hash signed data (hashed).
|
||||
* \param hash_len hash value length (in bytes).
|
||||
* \param pk EC public key.
|
||||
* \param sig signature.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t br_ecdsa_i31_vrfy_asn1(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk, const void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature verifier, "i31" implementation, "raw" format.
|
||||
*
|
||||
* \see br_ecdsa_vrfy()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hash signed data (hashed).
|
||||
* \param hash_len hash value length (in bytes).
|
||||
* \param pk EC public key.
|
||||
* \param sig signature.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t br_ecdsa_i31_vrfy_raw(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk, const void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature generator, "i15" implementation, "asn1" format.
|
||||
*
|
||||
* \see br_ecdsa_sign()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hf hash function used to process the data.
|
||||
* \param hash_value signed data (hashed).
|
||||
* \param sk EC private key.
|
||||
* \param sig destination buffer.
|
||||
* \return the signature length (in bytes), or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_i15_sign_asn1(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature generator, "i15" implementation, "raw" format.
|
||||
*
|
||||
* \see br_ecdsa_sign()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hf hash function used to process the data.
|
||||
* \param hash_value signed data (hashed).
|
||||
* \param sk EC private key.
|
||||
* \param sig destination buffer.
|
||||
* \return the signature length (in bytes), or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_i15_sign_raw(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature verifier, "i15" implementation, "asn1" format.
|
||||
*
|
||||
* \see br_ecdsa_vrfy()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hash signed data (hashed).
|
||||
* \param hash_len hash value length (in bytes).
|
||||
* \param pk EC public key.
|
||||
* \param sig signature.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t br_ecdsa_i15_vrfy_asn1(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk, const void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature verifier, "i15" implementation, "raw" format.
|
||||
*
|
||||
* \see br_ecdsa_vrfy()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hash signed data (hashed).
|
||||
* \param hash_len hash value length (in bytes).
|
||||
* \param pk EC public key.
|
||||
* \param sig signature.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t br_ecdsa_i15_vrfy_raw(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk, const void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief Get "default" ECDSA implementation (signer, asn1 format).
|
||||
*
|
||||
* This returns the preferred implementation of ECDSA signature generation
|
||||
* ("asn1" output format) on the current system.
|
||||
*
|
||||
* \return the default implementation.
|
||||
*/
|
||||
br_ecdsa_sign br_ecdsa_sign_asn1_get_default(void);
|
||||
|
||||
/**
|
||||
* \brief Get "default" ECDSA implementation (signer, raw format).
|
||||
*
|
||||
* This returns the preferred implementation of ECDSA signature generation
|
||||
* ("raw" output format) on the current system.
|
||||
*
|
||||
* \return the default implementation.
|
||||
*/
|
||||
br_ecdsa_sign br_ecdsa_sign_raw_get_default(void);
|
||||
|
||||
/**
|
||||
* \brief Get "default" ECDSA implementation (verifier, asn1 format).
|
||||
*
|
||||
* This returns the preferred implementation of ECDSA signature verification
|
||||
* ("asn1" output format) on the current system.
|
||||
*
|
||||
* \return the default implementation.
|
||||
*/
|
||||
br_ecdsa_vrfy br_ecdsa_vrfy_asn1_get_default(void);
|
||||
|
||||
/**
|
||||
* \brief Get "default" ECDSA implementation (verifier, raw format).
|
||||
*
|
||||
* This returns the preferred implementation of ECDSA signature verification
|
||||
* ("raw" output format) on the current system.
|
||||
*
|
||||
* \return the default implementation.
|
||||
*/
|
||||
br_ecdsa_vrfy br_ecdsa_vrfy_raw_get_default(void);
|
||||
|
||||
/**
|
||||
* \brief Maximum size for EC private key element buffer.
|
||||
*
|
||||
* This is the largest number of bytes that `br_ec_keygen()` may need or
|
||||
* ever return.
|
||||
*/
|
||||
#define BR_EC_KBUF_PRIV_MAX_SIZE 72
|
||||
|
||||
/**
|
||||
* \brief Maximum size for EC public key element buffer.
|
||||
*
|
||||
* This is the largest number of bytes that `br_ec_compute_public()` may
|
||||
* need or ever return.
|
||||
*/
|
||||
#define BR_EC_KBUF_PUB_MAX_SIZE 145
|
||||
|
||||
/**
|
||||
* \brief Generate a new EC private key.
|
||||
*
|
||||
* If the specified `curve` is not supported by the elliptic curve
|
||||
* implementation (`impl`), then this function returns zero.
|
||||
*
|
||||
* The `sk` structure fields are set to the new private key data. In
|
||||
* particular, `sk.x` is made to point to the provided key buffer (`kbuf`),
|
||||
* in which the actual private key data is written. That buffer is assumed
|
||||
* to be large enough. The `BR_EC_KBUF_PRIV_MAX_SIZE` defines the maximum
|
||||
* size for all supported curves.
|
||||
*
|
||||
* The number of bytes used in `kbuf` is returned. If `kbuf` is `NULL`, then
|
||||
* the private key is not actually generated, and `sk` may also be `NULL`;
|
||||
* the minimum length for `kbuf` is still computed and returned.
|
||||
*
|
||||
* If `sk` is `NULL` but `kbuf` is not `NULL`, then the private key is
|
||||
* still generated and stored in `kbuf`.
|
||||
*
|
||||
* \param rng_ctx source PRNG context (already initialized).
|
||||
* \param impl the elliptic curve implementation.
|
||||
* \param sk the private key structure to fill, or `NULL`.
|
||||
* \param kbuf the key element buffer, or `NULL`.
|
||||
* \param curve the curve identifier.
|
||||
* \return the key data length (in bytes), or zero.
|
||||
*/
|
||||
size_t br_ec_keygen(const br_prng_class **rng_ctx,
|
||||
const br_ec_impl *impl, br_ec_private_key *sk,
|
||||
void *kbuf, int curve);
|
||||
|
||||
/**
|
||||
* \brief Compute EC public key from EC private key.
|
||||
*
|
||||
* This function uses the provided elliptic curve implementation (`impl`)
|
||||
* to compute the public key corresponding to the private key held in `sk`.
|
||||
* The public key point is written into `kbuf`, which is then linked from
|
||||
* the `*pk` structure. The size of the public key point, i.e. the number
|
||||
* of bytes used in `kbuf`, is returned.
|
||||
*
|
||||
* If `kbuf` is `NULL`, then the public key point is NOT computed, and
|
||||
* the public key structure `*pk` is unmodified (`pk` may be `NULL` in
|
||||
* that case). The size of the public key point is still returned.
|
||||
*
|
||||
* If `pk` is `NULL` but `kbuf` is not `NULL`, then the public key
|
||||
* point is computed and stored in `kbuf`, and its size is returned.
|
||||
*
|
||||
* If the curve used by the private key is not supported by the curve
|
||||
* implementation, then this function returns zero.
|
||||
*
|
||||
* The private key MUST be valid. An off-range private key value is not
|
||||
* necessarily detected, and leads to unpredictable results.
|
||||
*
|
||||
* \param impl the elliptic curve implementation.
|
||||
* \param pk the public key structure to fill (or `NULL`).
|
||||
* \param kbuf the public key point buffer (or `NULL`).
|
||||
* \param sk the source private key.
|
||||
* \return the public key point length (in bytes), or zero.
|
||||
*/
|
||||
size_t br_ec_compute_pub(const br_ec_impl *impl, br_ec_public_key *pk,
|
||||
void *kbuf, const br_ec_private_key *sk);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BR_BEARSSL_HMAC_H__
|
||||
#define BR_BEARSSL_HMAC_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bearssl_hash.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file bearssl_hmac.h
|
||||
*
|
||||
* # HMAC
|
||||
*
|
||||
* HMAC is initialized with a key and an underlying hash function; it
|
||||
* then fills a "key context". That context contains the processed
|
||||
* key.
|
||||
*
|
||||
* With the key context, a HMAC context can be initialized to process
|
||||
* the input bytes and obtain the MAC output. The key context is not
|
||||
* modified during that process, and can be reused.
|
||||
*
|
||||
* IMPORTANT: HMAC shall be used only with functions that have the
|
||||
* following properties:
|
||||
*
|
||||
* - hash output size does not exceed 64 bytes;
|
||||
* - hash internal state size does not exceed 64 bytes;
|
||||
* - internal block length is a power of 2 between 16 and 256 bytes.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief HMAC key context.
|
||||
*
|
||||
* The HMAC key context is initialised with a hash function implementation
|
||||
* and a secret key. Contents are opaque (callers should not access them
|
||||
* directly). The caller is responsible for allocating the context where
|
||||
* appropriate. Context initialisation and usage incurs no dynamic
|
||||
* allocation, so there is no release function.
|
||||
*/
|
||||
typedef struct {
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
const br_hash_class *dig_vtable;
|
||||
unsigned char ksi[64], kso[64];
|
||||
#endif
|
||||
} br_hmac_key_context;
|
||||
|
||||
/**
|
||||
* \brief HMAC key context initialisation.
|
||||
*
|
||||
* Initialise the key context with the provided key, using the hash function
|
||||
* identified by `digest_vtable`. This supports arbitrary key lengths.
|
||||
*
|
||||
* \param kc HMAC key context to initialise.
|
||||
* \param digest_vtable pointer to the hash function implementation vtable.
|
||||
* \param key pointer to the HMAC secret key.
|
||||
* \param key_len HMAC secret key length (in bytes).
|
||||
*/
|
||||
void br_hmac_key_init(br_hmac_key_context *kc,
|
||||
const br_hash_class *digest_vtable, const void *key, size_t key_len);
|
||||
|
||||
/*
|
||||
* \brief Get the underlying hash function.
|
||||
*
|
||||
* This function returns a pointer to the implementation vtable of the
|
||||
* hash function used for this HMAC key context.
|
||||
*
|
||||
* \param kc HMAC key context.
|
||||
* \return the hash function implementation.
|
||||
*/
|
||||
static inline const br_hash_class *br_hmac_key_get_digest(
|
||||
const br_hmac_key_context *kc)
|
||||
{
|
||||
return kc->dig_vtable;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief HMAC computation context.
|
||||
*
|
||||
* The HMAC computation context maintains the state for a single HMAC
|
||||
* computation. It is modified as input bytes are injected. The context
|
||||
* is caller-allocated and has no release function since it does not
|
||||
* dynamically allocate external resources. Its contents are opaque.
|
||||
*/
|
||||
typedef struct {
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
br_hash_compat_context dig;
|
||||
unsigned char kso[64];
|
||||
size_t out_len;
|
||||
#endif
|
||||
} br_hmac_context;
|
||||
|
||||
/**
|
||||
* \brief HMAC computation initialisation.
|
||||
*
|
||||
* Initialise a HMAC context with a key context. The key context is
|
||||
* unmodified. Relevant data from the key context is immediately copied;
|
||||
* the key context can thus be independently reused, modified or released
|
||||
* without impacting this HMAC computation.
|
||||
*
|
||||
* An explicit output length can be specified; the actual output length
|
||||
* will be the minimum of that value and the natural HMAC output length.
|
||||
* If `out_len` is 0, then the natural HMAC output length is selected. The
|
||||
* "natural output length" is the output length of the underlying hash
|
||||
* function.
|
||||
*
|
||||
* \param ctx HMAC context to initialise.
|
||||
* \param kc HMAC key context (already initialised with the key).
|
||||
* \param out_len HMAC output length (0 to select "natural length").
|
||||
*/
|
||||
void br_hmac_init(br_hmac_context *ctx,
|
||||
const br_hmac_key_context *kc, size_t out_len);
|
||||
|
||||
/**
|
||||
* \brief Get the HMAC output size.
|
||||
*
|
||||
* The HMAC output size is the number of bytes that will actually be
|
||||
* produced with `br_hmac_out()` with the provided context. This function
|
||||
* MUST NOT be called on a non-initialised HMAC computation context.
|
||||
* The returned value is the minimum of the HMAC natural length (output
|
||||
* size of the underlying hash function) and the `out_len` parameter which
|
||||
* was used with the last `br_hmac_init()` call on that context (if the
|
||||
* initialisation `out_len` parameter was 0, then this function will
|
||||
* return the HMAC natural length).
|
||||
*
|
||||
* \param ctx the (already initialised) HMAC computation context.
|
||||
* \return the HMAC actual output size.
|
||||
*/
|
||||
static inline size_t
|
||||
br_hmac_size(br_hmac_context *ctx)
|
||||
{
|
||||
return ctx->out_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* \brief Get the underlying hash function.
|
||||
*
|
||||
* This function returns a pointer to the implementation vtable of the
|
||||
* hash function used for this HMAC context.
|
||||
*
|
||||
* \param hc HMAC context.
|
||||
* \return the hash function implementation.
|
||||
*/
|
||||
static inline const br_hash_class *br_hmac_get_digest(
|
||||
const br_hmac_context *hc)
|
||||
{
|
||||
return hc->dig.vtable;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Inject some bytes in HMAC.
|
||||
*
|
||||
* The provided `len` bytes are injected as extra input in the HMAC
|
||||
* computation incarnated by the `ctx` HMAC context. It is acceptable
|
||||
* that `len` is zero, in which case `data` is ignored (and may be
|
||||
* `NULL`) and this function does nothing.
|
||||
*/
|
||||
void br_hmac_update(br_hmac_context *ctx, const void *data, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Compute the HMAC output.
|
||||
*
|
||||
* The destination buffer MUST be large enough to accommodate the result;
|
||||
* its length is at most the "natural length" of HMAC (i.e. the output
|
||||
* length of the underlying hash function). The context is NOT modified;
|
||||
* further bytes may be processed. Thus, "partial HMAC" values can be
|
||||
* efficiently obtained.
|
||||
*
|
||||
* Returned value is the output length (in bytes).
|
||||
*
|
||||
* \param ctx HMAC computation context.
|
||||
* \param out destination buffer for the HMAC output.
|
||||
* \return the produced value length (in bytes).
|
||||
*/
|
||||
size_t br_hmac_out(const br_hmac_context *ctx, void *out);
|
||||
|
||||
/**
|
||||
* \brief Constant-time HMAC computation.
|
||||
*
|
||||
* This function compute the HMAC output in constant time. Some extra
|
||||
* input bytes are processed, then the output is computed. The extra
|
||||
* input consists in the `len` bytes pointed to by `data`. The `len`
|
||||
* parameter must lie between `min_len` and `max_len` (inclusive);
|
||||
* `max_len` bytes are actually read from `data`. Computing time (and
|
||||
* memory access pattern) will not depend upon the data byte contents or
|
||||
* the value of `len`.
|
||||
*
|
||||
* The output is written in the `out` buffer, that MUST be large enough
|
||||
* to receive it.
|
||||
*
|
||||
* The difference `max_len - min_len` MUST be less than 2<sup>30</sup>
|
||||
* (i.e. about one gigabyte).
|
||||
*
|
||||
* This function computes the output properly only if the underlying
|
||||
* hash function uses MD padding (i.e. MD5, SHA-1, SHA-224, SHA-256,
|
||||
* SHA-384 or SHA-512).
|
||||
*
|
||||
* The provided context is NOT modified.
|
||||
*
|
||||
* \param ctx the (already initialised) HMAC computation context.
|
||||
* \param data the extra input bytes.
|
||||
* \param len the extra input length (in bytes).
|
||||
* \param min_len minimum extra input length (in bytes).
|
||||
* \param max_len maximum extra input length (in bytes).
|
||||
* \param out destination buffer for the HMAC output.
|
||||
* \return the produced value length (in bytes).
|
||||
*/
|
||||
size_t br_hmac_outCT(const br_hmac_context *ctx,
|
||||
const void *data, size_t len, size_t min_len, size_t max_len,
|
||||
void *out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BR_BEARSSL_KDF_H__
|
||||
#define BR_BEARSSL_KDF_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bearssl_hash.h"
|
||||
#include "bearssl_hmac.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file bearssl_kdf.h
|
||||
*
|
||||
* # Key Derivation Functions
|
||||
*
|
||||
* KDF are functions that takes a variable length input, and provide a
|
||||
* variable length output, meant to be used to derive subkeys from a
|
||||
* master key.
|
||||
*
|
||||
* ## HKDF
|
||||
*
|
||||
* HKDF is a KDF defined by [RFC 5869](https://tools.ietf.org/html/rfc5869).
|
||||
* It is based on HMAC, itself using an underlying hash function. Any
|
||||
* hash function can be used, as long as it is compatible with the rules
|
||||
* for the HMAC implementation (i.e. output size is 64 bytes or less, hash
|
||||
* internal state size is 64 bytes or less, and the internal block length is
|
||||
* a power of 2 between 16 and 256 bytes). HKDF has two phases:
|
||||
*
|
||||
* - HKDF-Extract: the input data in ingested, along with a "salt" value.
|
||||
*
|
||||
* - HKDF-Expand: the output is produced, from the result of processing
|
||||
* the input and salt, and using an extra non-secret parameter called
|
||||
* "info".
|
||||
*
|
||||
* The "salt" and "info" strings are non-secret and can be empty. Their role
|
||||
* is normally to bind the input and output, respectively, to conventional
|
||||
* identifiers that qualifu them within the used protocol or application.
|
||||
*
|
||||
* The implementation defined in this file uses the following functions:
|
||||
*
|
||||
* - `br_hkdf_init()`: initialize an HKDF context, with a hash function,
|
||||
* and the salt. This starts the HKDF-Extract process.
|
||||
*
|
||||
* - `br_hkdf_inject()`: inject more input bytes. This function may be
|
||||
* called repeatedly if the input data is provided by chunks.
|
||||
*
|
||||
* - `br_hkdf_flip()`: end the HKDF-Extract process, and start the
|
||||
* HKDF-Expand process.
|
||||
*
|
||||
* - `br_hkdf_produce()`: get the next bytes of output. This function
|
||||
* may be called several times to obtain the full output by chunks.
|
||||
* For correct HKDF processing, the same "info" string must be
|
||||
* provided for each call.
|
||||
*
|
||||
* Note that the HKDF total output size (the number of bytes that
|
||||
* HKDF-Expand is willing to produce) is limited: if the hash output size
|
||||
* is _n_ bytes, then the maximum output size is _255*n_.
|
||||
*
|
||||
* ## SHAKE
|
||||
*
|
||||
* SHAKE is defined in
|
||||
* [FIPS 202](https://csrc.nist.gov/publications/detail/fips/202/final)
|
||||
* under two versions: SHAKE128 and SHAKE256, offering an alleged
|
||||
* "security level" of 128 and 256 bits, respectively (SHAKE128 is
|
||||
* about 20 to 25% faster than SHAKE256). SHAKE internally relies on
|
||||
* the Keccak family of sponge functions, not on any externally provided
|
||||
* hash function. Contrary to HKDF, SHAKE does not have a concept of
|
||||
* either a "salt" or an "info" string. The API consists in four
|
||||
* functions:
|
||||
*
|
||||
* - `br_shake_init()`: initialize a SHAKE context for a given
|
||||
* security level.
|
||||
*
|
||||
* - `br_shake_inject()`: inject more input bytes. This function may be
|
||||
* called repeatedly if the input data is provided by chunks.
|
||||
*
|
||||
* - `br_shake_flip()`: end the data injection process, and start the
|
||||
* data production process.
|
||||
*
|
||||
* - `br_shake_produce()`: get the next bytes of output. This function
|
||||
* may be called several times to obtain the full output by chunks.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief HKDF context.
|
||||
*
|
||||
* The HKDF context is initialized with a hash function implementation
|
||||
* and a salt value. Contents are opaque (callers should not access them
|
||||
* directly). The caller is responsible for allocating the context where
|
||||
* appropriate. Context initialisation and usage incurs no dynamic
|
||||
* allocation, so there is no release function.
|
||||
*/
|
||||
typedef struct {
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
union {
|
||||
br_hmac_context hmac_ctx;
|
||||
br_hmac_key_context prk_ctx;
|
||||
} u;
|
||||
unsigned char buf[64];
|
||||
size_t ptr;
|
||||
size_t dig_len;
|
||||
unsigned chunk_num;
|
||||
#endif
|
||||
} br_hkdf_context;
|
||||
|
||||
/**
|
||||
* \brief HKDF context initialization.
|
||||
*
|
||||
* The underlying hash function and salt value are provided. Arbitrary
|
||||
* salt lengths can be used.
|
||||
*
|
||||
* HKDF makes a difference between a salt of length zero, and an
|
||||
* absent salt (the latter being equivalent to a salt consisting of
|
||||
* bytes of value zero, of the same length as the hash function output).
|
||||
* If `salt_len` is zero, then this function assumes that the salt is
|
||||
* present but of length zero. To specify an _absent_ salt, use
|
||||
* `BR_HKDF_NO_SALT` as `salt` parameter (`salt_len` is then ignored).
|
||||
*
|
||||
* \param hc HKDF context to initialise.
|
||||
* \param digest_vtable pointer to the hash function implementation vtable.
|
||||
* \param salt HKDF-Extract salt.
|
||||
* \param salt_len HKDF-Extract salt length (in bytes).
|
||||
*/
|
||||
void br_hkdf_init(br_hkdf_context *hc, const br_hash_class *digest_vtable,
|
||||
const void *salt, size_t salt_len);
|
||||
|
||||
/**
|
||||
* \brief The special "absent salt" value for HKDF.
|
||||
*/
|
||||
#define BR_HKDF_NO_SALT (&br_hkdf_no_salt)
|
||||
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
extern const unsigned char br_hkdf_no_salt;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief HKDF input injection (HKDF-Extract).
|
||||
*
|
||||
* This function injects some more input bytes ("key material") into
|
||||
* HKDF. This function may be called several times, after `br_hkdf_init()`
|
||||
* but before `br_hkdf_flip()`.
|
||||
*
|
||||
* \param hc HKDF context.
|
||||
* \param ikm extra input bytes.
|
||||
* \param ikm_len number of extra input bytes.
|
||||
*/
|
||||
void br_hkdf_inject(br_hkdf_context *hc, const void *ikm, size_t ikm_len);
|
||||
|
||||
/**
|
||||
* \brief HKDF switch to the HKDF-Expand phase.
|
||||
*
|
||||
* This call terminates the HKDF-Extract process (input injection), and
|
||||
* starts the HKDF-Expand process (output production).
|
||||
*
|
||||
* \param hc HKDF context.
|
||||
*/
|
||||
void br_hkdf_flip(br_hkdf_context *hc);
|
||||
|
||||
/**
|
||||
* \brief HKDF output production (HKDF-Expand).
|
||||
*
|
||||
* Produce more output bytes from the current state. This function may be
|
||||
* called several times, but only after `br_hkdf_flip()`.
|
||||
*
|
||||
* Returned value is the number of actually produced bytes. The total
|
||||
* output length is limited to 255 times the output length of the
|
||||
* underlying hash function.
|
||||
*
|
||||
* \param hc HKDF context.
|
||||
* \param info application specific information string.
|
||||
* \param info_len application specific information string length (in bytes).
|
||||
* \param out destination buffer for the HKDF output.
|
||||
* \param out_len the length of the requested output (in bytes).
|
||||
* \return the produced output length (in bytes).
|
||||
*/
|
||||
size_t br_hkdf_produce(br_hkdf_context *hc,
|
||||
const void *info, size_t info_len, void *out, size_t out_len);
|
||||
|
||||
/**
|
||||
* \brief SHAKE context.
|
||||
*
|
||||
* The HKDF context is initialized with a "security level". The internal
|
||||
* notion is called "capacity"; the capacity is twice the security level
|
||||
* (for instance, SHAKE128 has capacity 256).
|
||||
*
|
||||
* The caller is responsible for allocating the context where
|
||||
* appropriate. Context initialisation and usage incurs no dynamic
|
||||
* allocation, so there is no release function.
|
||||
*/
|
||||
typedef struct {
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
unsigned char dbuf[200];
|
||||
size_t dptr;
|
||||
size_t rate;
|
||||
uint64_t A[25];
|
||||
#endif
|
||||
} br_shake_context;
|
||||
|
||||
/**
|
||||
* \brief SHAKE context initialization.
|
||||
*
|
||||
* The context is initialized for the provided "security level".
|
||||
* Internally, this sets the "capacity" to twice the security level;
|
||||
* thus, for SHAKE128, the `security_level` parameter should be 128,
|
||||
* which corresponds to a 256-bit capacity.
|
||||
*
|
||||
* Allowed security levels are all multiples of 32, from 32 to 768,
|
||||
* inclusive. Larger security levels imply lower performance; levels
|
||||
* beyond 256 bits don't make much sense. Standard levels are 128
|
||||
* and 256 bits (for SHAKE128 and SHAKE256, respectively).
|
||||
*
|
||||
* \param sc SHAKE context to initialise.
|
||||
* \param security_level security level (in bits).
|
||||
*/
|
||||
void br_shake_init(br_shake_context *sc, int security_level);
|
||||
|
||||
/**
|
||||
* \brief SHAKE input injection.
|
||||
*
|
||||
* This function injects some more input bytes ("key material") into
|
||||
* SHAKE. This function may be called several times, after `br_shake_init()`
|
||||
* but before `br_shake_flip()`.
|
||||
*
|
||||
* \param sc SHAKE context.
|
||||
* \param data extra input bytes.
|
||||
* \param len number of extra input bytes.
|
||||
*/
|
||||
void br_shake_inject(br_shake_context *sc, const void *data, size_t len);
|
||||
|
||||
/**
|
||||
* \brief SHAKE switch to production phase.
|
||||
*
|
||||
* This call terminates the input injection process, and starts the
|
||||
* output production process.
|
||||
*
|
||||
* \param sc SHAKE context.
|
||||
*/
|
||||
void br_shake_flip(br_shake_context *hc);
|
||||
|
||||
/**
|
||||
* \brief SHAKE output production.
|
||||
*
|
||||
* Produce more output bytes from the current state. This function may be
|
||||
* called several times, but only after `br_shake_flip()`.
|
||||
*
|
||||
* There is no practical limit to the number of bytes that may be produced.
|
||||
*
|
||||
* \param sc SHAKE context.
|
||||
* \param out destination buffer for the SHAKE output.
|
||||
* \param len the length of the requested output (in bytes).
|
||||
*/
|
||||
void br_shake_produce(br_shake_context *sc, void *out, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BR_BEARSSL_PEM_H__
|
||||
#define BR_BEARSSL_PEM_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file bearssl_pem.h
|
||||
*
|
||||
* # PEM Support
|
||||
*
|
||||
* PEM is a traditional encoding layer use to store binary objects (in
|
||||
* particular X.509 certificates, and private keys) in text files. While
|
||||
* the acronym comes from an old, defunct standard ("Privacy Enhanced
|
||||
* Mail"), the format has been reused, with some variations, by many
|
||||
* systems, and is a _de facto_ standard, even though it is not, actually,
|
||||
* specified in all clarity anywhere.
|
||||
*
|
||||
* ## Format Details
|
||||
*
|
||||
* BearSSL contains a generic, streamed PEM decoder, which handles the
|
||||
* following format:
|
||||
*
|
||||
* - The input source (a sequence of bytes) is assumed to be the
|
||||
* encoding of a text file in an ASCII-compatible charset. This
|
||||
* includes ISO-8859-1, Windows-1252, and UTF-8 encodings. Each
|
||||
* line ends on a newline character (U+000A LINE FEED). The
|
||||
* U+000D CARRIAGE RETURN characters are ignored, so the code
|
||||
* accepts both Windows-style and Unix-style line endings.
|
||||
*
|
||||
* - Each object begins with a banner that occurs at the start of
|
||||
* a line; the first banner characters are "`-----BEGIN `" (five
|
||||
* dashes, the word "BEGIN", and a space). The banner matching is
|
||||
* not case-sensitive.
|
||||
*
|
||||
* - The _object name_ consists in the characters that follow the
|
||||
* banner start sequence, up to the end of the line, but without
|
||||
* trailing dashes (in "normal" PEM, there are five trailing
|
||||
* dashes, but this implementation is not picky about these dashes).
|
||||
* The BearSSL decoder normalises the name characters to uppercase
|
||||
* (for ASCII letters only) and accepts names up to 127 characters.
|
||||
*
|
||||
* - The object ends with a banner that again occurs at the start of
|
||||
* a line, and starts with "`-----END `" (again case-insensitive).
|
||||
*
|
||||
* - Between that start and end banner, only Base64 data shall occur.
|
||||
* Base64 converts each sequence of three bytes into four
|
||||
* characters; the four characters are ASCII letters, digits, "`+`"
|
||||
* or "`-`" signs, and one or two "`=`" signs may occur in the last
|
||||
* quartet. Whitespace is ignored (whitespace is any ASCII character
|
||||
* of code 32 or less, so control characters are whitespace) and
|
||||
* lines may have arbitrary length; the only restriction is that the
|
||||
* four characters of a quartet must appear on the same line (no
|
||||
* line break inside a quartet).
|
||||
*
|
||||
* - A single file may contain more than one PEM object. Bytes that
|
||||
* occur between objects are ignored.
|
||||
*
|
||||
*
|
||||
* ## PEM Decoder API
|
||||
*
|
||||
* The PEM decoder offers a state-machine API. The caller allocates a
|
||||
* decoder context, then injects source bytes. Source bytes are pushed
|
||||
* with `br_pem_decoder_push()`. The decoder stops accepting bytes when
|
||||
* it reaches an "event", which is either the start of an object, the
|
||||
* end of an object, or a decoding error within an object.
|
||||
*
|
||||
* The `br_pem_decoder_event()` function is used to obtain the current
|
||||
* event; it also clears it, thus allowing the decoder to accept more
|
||||
* bytes. When a object start event is raised, the decoder context
|
||||
* offers the found object name (normalised to ASCII uppercase).
|
||||
*
|
||||
* When an object is reached, the caller must set an appropriate callback
|
||||
* function, which will receive (by chunks) the decoded object data.
|
||||
*
|
||||
* Since the decoder context makes no dynamic allocation, it requires
|
||||
* no explicit deallocation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief PEM decoder context.
|
||||
*
|
||||
* Contents are opaque (they should not be accessed directly).
|
||||
*/
|
||||
typedef struct {
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
/* CPU for the T0 virtual machine. */
|
||||
struct {
|
||||
uint32_t *dp;
|
||||
uint32_t *rp;
|
||||
const unsigned char *ip;
|
||||
} cpu;
|
||||
uint32_t dp_stack[32];
|
||||
uint32_t rp_stack[32];
|
||||
int err;
|
||||
|
||||
const unsigned char *hbuf;
|
||||
size_t hlen;
|
||||
|
||||
void (*dest)(void *dest_ctx, const void *src, size_t len);
|
||||
void *dest_ctx;
|
||||
|
||||
unsigned char event;
|
||||
char name[128];
|
||||
unsigned char buf[255];
|
||||
size_t ptr;
|
||||
#endif
|
||||
} br_pem_decoder_context;
|
||||
|
||||
/**
|
||||
* \brief Initialise a PEM decoder structure.
|
||||
*
|
||||
* \param ctx decoder context to initialise.
|
||||
*/
|
||||
void br_pem_decoder_init(br_pem_decoder_context *ctx);
|
||||
|
||||
/**
|
||||
* \brief Push some bytes into the decoder.
|
||||
*
|
||||
* Returned value is the number of bytes actually consumed; this may be
|
||||
* less than the number of provided bytes if an event is raised. When an
|
||||
* event is raised, it must be read (with `br_pem_decoder_event()`);
|
||||
* until the event is read, this function will return 0.
|
||||
*
|
||||
* \param ctx decoder context.
|
||||
* \param data new data bytes.
|
||||
* \param len number of new data bytes.
|
||||
* \return the number of bytes actually received (may be less than `len`).
|
||||
*/
|
||||
size_t br_pem_decoder_push(br_pem_decoder_context *ctx,
|
||||
const void *data, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Set the receiver for decoded data.
|
||||
*
|
||||
* When an object is entered, the provided function (with opaque context
|
||||
* pointer) will be called repeatedly with successive chunks of decoded
|
||||
* data for that object. If `dest` is set to 0, then decoded data is
|
||||
* simply ignored. The receiver can be set at any time, but, in practice,
|
||||
* it should be called immediately after receiving a "start of object"
|
||||
* event.
|
||||
*
|
||||
* \param ctx decoder context.
|
||||
* \param dest callback for receiving decoded data.
|
||||
* \param dest_ctx opaque context pointer for the `dest` callback.
|
||||
*/
|
||||
static inline void
|
||||
br_pem_decoder_setdest(br_pem_decoder_context *ctx,
|
||||
void (*dest)(void *dest_ctx, const void *src, size_t len),
|
||||
void *dest_ctx)
|
||||
{
|
||||
ctx->dest = dest;
|
||||
ctx->dest_ctx = dest_ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the last event.
|
||||
*
|
||||
* If an event was raised, then this function returns the event value, and
|
||||
* also clears it, thereby allowing the decoder to proceed. If no event
|
||||
* was raised since the last call to `br_pem_decoder_event()`, then this
|
||||
* function returns 0.
|
||||
*
|
||||
* \param ctx decoder context.
|
||||
* \return the raised event, or 0.
|
||||
*/
|
||||
int br_pem_decoder_event(br_pem_decoder_context *ctx);
|
||||
|
||||
/**
|
||||
* \brief Event: start of object.
|
||||
*
|
||||
* This event is raised when the start of a new object has been detected.
|
||||
* The object name (normalised to uppercase) can be accessed with
|
||||
* `br_pem_decoder_name()`.
|
||||
*/
|
||||
#define BR_PEM_BEGIN_OBJ 1
|
||||
|
||||
/**
|
||||
* \brief Event: end of object.
|
||||
*
|
||||
* This event is raised when the end of the current object is reached
|
||||
* (normally, i.e. with no decoding error).
|
||||
*/
|
||||
#define BR_PEM_END_OBJ 2
|
||||
|
||||
/**
|
||||
* \brief Event: decoding error.
|
||||
*
|
||||
* This event is raised when decoding fails within an object.
|
||||
* This formally closes the current object and brings the decoder back
|
||||
* to the "out of any object" state. The offending line in the source
|
||||
* is consumed.
|
||||
*/
|
||||
#define BR_PEM_ERROR 3
|
||||
|
||||
/**
|
||||
* \brief Get the name of the encountered object.
|
||||
*
|
||||
* The encountered object name is defined only when the "start of object"
|
||||
* event is raised. That name is normalised to uppercase (for ASCII letters
|
||||
* only) and does not include trailing dashes.
|
||||
*
|
||||
* \param ctx decoder context.
|
||||
* \return the current object name.
|
||||
*/
|
||||
static inline const char *
|
||||
br_pem_decoder_name(br_pem_decoder_context *ctx)
|
||||
{
|
||||
return ctx->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Encode an object in PEM.
|
||||
*
|
||||
* This function encodes the provided binary object (`data`, of length `len`
|
||||
* bytes) into PEM. The `banner` text will be included in the header and
|
||||
* footer (e.g. use `"CERTIFICATE"` to get a `"BEGIN CERTIFICATE"` header).
|
||||
*
|
||||
* The length (in characters) of the PEM output is returned; that length
|
||||
* does NOT include the terminating zero, that this function nevertheless
|
||||
* adds. If using the returned value for allocation purposes, the allocated
|
||||
* buffer size MUST be at least one byte larger than the returned size.
|
||||
*
|
||||
* If `dest` is `NULL`, then the encoding does not happen; however, the
|
||||
* length of the encoded object is still computed and returned.
|
||||
*
|
||||
* The `data` pointer may be `NULL` only if `len` is zero (when encoding
|
||||
* an object of length zero, which is not very useful), or when `dest`
|
||||
* is `NULL` (in that case, source data bytes are ignored).
|
||||
*
|
||||
* Some `flags` can be specified to alter the encoding behaviour:
|
||||
*
|
||||
* - If `BR_PEM_LINE64` is set, then line-breaking will occur after
|
||||
* every 64 characters of output, instead of the default of 76.
|
||||
*
|
||||
* - If `BR_PEM_CRLF` is set, then end-of-line sequence will use
|
||||
* CR+LF instead of a single LF.
|
||||
*
|
||||
* The `data` and `dest` buffers may overlap, in which case the source
|
||||
* binary data is destroyed in the process. Note that the PEM-encoded output
|
||||
* is always larger than the source binary.
|
||||
*
|
||||
* \param dest the destination buffer (or `NULL`).
|
||||
* \param data the source buffer (can be `NULL` in some cases).
|
||||
* \param len the source length (in bytes).
|
||||
* \param banner the PEM banner expression.
|
||||
* \param flags the behavioural flags.
|
||||
* \return the PEM object length (in characters), EXCLUDING the final zero.
|
||||
*/
|
||||
size_t br_pem_encode(void *dest, const void *data, size_t len,
|
||||
const char *banner, unsigned flags);
|
||||
|
||||
/**
|
||||
* \brief PEM encoding flag: split lines at 64 characters.
|
||||
*/
|
||||
#define BR_PEM_LINE64 0x0001
|
||||
|
||||
/**
|
||||
* \brief PEM encoding flag: use CR+LF line endings.
|
||||
*/
|
||||
#define BR_PEM_CRLF 0x0002
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BR_BEARSSL_PRF_H__
|
||||
#define BR_BEARSSL_PRF_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file bearssl_prf.h
|
||||
*
|
||||
* # The TLS PRF
|
||||
*
|
||||
* The "PRF" is the pseudorandom function used internally during the
|
||||
* SSL/TLS handshake, notably to expand negotiated shared secrets into
|
||||
* the symmetric encryption keys that will be used to process the
|
||||
* application data.
|
||||
*
|
||||
* TLS 1.0 and 1.1 define a PRF that is based on both MD5 and SHA-1. This
|
||||
* is implemented by the `br_tls10_prf()` function.
|
||||
*
|
||||
* TLS 1.2 redefines the PRF, using an explicit hash function. The
|
||||
* `br_tls12_sha256_prf()` and `br_tls12_sha384_prf()` functions apply that
|
||||
* PRF with, respectively, SHA-256 and SHA-384. Most standard cipher suites
|
||||
* rely on the SHA-256 based PRF, but some use SHA-384.
|
||||
*
|
||||
* The PRF always uses as input three parameters: a "secret" (some
|
||||
* bytes), a "label" (ASCII string), and a "seed" (again some bytes). An
|
||||
* arbitrary output length can be produced. The "seed" is provided as an
|
||||
* arbitrary number of binary chunks, that gets internally concatenated.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Type for a seed chunk.
|
||||
*
|
||||
* Each chunk may have an arbitrary length, and may be empty (no byte at
|
||||
* all). If the chunk length is zero, then the pointer to the chunk data
|
||||
* may be `NULL`.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Pointer to the chunk data.
|
||||
*/
|
||||
const void *data;
|
||||
|
||||
/**
|
||||
* \brief Chunk length (in bytes).
|
||||
*/
|
||||
size_t len;
|
||||
} br_tls_prf_seed_chunk;
|
||||
|
||||
/**
|
||||
* \brief PRF implementation for TLS 1.0 and 1.1.
|
||||
*
|
||||
* This PRF is the one specified by TLS 1.0 and 1.1. It internally uses
|
||||
* MD5 and SHA-1.
|
||||
*
|
||||
* \param dst destination buffer.
|
||||
* \param len output length (in bytes).
|
||||
* \param secret secret value (key) for this computation.
|
||||
* \param secret_len length of "secret" (in bytes).
|
||||
* \param label PRF label (zero-terminated ASCII string).
|
||||
* \param seed_num number of seed chunks.
|
||||
* \param seed seed chnks for this computation (usually non-secret).
|
||||
*/
|
||||
void br_tls10_prf(void *dst, size_t len,
|
||||
const void *secret, size_t secret_len, const char *label,
|
||||
size_t seed_num, const br_tls_prf_seed_chunk *seed);
|
||||
|
||||
/**
|
||||
* \brief PRF implementation for TLS 1.2, with SHA-256.
|
||||
*
|
||||
* This PRF is the one specified by TLS 1.2, when the underlying hash
|
||||
* function is SHA-256.
|
||||
*
|
||||
* \param dst destination buffer.
|
||||
* \param len output length (in bytes).
|
||||
* \param secret secret value (key) for this computation.
|
||||
* \param secret_len length of "secret" (in bytes).
|
||||
* \param label PRF label (zero-terminated ASCII string).
|
||||
* \param seed_num number of seed chunks.
|
||||
* \param seed seed chnks for this computation (usually non-secret).
|
||||
*/
|
||||
void br_tls12_sha256_prf(void *dst, size_t len,
|
||||
const void *secret, size_t secret_len, const char *label,
|
||||
size_t seed_num, const br_tls_prf_seed_chunk *seed);
|
||||
|
||||
/**
|
||||
* \brief PRF implementation for TLS 1.2, with SHA-384.
|
||||
*
|
||||
* This PRF is the one specified by TLS 1.2, when the underlying hash
|
||||
* function is SHA-384.
|
||||
*
|
||||
* \param dst destination buffer.
|
||||
* \param len output length (in bytes).
|
||||
* \param secret secret value (key) for this computation.
|
||||
* \param secret_len length of "secret" (in bytes).
|
||||
* \param label PRF label (zero-terminated ASCII string).
|
||||
* \param seed_num number of seed chunks.
|
||||
* \param seed seed chnks for this computation (usually non-secret).
|
||||
*/
|
||||
void br_tls12_sha384_prf(void *dst, size_t len,
|
||||
const void *secret, size_t secret_len, const char *label,
|
||||
size_t seed_num, const br_tls_prf_seed_chunk *seed);
|
||||
|
||||
/**
|
||||
* brief A convenient type name for a PRF implementation.
|
||||
*
|
||||
* \param dst destination buffer.
|
||||
* \param len output length (in bytes).
|
||||
* \param secret secret value (key) for this computation.
|
||||
* \param secret_len length of "secret" (in bytes).
|
||||
* \param label PRF label (zero-terminated ASCII string).
|
||||
* \param seed_num number of seed chunks.
|
||||
* \param seed seed chnks for this computation (usually non-secret).
|
||||
*/
|
||||
typedef void (*br_tls_prf_impl)(void *dst, size_t len,
|
||||
const void *secret, size_t secret_len, const char *label,
|
||||
size_t seed_num, const br_tls_prf_seed_chunk *seed);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,397 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BR_BEARSSL_RAND_H__
|
||||
#define BR_BEARSSL_RAND_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bearssl_block.h"
|
||||
#include "bearssl_hash.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file bearssl_rand.h
|
||||
*
|
||||
* # Pseudo-Random Generators
|
||||
*
|
||||
* A PRNG is a state-based engine that outputs pseudo-random bytes on
|
||||
* demand. It is initialized with an initial seed, and additional seed
|
||||
* bytes can be added afterwards. Bytes produced depend on the seeds and
|
||||
* also on the exact sequence of calls (including sizes requested for
|
||||
* each call).
|
||||
*
|
||||
*
|
||||
* ## Procedural and OOP API
|
||||
*
|
||||
* For the PRNG of name "`xxx`", two API are provided. The _procedural_
|
||||
* API defined a context structure `br_xxx_context` and three functions:
|
||||
*
|
||||
* - `br_xxx_init()`
|
||||
*
|
||||
* Initialise the context with an initial seed.
|
||||
*
|
||||
* - `br_xxx_generate()`
|
||||
*
|
||||
* Produce some pseudo-random bytes.
|
||||
*
|
||||
* - `br_xxx_update()`
|
||||
*
|
||||
* Inject some additional seed.
|
||||
*
|
||||
* The initialisation function sets the first context field (`vtable`)
|
||||
* to a pointer to the vtable that supports the OOP API. The OOP API
|
||||
* provides access to the same functions through function pointers,
|
||||
* named `init()`, `generate()` and `update()`.
|
||||
*
|
||||
* Note that the context initialisation method may accept additional
|
||||
* parameters, provided as a 'const void *' pointer at API level. These
|
||||
* additional parameters depend on the implemented PRNG.
|
||||
*
|
||||
*
|
||||
* ## HMAC_DRBG
|
||||
*
|
||||
* HMAC_DRBG is defined in [NIST SP 800-90A Revision
|
||||
* 1](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf).
|
||||
* It uses HMAC repeatedly, over some configurable underlying hash
|
||||
* function. In BearSSL, it is implemented under the "`hmac_drbg`" name.
|
||||
* The "extra parameters" pointer for context initialisation should be
|
||||
* set to a pointer to the vtable for the underlying hash function (e.g.
|
||||
* pointer to `br_sha256_vtable` to use HMAC_DRBG with SHA-256).
|
||||
*
|
||||
* According to the NIST standard, each request shall produce up to
|
||||
* 2<sup>19</sup> bits (i.e. 64 kB of data); moreover, the context shall
|
||||
* be reseeded at least once every 2<sup>48</sup> requests. This
|
||||
* implementation does not maintain the reseed counter (the threshold is
|
||||
* too high to be reached in practice) and does not object to producing
|
||||
* more than 64 kB in a single request; thus, the code cannot fail,
|
||||
* which corresponds to the fact that the API has no room for error
|
||||
* codes. However, this implies that requesting more than 64 kB in one
|
||||
* `generate()` request, or making more than 2<sup>48</sup> requests
|
||||
* without reseeding, is formally out of NIST specification. There is
|
||||
* no currently known security penalty for exceeding the NIST limits,
|
||||
* and, in any case, HMAC_DRBG usage in implementing SSL/TLS always
|
||||
* stays much below these thresholds.
|
||||
*
|
||||
*
|
||||
* ## AESCTR_DRBG
|
||||
*
|
||||
* AESCTR_DRBG is a custom PRNG based on AES-128 in CTR mode. This is
|
||||
* meant to be used only in situations where you are desperate for
|
||||
* speed, and have an hardware-optimized AES/CTR implementation. Whether
|
||||
* this will yield perceptible improvements depends on what you use the
|
||||
* pseudorandom bytes for, and how many you want; for instance, RSA key
|
||||
* pair generation uses a substantial amount of randomness, and using
|
||||
* AESCTR_DRBG instead of HMAC_DRBG yields a 15 to 20% increase in key
|
||||
* generation speed on a recent x86 CPU (Intel Core i7-6567U at 3.30 GHz).
|
||||
*
|
||||
* Internally, it uses CTR mode with successive counter values, starting
|
||||
* at zero (counter value expressed over 128 bits, big-endian convention).
|
||||
* The counter is not allowed to reach 32768; thus, every 32768*16 bytes
|
||||
* at most, the `update()` function is run (on an empty seed, if none is
|
||||
* provided). The `update()` function computes the new AES-128 key by
|
||||
* applying a custom hash function to the concatenation of a state-dependent
|
||||
* word (encryption of an all-one block with the current key) and the new
|
||||
* seed. The custom hash function uses Hirose's construction over AES-256;
|
||||
* see the comments in `aesctr_drbg.c` for details.
|
||||
*
|
||||
* This DRBG does not follow an existing standard, and thus should be
|
||||
* considered as inadequate for production use until it has been properly
|
||||
* analysed.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Class type for PRNG implementations.
|
||||
*
|
||||
* A `br_prng_class` instance references the methods implementing a PRNG.
|
||||
* Constant instances of this structure are defined for each implemented
|
||||
* PRNG. Such instances are also called "vtables".
|
||||
*/
|
||||
typedef struct br_prng_class_ br_prng_class;
|
||||
struct br_prng_class_ {
|
||||
/**
|
||||
* \brief Size (in bytes) of the context structure appropriate for
|
||||
* running this PRNG.
|
||||
*/
|
||||
size_t context_size;
|
||||
|
||||
/**
|
||||
* \brief Initialisation method.
|
||||
*
|
||||
* The context to initialise is provided as a pointer to its
|
||||
* first field (the vtable pointer); this function sets that
|
||||
* first field to a pointer to the vtable.
|
||||
*
|
||||
* The extra parameters depend on the implementation; each
|
||||
* implementation defines what kind of extra parameters it
|
||||
* expects (if any).
|
||||
*
|
||||
* Requirements on the initial seed depend on the implemented
|
||||
* PRNG.
|
||||
*
|
||||
* \param ctx PRNG context to initialise.
|
||||
* \param params extra parameters for the PRNG.
|
||||
* \param seed initial seed.
|
||||
* \param seed_len initial seed length (in bytes).
|
||||
*/
|
||||
void (*init)(const br_prng_class **ctx, const void *params,
|
||||
const void *seed, size_t seed_len);
|
||||
|
||||
/**
|
||||
* \brief Random bytes generation.
|
||||
*
|
||||
* This method produces `len` pseudorandom bytes, in the `out`
|
||||
* buffer. The context is updated accordingly.
|
||||
*
|
||||
* \param ctx PRNG context.
|
||||
* \param out output buffer.
|
||||
* \param len number of pseudorandom bytes to produce.
|
||||
*/
|
||||
void (*generate)(const br_prng_class **ctx, void *out, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Inject additional seed bytes.
|
||||
*
|
||||
* The provided seed bytes are added into the PRNG internal
|
||||
* entropy pool.
|
||||
*
|
||||
* \param ctx PRNG context.
|
||||
* \param seed additional seed.
|
||||
* \param seed_len additional seed length (in bytes).
|
||||
*/
|
||||
void (*update)(const br_prng_class **ctx,
|
||||
const void *seed, size_t seed_len);
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Context for HMAC_DRBG.
|
||||
*
|
||||
* The context contents are opaque, except the first field, which
|
||||
* supports OOP.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Pointer to the vtable.
|
||||
*
|
||||
* This field is set with the initialisation method/function.
|
||||
*/
|
||||
const br_prng_class *vtable;
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
unsigned char K[64];
|
||||
unsigned char V[64];
|
||||
const br_hash_class *digest_class;
|
||||
#endif
|
||||
} br_hmac_drbg_context;
|
||||
|
||||
/**
|
||||
* \brief Statically allocated, constant vtable for HMAC_DRBG.
|
||||
*/
|
||||
extern const br_prng_class br_hmac_drbg_vtable;
|
||||
|
||||
/**
|
||||
* \brief HMAC_DRBG initialisation.
|
||||
*
|
||||
* The context to initialise is provided as a pointer to its first field
|
||||
* (the vtable pointer); this function sets that first field to a
|
||||
* pointer to the vtable.
|
||||
*
|
||||
* The `seed` value is what is called, in NIST terminology, the
|
||||
* concatenation of the "seed", "nonce" and "personalization string", in
|
||||
* that order.
|
||||
*
|
||||
* The `digest_class` parameter defines the underlying hash function.
|
||||
* Formally, the NIST standard specifies that the hash function shall
|
||||
* be only SHA-1 or one of the SHA-2 functions. This implementation also
|
||||
* works with any other implemented hash function (such as MD5), but
|
||||
* this is non-standard and therefore not recommended.
|
||||
*
|
||||
* \param ctx HMAC_DRBG context to initialise.
|
||||
* \param digest_class vtable for the underlying hash function.
|
||||
* \param seed initial seed.
|
||||
* \param seed_len initial seed length (in bytes).
|
||||
*/
|
||||
void br_hmac_drbg_init(br_hmac_drbg_context *ctx,
|
||||
const br_hash_class *digest_class, const void *seed, size_t seed_len);
|
||||
|
||||
/**
|
||||
* \brief Random bytes generation with HMAC_DRBG.
|
||||
*
|
||||
* This method produces `len` pseudorandom bytes, in the `out`
|
||||
* buffer. The context is updated accordingly. Formally, requesting
|
||||
* more than 65536 bytes in one request falls out of specification
|
||||
* limits (but it won't fail).
|
||||
*
|
||||
* \param ctx HMAC_DRBG context.
|
||||
* \param out output buffer.
|
||||
* \param len number of pseudorandom bytes to produce.
|
||||
*/
|
||||
void br_hmac_drbg_generate(br_hmac_drbg_context *ctx, void *out, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Inject additional seed bytes in HMAC_DRBG.
|
||||
*
|
||||
* The provided seed bytes are added into the HMAC_DRBG internal
|
||||
* entropy pool. The process does not _replace_ existing entropy,
|
||||
* thus pushing non-random bytes (i.e. bytes which are known to the
|
||||
* attackers) does not degrade the overall quality of generated bytes.
|
||||
*
|
||||
* \param ctx HMAC_DRBG context.
|
||||
* \param seed additional seed.
|
||||
* \param seed_len additional seed length (in bytes).
|
||||
*/
|
||||
void br_hmac_drbg_update(br_hmac_drbg_context *ctx,
|
||||
const void *seed, size_t seed_len);
|
||||
|
||||
/**
|
||||
* \brief Get the hash function implementation used by a given instance of
|
||||
* HMAC_DRBG.
|
||||
*
|
||||
* This calls MUST NOT be performed on a context which was not
|
||||
* previously initialised.
|
||||
*
|
||||
* \param ctx HMAC_DRBG context.
|
||||
* \return the hash function vtable.
|
||||
*/
|
||||
static inline const br_hash_class *
|
||||
br_hmac_drbg_get_hash(const br_hmac_drbg_context *ctx)
|
||||
{
|
||||
return ctx->digest_class;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Type for a provider of entropy seeds.
|
||||
*
|
||||
* A "seeder" is a function that is able to obtain random values from
|
||||
* some source and inject them as entropy seed in a PRNG. A seeder
|
||||
* shall guarantee that the total entropy of the injected seed is large
|
||||
* enough to seed a PRNG for purposes of cryptographic key generation
|
||||
* (i.e. at least 128 bits).
|
||||
*
|
||||
* A seeder may report a failure to obtain adequate entropy. Seeders
|
||||
* shall endeavour to fix themselves transient errors by trying again;
|
||||
* thus, callers may consider reported errors as permanent.
|
||||
*
|
||||
* \param ctx PRNG context to seed.
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
typedef int (*br_prng_seeder)(const br_prng_class **ctx);
|
||||
|
||||
/**
|
||||
* \brief Get a seeder backed by the operating system or hardware.
|
||||
*
|
||||
* Get a seeder that feeds on RNG facilities provided by the current
|
||||
* operating system or hardware. If no such facility is known, then 0
|
||||
* is returned.
|
||||
*
|
||||
* If `name` is not `NULL`, then `*name` is set to a symbolic string
|
||||
* that identifies the seeder implementation. If no seeder is returned
|
||||
* and `name` is not `NULL`, then `*name` is set to a pointer to the
|
||||
* constant string `"none"`.
|
||||
*
|
||||
* \param name receiver for seeder name, or `NULL`.
|
||||
* \return the system seeder, if available, or 0.
|
||||
*/
|
||||
br_prng_seeder br_prng_seeder_system(const char **name);
|
||||
|
||||
/**
|
||||
* \brief Context for AESCTR_DRBG.
|
||||
*
|
||||
* The context contents are opaque, except the first field, which
|
||||
* supports OOP.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Pointer to the vtable.
|
||||
*
|
||||
* This field is set with the initialisation method/function.
|
||||
*/
|
||||
const br_prng_class *vtable;
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
br_aes_gen_ctr_keys sk;
|
||||
uint32_t cc;
|
||||
#endif
|
||||
} br_aesctr_drbg_context;
|
||||
|
||||
/**
|
||||
* \brief Statically allocated, constant vtable for AESCTR_DRBG.
|
||||
*/
|
||||
extern const br_prng_class br_aesctr_drbg_vtable;
|
||||
|
||||
/**
|
||||
* \brief AESCTR_DRBG initialisation.
|
||||
*
|
||||
* The context to initialise is provided as a pointer to its first field
|
||||
* (the vtable pointer); this function sets that first field to a
|
||||
* pointer to the vtable.
|
||||
*
|
||||
* The internal AES key is first set to the all-zero key; then, the
|
||||
* `br_aesctr_drbg_update()` function is called with the provided `seed`.
|
||||
* The call is performed even if the seed length (`seed_len`) is zero.
|
||||
*
|
||||
* The `aesctr` parameter defines the underlying AES/CTR implementation.
|
||||
*
|
||||
* \param ctx AESCTR_DRBG context to initialise.
|
||||
* \param aesctr vtable for the AES/CTR implementation.
|
||||
* \param seed initial seed (can be `NULL` if `seed_len` is zero).
|
||||
* \param seed_len initial seed length (in bytes).
|
||||
*/
|
||||
void br_aesctr_drbg_init(br_aesctr_drbg_context *ctx,
|
||||
const br_block_ctr_class *aesctr, const void *seed, size_t seed_len);
|
||||
|
||||
/**
|
||||
* \brief Random bytes generation with AESCTR_DRBG.
|
||||
*
|
||||
* This method produces `len` pseudorandom bytes, in the `out`
|
||||
* buffer. The context is updated accordingly.
|
||||
*
|
||||
* \param ctx AESCTR_DRBG context.
|
||||
* \param out output buffer.
|
||||
* \param len number of pseudorandom bytes to produce.
|
||||
*/
|
||||
void br_aesctr_drbg_generate(br_aesctr_drbg_context *ctx,
|
||||
void *out, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Inject additional seed bytes in AESCTR_DRBG.
|
||||
*
|
||||
* The provided seed bytes are added into the AESCTR_DRBG internal
|
||||
* entropy pool. The process does not _replace_ existing entropy,
|
||||
* thus pushing non-random bytes (i.e. bytes which are known to the
|
||||
* attackers) does not degrade the overall quality of generated bytes.
|
||||
*
|
||||
* \param ctx AESCTR_DRBG context.
|
||||
* \param seed additional seed.
|
||||
* \param seed_len additional seed length (in bytes).
|
||||
*/
|
||||
void br_aesctr_drbg_update(br_aesctr_drbg_context *ctx,
|
||||
const void *seed, size_t seed_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,486 @@
|
||||
// <bit> -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2018-2024 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file include/bit
|
||||
* This is a Standard C++ Library header.
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_BIT
|
||||
#define _GLIBCXX_BIT 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
|
||||
#include <concepts> // for std::integral
|
||||
#include <type_traits>
|
||||
|
||||
#if _GLIBCXX_HOSTED || __has_include(<ext/numeric_traits.h>)
|
||||
# include <ext/numeric_traits.h>
|
||||
#else
|
||||
# include <limits>
|
||||
/// @cond undocumented
|
||||
namespace __gnu_cxx
|
||||
{
|
||||
template<typename _Tp>
|
||||
struct __int_traits
|
||||
{
|
||||
static constexpr int __digits = std::numeric_limits<_Tp>::digits;
|
||||
static constexpr _Tp __max = std::numeric_limits<_Tp>::max();
|
||||
};
|
||||
}
|
||||
/// @endcond
|
||||
#endif
|
||||
|
||||
#define __glibcxx_want_bit_cast
|
||||
#define __glibcxx_want_byteswap
|
||||
#define __glibcxx_want_bitops
|
||||
#define __glibcxx_want_int_pow2
|
||||
#define __glibcxx_want_endian
|
||||
#include <bits/version.h>
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* @defgroup bit_manip Bit manipulation
|
||||
* @ingroup numerics
|
||||
*
|
||||
* Utilities for examining and manipulating individual bits.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef __cpp_lib_bit_cast // C++ >= 20
|
||||
|
||||
/// Create a value of type `To` from the bits of `from`.
|
||||
/**
|
||||
* @tparam _To A trivially-copyable type.
|
||||
* @param __from A trivially-copyable object of the same size as `_To`.
|
||||
* @return An object of type `_To`.
|
||||
* @since C++20
|
||||
*/
|
||||
template<typename _To, typename _From>
|
||||
[[nodiscard]]
|
||||
constexpr _To
|
||||
bit_cast(const _From& __from) noexcept
|
||||
#ifdef __cpp_concepts
|
||||
requires (sizeof(_To) == sizeof(_From))
|
||||
&& is_trivially_copyable_v<_To> && is_trivially_copyable_v<_From>
|
||||
#endif
|
||||
{
|
||||
return __builtin_bit_cast(_To, __from);
|
||||
}
|
||||
#endif // __cpp_lib_bit_cast
|
||||
|
||||
#ifdef __cpp_lib_byteswap // C++ >= 23
|
||||
|
||||
/// Reverse order of bytes in the object representation of `value`.
|
||||
/**
|
||||
* @tparam _Tp An integral type.
|
||||
* @param __value An object of integer type.
|
||||
* @return An object of the same type, with the bytes reversed.
|
||||
* @since C++23
|
||||
*/
|
||||
template<integral _Tp>
|
||||
[[nodiscard]]
|
||||
constexpr _Tp
|
||||
byteswap(_Tp __value) noexcept
|
||||
{
|
||||
if constexpr (sizeof(_Tp) == 1)
|
||||
return __value;
|
||||
#if __cpp_if_consteval >= 202106L && __CHAR_BIT__ == 8
|
||||
if !consteval
|
||||
{
|
||||
if constexpr (sizeof(_Tp) == 2)
|
||||
return __builtin_bswap16(__value);
|
||||
if constexpr (sizeof(_Tp) == 4)
|
||||
return __builtin_bswap32(__value);
|
||||
if constexpr (sizeof(_Tp) == 8)
|
||||
return __builtin_bswap64(__value);
|
||||
if constexpr (sizeof(_Tp) == 16)
|
||||
#if __has_builtin(__builtin_bswap128)
|
||||
return __builtin_bswap128(__value);
|
||||
#else
|
||||
return (__builtin_bswap64(__value >> 64)
|
||||
| (static_cast<_Tp>(__builtin_bswap64(__value)) << 64));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
// Fallback implementation that handles even __int24 etc.
|
||||
using _Up = typename __make_unsigned<__remove_cv_t<_Tp>>::__type;
|
||||
size_t __diff = __CHAR_BIT__ * (sizeof(_Tp) - 1);
|
||||
_Up __mask1 = static_cast<unsigned char>(~0);
|
||||
_Up __mask2 = __mask1 << __diff;
|
||||
_Up __val = __value;
|
||||
for (size_t __i = 0; __i < sizeof(_Tp) / 2; ++__i)
|
||||
{
|
||||
_Up __byte1 = __val & __mask1;
|
||||
_Up __byte2 = __val & __mask2;
|
||||
__val = (__val ^ __byte1 ^ __byte2
|
||||
^ (__byte1 << __diff) ^ (__byte2 >> __diff));
|
||||
__mask1 <<= __CHAR_BIT__;
|
||||
__mask2 >>= __CHAR_BIT__;
|
||||
__diff -= 2 * __CHAR_BIT__;
|
||||
}
|
||||
return __val;
|
||||
}
|
||||
#endif // __cpp_lib_byteswap
|
||||
|
||||
/// @cond undocumented
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr _Tp
|
||||
__rotl(_Tp __x, int __s) noexcept
|
||||
{
|
||||
constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits;
|
||||
if _GLIBCXX17_CONSTEXPR ((_Nd & (_Nd - 1)) == 0)
|
||||
{
|
||||
// Variant for power of two _Nd which the compiler can
|
||||
// easily pattern match.
|
||||
constexpr unsigned __uNd = _Nd;
|
||||
const unsigned __r = __s;
|
||||
return (__x << (__r % __uNd)) | (__x >> ((-__r) % __uNd));
|
||||
}
|
||||
const int __r = __s % _Nd;
|
||||
if (__r == 0)
|
||||
return __x;
|
||||
else if (__r > 0)
|
||||
return (__x << __r) | (__x >> ((_Nd - __r) % _Nd));
|
||||
else
|
||||
return (__x >> -__r) | (__x << ((_Nd + __r) % _Nd)); // rotr(x, -r)
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr _Tp
|
||||
__rotr(_Tp __x, int __s) noexcept
|
||||
{
|
||||
constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits;
|
||||
if _GLIBCXX17_CONSTEXPR ((_Nd & (_Nd - 1)) == 0)
|
||||
{
|
||||
// Variant for power of two _Nd which the compiler can
|
||||
// easily pattern match.
|
||||
constexpr unsigned __uNd = _Nd;
|
||||
const unsigned __r = __s;
|
||||
return (__x >> (__r % __uNd)) | (__x << ((-__r) % __uNd));
|
||||
}
|
||||
const int __r = __s % _Nd;
|
||||
if (__r == 0)
|
||||
return __x;
|
||||
else if (__r > 0)
|
||||
return (__x >> __r) | (__x << ((_Nd - __r) % _Nd));
|
||||
else
|
||||
return (__x << -__r) | (__x >> ((_Nd + __r) % _Nd)); // rotl(x, -r)
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr int
|
||||
__countl_zero(_Tp __x) noexcept
|
||||
{
|
||||
using __gnu_cxx::__int_traits;
|
||||
constexpr auto _Nd = __int_traits<_Tp>::__digits;
|
||||
|
||||
if (__x == 0)
|
||||
return _Nd;
|
||||
|
||||
constexpr auto _Nd_ull = __int_traits<unsigned long long>::__digits;
|
||||
constexpr auto _Nd_ul = __int_traits<unsigned long>::__digits;
|
||||
constexpr auto _Nd_u = __int_traits<unsigned>::__digits;
|
||||
|
||||
if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u)
|
||||
{
|
||||
constexpr int __diff = _Nd_u - _Nd;
|
||||
return __builtin_clz(__x) - __diff;
|
||||
}
|
||||
else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul)
|
||||
{
|
||||
constexpr int __diff = _Nd_ul - _Nd;
|
||||
return __builtin_clzl(__x) - __diff;
|
||||
}
|
||||
else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull)
|
||||
{
|
||||
constexpr int __diff = _Nd_ull - _Nd;
|
||||
return __builtin_clzll(__x) - __diff;
|
||||
}
|
||||
else // (_Nd > _Nd_ull)
|
||||
{
|
||||
static_assert(_Nd <= (2 * _Nd_ull),
|
||||
"Maximum supported integer size is 128-bit");
|
||||
|
||||
unsigned long long __high = __x >> _Nd_ull;
|
||||
if (__high != 0)
|
||||
{
|
||||
constexpr int __diff = (2 * _Nd_ull) - _Nd;
|
||||
return __builtin_clzll(__high) - __diff;
|
||||
}
|
||||
constexpr auto __max_ull = __int_traits<unsigned long long>::__max;
|
||||
unsigned long long __low = __x & __max_ull;
|
||||
return (_Nd - _Nd_ull) + __builtin_clzll(__low);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr int
|
||||
__countl_one(_Tp __x) noexcept
|
||||
{
|
||||
return std::__countl_zero<_Tp>((_Tp)~__x);
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr int
|
||||
__countr_zero(_Tp __x) noexcept
|
||||
{
|
||||
using __gnu_cxx::__int_traits;
|
||||
constexpr auto _Nd = __int_traits<_Tp>::__digits;
|
||||
|
||||
if (__x == 0)
|
||||
return _Nd;
|
||||
|
||||
constexpr auto _Nd_ull = __int_traits<unsigned long long>::__digits;
|
||||
constexpr auto _Nd_ul = __int_traits<unsigned long>::__digits;
|
||||
constexpr auto _Nd_u = __int_traits<unsigned>::__digits;
|
||||
|
||||
if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u)
|
||||
return __builtin_ctz(__x);
|
||||
else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul)
|
||||
return __builtin_ctzl(__x);
|
||||
else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull)
|
||||
return __builtin_ctzll(__x);
|
||||
else // (_Nd > _Nd_ull)
|
||||
{
|
||||
static_assert(_Nd <= (2 * _Nd_ull),
|
||||
"Maximum supported integer size is 128-bit");
|
||||
|
||||
constexpr auto __max_ull = __int_traits<unsigned long long>::__max;
|
||||
unsigned long long __low = __x & __max_ull;
|
||||
if (__low != 0)
|
||||
return __builtin_ctzll(__low);
|
||||
unsigned long long __high = __x >> _Nd_ull;
|
||||
return __builtin_ctzll(__high) + _Nd_ull;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr int
|
||||
__countr_one(_Tp __x) noexcept
|
||||
{
|
||||
return std::__countr_zero((_Tp)~__x);
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr int
|
||||
__popcount(_Tp __x) noexcept
|
||||
{
|
||||
using __gnu_cxx::__int_traits;
|
||||
constexpr auto _Nd = __int_traits<_Tp>::__digits;
|
||||
|
||||
constexpr auto _Nd_ull = __int_traits<unsigned long long>::__digits;
|
||||
constexpr auto _Nd_ul = __int_traits<unsigned long>::__digits;
|
||||
constexpr auto _Nd_u = __int_traits<unsigned>::__digits;
|
||||
|
||||
if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u)
|
||||
return __builtin_popcount(__x);
|
||||
else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul)
|
||||
return __builtin_popcountl(__x);
|
||||
else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull)
|
||||
return __builtin_popcountll(__x);
|
||||
else // (_Nd > _Nd_ull)
|
||||
{
|
||||
static_assert(_Nd <= (2 * _Nd_ull),
|
||||
"Maximum supported integer size is 128-bit");
|
||||
|
||||
constexpr auto __max_ull = __int_traits<unsigned long long>::__max;
|
||||
unsigned long long __low = __x & __max_ull;
|
||||
unsigned long long __high = __x >> _Nd_ull;
|
||||
return __builtin_popcountll(__low) + __builtin_popcountll(__high);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr bool
|
||||
__has_single_bit(_Tp __x) noexcept
|
||||
{ return std::__popcount(__x) == 1; }
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr _Tp
|
||||
__bit_ceil(_Tp __x) noexcept
|
||||
{
|
||||
using __gnu_cxx::__int_traits;
|
||||
constexpr auto _Nd = __int_traits<_Tp>::__digits;
|
||||
if (__x == 0 || __x == 1)
|
||||
return 1;
|
||||
auto __shift_exponent = _Nd - std::__countl_zero((_Tp)(__x - 1u));
|
||||
// If the shift exponent equals _Nd then the correct result is not
|
||||
// representable as a value of _Tp, and so the result is undefined.
|
||||
// Want that undefined behaviour to be detected in constant expressions,
|
||||
// by UBSan, and by debug assertions.
|
||||
if (!std::__is_constant_evaluated())
|
||||
{
|
||||
__glibcxx_assert( __shift_exponent != __int_traits<_Tp>::__digits );
|
||||
}
|
||||
|
||||
using __promoted_type = decltype(__x << 1);
|
||||
if _GLIBCXX17_CONSTEXPR (!is_same<__promoted_type, _Tp>::value)
|
||||
{
|
||||
// If __x undergoes integral promotion then shifting by _Nd is
|
||||
// not undefined. In order to make the shift undefined, so that
|
||||
// it is diagnosed in constant expressions and by UBsan, we also
|
||||
// need to "promote" the shift exponent to be too large for the
|
||||
// promoted type.
|
||||
const int __extra_exp = sizeof(__promoted_type) / sizeof(_Tp) / 2;
|
||||
__shift_exponent |= (__shift_exponent & _Nd) << __extra_exp;
|
||||
}
|
||||
return (_Tp)1u << __shift_exponent;
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr _Tp
|
||||
__bit_floor(_Tp __x) noexcept
|
||||
{
|
||||
constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits;
|
||||
if (__x == 0)
|
||||
return 0;
|
||||
return (_Tp)1u << (_Nd - std::__countl_zero((_Tp)(__x >> 1)));
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr int
|
||||
__bit_width(_Tp __x) noexcept
|
||||
{
|
||||
constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits;
|
||||
return _Nd - std::__countl_zero(__x);
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
|
||||
#ifdef __cpp_lib_bitops // C++ >= 20
|
||||
|
||||
/// @cond undocumented
|
||||
template<typename _Tp>
|
||||
concept __unsigned_integer = __is_unsigned_integer<_Tp>::value;
|
||||
/// @endcond
|
||||
|
||||
// [bit.rot], rotating
|
||||
|
||||
/// Rotate `x` to the left by `s` bits.
|
||||
template<__unsigned_integer _Tp>
|
||||
[[nodiscard]] constexpr _Tp
|
||||
rotl(_Tp __x, int __s) noexcept
|
||||
{ return std::__rotl(__x, __s); }
|
||||
|
||||
/// Rotate `x` to the right by `s` bits.
|
||||
template<__unsigned_integer _Tp>
|
||||
[[nodiscard]] constexpr _Tp
|
||||
rotr(_Tp __x, int __s) noexcept
|
||||
{ return std::__rotr(__x, __s); }
|
||||
|
||||
// [bit.count], counting
|
||||
|
||||
/// The number of contiguous zero bits, starting from the highest bit.
|
||||
template<__unsigned_integer _Tp>
|
||||
constexpr int
|
||||
countl_zero(_Tp __x) noexcept
|
||||
{ return std::__countl_zero(__x); }
|
||||
|
||||
/// The number of contiguous one bits, starting from the highest bit.
|
||||
template<__unsigned_integer _Tp>
|
||||
constexpr int
|
||||
countl_one(_Tp __x) noexcept
|
||||
{ return std::__countl_one(__x); }
|
||||
|
||||
/// The number of contiguous zero bits, starting from the lowest bit.
|
||||
template<__unsigned_integer _Tp>
|
||||
constexpr int
|
||||
countr_zero(_Tp __x) noexcept
|
||||
{ return std::__countr_zero(__x); }
|
||||
|
||||
/// The number of contiguous one bits, starting from the lowest bit.
|
||||
template<__unsigned_integer _Tp>
|
||||
constexpr int
|
||||
countr_one(_Tp __x) noexcept
|
||||
{ return std::__countr_one(__x); }
|
||||
|
||||
/// The number of bits set in `x`.
|
||||
template<__unsigned_integer _Tp>
|
||||
constexpr int
|
||||
popcount(_Tp __x) noexcept
|
||||
{ return std::__popcount(__x); }
|
||||
#endif // __cpp_lib_bitops
|
||||
|
||||
#ifdef __cpp_lib_int_pow2 // C++ >= 20
|
||||
// [bit.pow.two], integral powers of 2
|
||||
|
||||
/// True if `x` is a power of two, false otherwise.
|
||||
template<__unsigned_integer _Tp>
|
||||
constexpr bool
|
||||
has_single_bit(_Tp __x) noexcept
|
||||
{ return std::__has_single_bit(__x); }
|
||||
|
||||
/// The smallest power-of-two not less than `x`.
|
||||
template<__unsigned_integer _Tp>
|
||||
constexpr _Tp
|
||||
bit_ceil(_Tp __x) noexcept
|
||||
{ return std::__bit_ceil(__x); }
|
||||
|
||||
/// The largest power-of-two not greater than `x`.
|
||||
template<__unsigned_integer _Tp>
|
||||
constexpr _Tp
|
||||
bit_floor(_Tp __x) noexcept
|
||||
{ return std::__bit_floor(__x); }
|
||||
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 3656. Inconsistent bit operations returning a count
|
||||
/// The smallest integer greater than the base-2 logarithm of `x`.
|
||||
template<__unsigned_integer _Tp>
|
||||
constexpr int
|
||||
bit_width(_Tp __x) noexcept
|
||||
{ return std::__bit_width(__x); }
|
||||
#endif // defined (__cpp_lib_int_pow2)
|
||||
|
||||
#ifdef __cpp_lib_endian // C++ >= 20
|
||||
|
||||
/// Byte order constants
|
||||
/**
|
||||
* The platform endianness can be checked by comparing `std::endian::native`
|
||||
* to one of `std::endian::big` or `std::endian::little`.
|
||||
*
|
||||
* @since C++20
|
||||
*/
|
||||
enum class endian
|
||||
{
|
||||
little = __ORDER_LITTLE_ENDIAN__,
|
||||
big = __ORDER_BIG_ENDIAN__,
|
||||
native = __BYTE_ORDER__
|
||||
};
|
||||
#endif // __cpp_lib_endian
|
||||
|
||||
/// @}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
||||
#endif // C++14
|
||||
#endif // _GLIBCXX_BIT
|
||||
@@ -0,0 +1,970 @@
|
||||
// <algorithm> Forward declarations -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007-2024 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/algorithmfwd.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{algorithm}
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_ALGORITHMFWD_H
|
||||
#define _GLIBCXX_ALGORITHMFWD_H 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include <bits/c++config.h>
|
||||
#include <bits/stl_pair.h>
|
||||
#include <bits/stl_iterator_base_types.h>
|
||||
#if __cplusplus >= 201103L
|
||||
#include <initializer_list>
|
||||
#endif
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/*
|
||||
adjacent_find
|
||||
all_of (C++11)
|
||||
any_of (C++11)
|
||||
binary_search
|
||||
clamp (C++17)
|
||||
copy
|
||||
copy_backward
|
||||
copy_if (C++11)
|
||||
copy_n (C++11)
|
||||
count
|
||||
count_if
|
||||
equal
|
||||
equal_range
|
||||
fill
|
||||
fill_n
|
||||
find
|
||||
find_end
|
||||
find_first_of
|
||||
find_if
|
||||
find_if_not (C++11)
|
||||
for_each
|
||||
generate
|
||||
generate_n
|
||||
includes
|
||||
inplace_merge
|
||||
is_heap (C++11)
|
||||
is_heap_until (C++11)
|
||||
is_partitioned (C++11)
|
||||
is_sorted (C++11)
|
||||
is_sorted_until (C++11)
|
||||
iter_swap
|
||||
lexicographical_compare
|
||||
lower_bound
|
||||
make_heap
|
||||
max
|
||||
max_element
|
||||
merge
|
||||
min
|
||||
min_element
|
||||
minmax (C++11)
|
||||
minmax_element (C++11)
|
||||
mismatch
|
||||
next_permutation
|
||||
none_of (C++11)
|
||||
nth_element
|
||||
partial_sort
|
||||
partial_sort_copy
|
||||
partition
|
||||
partition_copy (C++11)
|
||||
partition_point (C++11)
|
||||
pop_heap
|
||||
prev_permutation
|
||||
push_heap
|
||||
random_shuffle
|
||||
remove
|
||||
remove_copy
|
||||
remove_copy_if
|
||||
remove_if
|
||||
replace
|
||||
replace_copy
|
||||
replace_copy_if
|
||||
replace_if
|
||||
reverse
|
||||
reverse_copy
|
||||
rotate
|
||||
rotate_copy
|
||||
search
|
||||
search_n
|
||||
set_difference
|
||||
set_intersection
|
||||
set_symmetric_difference
|
||||
set_union
|
||||
shuffle (C++11)
|
||||
sort
|
||||
sort_heap
|
||||
stable_partition
|
||||
stable_sort
|
||||
swap
|
||||
swap_ranges
|
||||
transform
|
||||
unique
|
||||
unique_copy
|
||||
upper_bound
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup algorithms Algorithms
|
||||
*
|
||||
* Components for performing algorithmic operations. Includes
|
||||
* non-modifying sequence, modifying (mutating) sequence, sorting,
|
||||
* searching, merge, partition, heap, set, minima, maxima, and
|
||||
* permutation operations.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup mutating_algorithms Mutating
|
||||
* @ingroup algorithms
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup non_mutating_algorithms Non-Mutating
|
||||
* @ingroup algorithms
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup sorting_algorithms Sorting
|
||||
* @ingroup algorithms
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup set_algorithms Set Operations
|
||||
* @ingroup sorting_algorithms
|
||||
*
|
||||
* These algorithms are common set operations performed on sequences
|
||||
* that are already sorted. The number of comparisons will be
|
||||
* linear.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup binary_search_algorithms Binary Search
|
||||
* @ingroup sorting_algorithms
|
||||
*
|
||||
* These algorithms are variations of a classic binary search, and
|
||||
* all assume that the sequence being searched is already sorted.
|
||||
*
|
||||
* The number of comparisons will be logarithmic (and as few as
|
||||
* possible). The number of steps through the sequence will be
|
||||
* logarithmic for random-access iterators (e.g., pointers), and
|
||||
* linear otherwise.
|
||||
*
|
||||
* The LWG has passed Defect Report 270, which notes: <em>The
|
||||
* proposed resolution reinterprets binary search. Instead of
|
||||
* thinking about searching for a value in a sorted range, we view
|
||||
* that as an important special case of a more general algorithm:
|
||||
* searching for the partition point in a partitioned range. We
|
||||
* also add a guarantee that the old wording did not: we ensure that
|
||||
* the upper bound is no earlier than the lower bound, that the pair
|
||||
* returned by equal_range is a valid range, and that the first part
|
||||
* of that pair is the lower bound.</em>
|
||||
*
|
||||
* The actual effect of the first sentence is that a comparison
|
||||
* functor passed by the user doesn't necessarily need to induce a
|
||||
* strict weak ordering relation. Rather, it partitions the range.
|
||||
*/
|
||||
|
||||
// adjacent_find
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _IIter, typename _Predicate>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
bool
|
||||
all_of(_IIter, _IIter, _Predicate);
|
||||
|
||||
template<typename _IIter, typename _Predicate>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
bool
|
||||
any_of(_IIter, _IIter, _Predicate);
|
||||
#endif
|
||||
|
||||
template<typename _FIter, typename _Tp>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
bool
|
||||
binary_search(_FIter, _FIter, const _Tp&);
|
||||
|
||||
template<typename _FIter, typename _Tp, typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
bool
|
||||
binary_search(_FIter, _FIter, const _Tp&, _Compare);
|
||||
|
||||
#if __cplusplus > 201402L
|
||||
template<typename _Tp>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
const _Tp&
|
||||
clamp(const _Tp&, const _Tp&, const _Tp&);
|
||||
|
||||
template<typename _Tp, typename _Compare>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
const _Tp&
|
||||
clamp(const _Tp&, const _Tp&, const _Tp&, _Compare);
|
||||
#endif
|
||||
|
||||
template<typename _IIter, typename _OIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
copy(_IIter, _IIter, _OIter);
|
||||
|
||||
template<typename _BIter1, typename _BIter2>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_BIter2
|
||||
copy_backward(_BIter1, _BIter1, _BIter2);
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _IIter, typename _OIter, typename _Predicate>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
copy_if(_IIter, _IIter, _OIter, _Predicate);
|
||||
|
||||
template<typename _IIter, typename _Size, typename _OIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
copy_n(_IIter, _Size, _OIter);
|
||||
#endif
|
||||
|
||||
// count
|
||||
// count_if
|
||||
|
||||
template<typename _FIter, typename _Tp>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
pair<_FIter, _FIter>
|
||||
equal_range(_FIter, _FIter, const _Tp&);
|
||||
|
||||
template<typename _FIter, typename _Tp, typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
pair<_FIter, _FIter>
|
||||
equal_range(_FIter, _FIter, const _Tp&, _Compare);
|
||||
|
||||
template<typename _FIter, typename _Tp>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
fill(_FIter, _FIter, const _Tp&);
|
||||
|
||||
template<typename _OIter, typename _Size, typename _Tp>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
fill_n(_OIter, _Size, const _Tp&);
|
||||
|
||||
// find
|
||||
|
||||
template<typename _FIter1, typename _FIter2>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_FIter1
|
||||
find_end(_FIter1, _FIter1, _FIter2, _FIter2);
|
||||
|
||||
template<typename _FIter1, typename _FIter2, typename _BinaryPredicate>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_FIter1
|
||||
find_end(_FIter1, _FIter1, _FIter2, _FIter2, _BinaryPredicate);
|
||||
|
||||
// find_first_of
|
||||
// find_if
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _IIter, typename _Predicate>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_IIter
|
||||
find_if_not(_IIter, _IIter, _Predicate);
|
||||
#endif
|
||||
|
||||
// for_each
|
||||
// generate
|
||||
// generate_n
|
||||
|
||||
template<typename _IIter1, typename _IIter2>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
bool
|
||||
includes(_IIter1, _IIter1, _IIter2, _IIter2);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
bool
|
||||
includes(_IIter1, _IIter1, _IIter2, _IIter2, _Compare);
|
||||
|
||||
template<typename _BIter>
|
||||
void
|
||||
inplace_merge(_BIter, _BIter, _BIter);
|
||||
|
||||
template<typename _BIter, typename _Compare>
|
||||
void
|
||||
inplace_merge(_BIter, _BIter, _BIter, _Compare);
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _RAIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
bool
|
||||
is_heap(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
bool
|
||||
is_heap(_RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _RAIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_RAIter
|
||||
is_heap_until(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_RAIter
|
||||
is_heap_until(_RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _IIter, typename _Predicate>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
bool
|
||||
is_partitioned(_IIter, _IIter, _Predicate);
|
||||
|
||||
template<typename _FIter1, typename _FIter2>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
bool
|
||||
is_permutation(_FIter1, _FIter1, _FIter2);
|
||||
|
||||
template<typename _FIter1, typename _FIter2,
|
||||
typename _BinaryPredicate>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
bool
|
||||
is_permutation(_FIter1, _FIter1, _FIter2, _BinaryPredicate);
|
||||
|
||||
template<typename _FIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
bool
|
||||
is_sorted(_FIter, _FIter);
|
||||
|
||||
template<typename _FIter, typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
bool
|
||||
is_sorted(_FIter, _FIter, _Compare);
|
||||
|
||||
template<typename _FIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_FIter
|
||||
is_sorted_until(_FIter, _FIter);
|
||||
|
||||
template<typename _FIter, typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_FIter
|
||||
is_sorted_until(_FIter, _FIter, _Compare);
|
||||
#endif
|
||||
|
||||
template<typename _FIter1, typename _FIter2>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
iter_swap(_FIter1, _FIter2);
|
||||
|
||||
template<typename _FIter, typename _Tp>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_FIter
|
||||
lower_bound(_FIter, _FIter, const _Tp&);
|
||||
|
||||
template<typename _FIter, typename _Tp, typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_FIter
|
||||
lower_bound(_FIter, _FIter, const _Tp&, _Compare);
|
||||
|
||||
template<typename _RAIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
make_heap(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
make_heap(_RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _Tp>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
const _Tp&
|
||||
max(const _Tp&, const _Tp&);
|
||||
|
||||
template<typename _Tp, typename _Compare>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
const _Tp&
|
||||
max(const _Tp&, const _Tp&, _Compare);
|
||||
|
||||
// max_element
|
||||
// merge
|
||||
|
||||
template<typename _Tp>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
const _Tp&
|
||||
min(const _Tp&, const _Tp&);
|
||||
|
||||
template<typename _Tp, typename _Compare>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
const _Tp&
|
||||
min(const _Tp&, const _Tp&, _Compare);
|
||||
|
||||
// min_element
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _Tp>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
pair<const _Tp&, const _Tp&>
|
||||
minmax(const _Tp&, const _Tp&);
|
||||
|
||||
template<typename _Tp, typename _Compare>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
pair<const _Tp&, const _Tp&>
|
||||
minmax(const _Tp&, const _Tp&, _Compare);
|
||||
|
||||
template<typename _FIter>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
pair<_FIter, _FIter>
|
||||
minmax_element(_FIter, _FIter);
|
||||
|
||||
template<typename _FIter, typename _Compare>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
pair<_FIter, _FIter>
|
||||
minmax_element(_FIter, _FIter, _Compare);
|
||||
|
||||
template<typename _Tp>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
_Tp
|
||||
min(initializer_list<_Tp>);
|
||||
|
||||
template<typename _Tp, typename _Compare>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
_Tp
|
||||
min(initializer_list<_Tp>, _Compare);
|
||||
|
||||
template<typename _Tp>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
_Tp
|
||||
max(initializer_list<_Tp>);
|
||||
|
||||
template<typename _Tp, typename _Compare>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
_Tp
|
||||
max(initializer_list<_Tp>, _Compare);
|
||||
|
||||
template<typename _Tp>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
pair<_Tp, _Tp>
|
||||
minmax(initializer_list<_Tp>);
|
||||
|
||||
template<typename _Tp, typename _Compare>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
pair<_Tp, _Tp>
|
||||
minmax(initializer_list<_Tp>, _Compare);
|
||||
#endif
|
||||
|
||||
// mismatch
|
||||
|
||||
template<typename _BIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
bool
|
||||
next_permutation(_BIter, _BIter);
|
||||
|
||||
template<typename _BIter, typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
bool
|
||||
next_permutation(_BIter, _BIter, _Compare);
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _IIter, typename _Predicate>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
bool
|
||||
none_of(_IIter, _IIter, _Predicate);
|
||||
#endif
|
||||
|
||||
// nth_element
|
||||
// partial_sort
|
||||
|
||||
template<typename _IIter, typename _RAIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_RAIter
|
||||
partial_sort_copy(_IIter, _IIter, _RAIter, _RAIter);
|
||||
|
||||
template<typename _IIter, typename _RAIter, typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_RAIter
|
||||
partial_sort_copy(_IIter, _IIter, _RAIter, _RAIter, _Compare);
|
||||
|
||||
// partition
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _IIter, typename _OIter1,
|
||||
typename _OIter2, typename _Predicate>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
pair<_OIter1, _OIter2>
|
||||
partition_copy(_IIter, _IIter, _OIter1, _OIter2, _Predicate);
|
||||
|
||||
template<typename _FIter, typename _Predicate>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_FIter
|
||||
partition_point(_FIter, _FIter, _Predicate);
|
||||
#endif
|
||||
|
||||
template<typename _RAIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
pop_heap(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
pop_heap(_RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _BIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
bool
|
||||
prev_permutation(_BIter, _BIter);
|
||||
|
||||
template<typename _BIter, typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
bool
|
||||
prev_permutation(_BIter, _BIter, _Compare);
|
||||
|
||||
template<typename _RAIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
push_heap(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
push_heap(_RAIter, _RAIter, _Compare);
|
||||
|
||||
// random_shuffle
|
||||
|
||||
template<typename _FIter, typename _Tp>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_FIter
|
||||
remove(_FIter, _FIter, const _Tp&);
|
||||
|
||||
template<typename _FIter, typename _Predicate>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_FIter
|
||||
remove_if(_FIter, _FIter, _Predicate);
|
||||
|
||||
template<typename _IIter, typename _OIter, typename _Tp>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
remove_copy(_IIter, _IIter, _OIter, const _Tp&);
|
||||
|
||||
template<typename _IIter, typename _OIter, typename _Predicate>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
remove_copy_if(_IIter, _IIter, _OIter, _Predicate);
|
||||
|
||||
// replace
|
||||
|
||||
template<typename _IIter, typename _OIter, typename _Tp>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
replace_copy(_IIter, _IIter, _OIter, const _Tp&, const _Tp&);
|
||||
|
||||
template<typename _Iter, typename _OIter, typename _Predicate, typename _Tp>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
replace_copy_if(_Iter, _Iter, _OIter, _Predicate, const _Tp&);
|
||||
|
||||
// replace_if
|
||||
|
||||
template<typename _BIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
reverse(_BIter, _BIter);
|
||||
|
||||
template<typename _BIter, typename _OIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
reverse_copy(_BIter, _BIter, _OIter);
|
||||
|
||||
_GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
|
||||
|
||||
template<typename _FIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_FIter
|
||||
rotate(_FIter, _FIter, _FIter);
|
||||
|
||||
_GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
|
||||
|
||||
template<typename _FIter, typename _OIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
rotate_copy(_FIter, _FIter, _FIter, _OIter);
|
||||
|
||||
// search
|
||||
// search_n
|
||||
// set_difference
|
||||
// set_intersection
|
||||
// set_symmetric_difference
|
||||
// set_union
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _RAIter, typename _UGenerator>
|
||||
void
|
||||
shuffle(_RAIter, _RAIter, _UGenerator&&);
|
||||
#endif
|
||||
|
||||
template<typename _RAIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
sort_heap(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
sort_heap(_RAIter, _RAIter, _Compare);
|
||||
|
||||
#if _GLIBCXX_HOSTED
|
||||
template<typename _BIter, typename _Predicate>
|
||||
_BIter
|
||||
stable_partition(_BIter, _BIter, _Predicate);
|
||||
#endif
|
||||
|
||||
#if __cplusplus < 201103L
|
||||
// For C++11 swap() is declared in <type_traits>.
|
||||
|
||||
template<typename _Tp, size_t _Nm>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
inline void
|
||||
swap(_Tp& __a, _Tp& __b);
|
||||
|
||||
template<typename _Tp, size_t _Nm>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
inline void
|
||||
swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]);
|
||||
#endif
|
||||
|
||||
template<typename _FIter1, typename _FIter2>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_FIter2
|
||||
swap_ranges(_FIter1, _FIter1, _FIter2);
|
||||
|
||||
// transform
|
||||
|
||||
template<typename _FIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_FIter
|
||||
unique(_FIter, _FIter);
|
||||
|
||||
template<typename _FIter, typename _BinaryPredicate>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_FIter
|
||||
unique(_FIter, _FIter, _BinaryPredicate);
|
||||
|
||||
// unique_copy
|
||||
|
||||
template<typename _FIter, typename _Tp>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_FIter
|
||||
upper_bound(_FIter, _FIter, const _Tp&);
|
||||
|
||||
template<typename _FIter, typename _Tp, typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_FIter
|
||||
upper_bound(_FIter, _FIter, const _Tp&, _Compare);
|
||||
|
||||
_GLIBCXX_BEGIN_NAMESPACE_ALGO
|
||||
|
||||
template<typename _FIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_FIter
|
||||
adjacent_find(_FIter, _FIter);
|
||||
|
||||
template<typename _FIter, typename _BinaryPredicate>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_FIter
|
||||
adjacent_find(_FIter, _FIter, _BinaryPredicate);
|
||||
|
||||
template<typename _IIter, typename _Tp>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
typename iterator_traits<_IIter>::difference_type
|
||||
count(_IIter, _IIter, const _Tp&);
|
||||
|
||||
template<typename _IIter, typename _Predicate>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
typename iterator_traits<_IIter>::difference_type
|
||||
count_if(_IIter, _IIter, _Predicate);
|
||||
|
||||
template<typename _IIter1, typename _IIter2>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
bool
|
||||
equal(_IIter1, _IIter1, _IIter2);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _BinaryPredicate>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
bool
|
||||
equal(_IIter1, _IIter1, _IIter2, _BinaryPredicate);
|
||||
|
||||
template<typename _IIter, typename _Tp>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_IIter
|
||||
find(_IIter, _IIter, const _Tp&);
|
||||
|
||||
template<typename _FIter1, typename _FIter2>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_FIter1
|
||||
find_first_of(_FIter1, _FIter1, _FIter2, _FIter2);
|
||||
|
||||
template<typename _FIter1, typename _FIter2, typename _BinaryPredicate>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_FIter1
|
||||
find_first_of(_FIter1, _FIter1, _FIter2, _FIter2, _BinaryPredicate);
|
||||
|
||||
template<typename _IIter, typename _Predicate>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_IIter
|
||||
find_if(_IIter, _IIter, _Predicate);
|
||||
|
||||
template<typename _IIter, typename _Funct>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_Funct
|
||||
for_each(_IIter, _IIter, _Funct);
|
||||
|
||||
template<typename _FIter, typename _Generator>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
generate(_FIter, _FIter, _Generator);
|
||||
|
||||
template<typename _OIter, typename _Size, typename _Generator>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
generate_n(_OIter, _Size, _Generator);
|
||||
|
||||
template<typename _IIter1, typename _IIter2>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
bool
|
||||
lexicographical_compare(_IIter1, _IIter1, _IIter2, _IIter2);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
bool
|
||||
lexicographical_compare(_IIter1, _IIter1, _IIter2, _IIter2, _Compare);
|
||||
|
||||
template<typename _FIter>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
_FIter
|
||||
max_element(_FIter, _FIter);
|
||||
|
||||
template<typename _FIter, typename _Compare>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
_FIter
|
||||
max_element(_FIter, _FIter, _Compare);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
merge(_IIter1, _IIter1, _IIter2, _IIter2, _OIter);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter,
|
||||
typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
merge(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare);
|
||||
|
||||
template<typename _FIter>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
_FIter
|
||||
min_element(_FIter, _FIter);
|
||||
|
||||
template<typename _FIter, typename _Compare>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
_FIter
|
||||
min_element(_FIter, _FIter, _Compare);
|
||||
|
||||
template<typename _IIter1, typename _IIter2>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
pair<_IIter1, _IIter2>
|
||||
mismatch(_IIter1, _IIter1, _IIter2);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _BinaryPredicate>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
pair<_IIter1, _IIter2>
|
||||
mismatch(_IIter1, _IIter1, _IIter2, _BinaryPredicate);
|
||||
|
||||
template<typename _RAIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
nth_element(_RAIter, _RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
nth_element(_RAIter, _RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _RAIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
partial_sort(_RAIter, _RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
partial_sort(_RAIter, _RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _BIter, typename _Predicate>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_BIter
|
||||
partition(_BIter, _BIter, _Predicate);
|
||||
|
||||
#if _GLIBCXX_HOSTED
|
||||
template<typename _RAIter>
|
||||
_GLIBCXX14_DEPRECATED_SUGGEST("std::shuffle")
|
||||
void
|
||||
random_shuffle(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Generator>
|
||||
_GLIBCXX14_DEPRECATED_SUGGEST("std::shuffle")
|
||||
void
|
||||
random_shuffle(_RAIter, _RAIter,
|
||||
#if __cplusplus >= 201103L
|
||||
_Generator&&);
|
||||
#else
|
||||
_Generator&);
|
||||
#endif
|
||||
#endif // HOSTED
|
||||
|
||||
template<typename _FIter, typename _Tp>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
replace(_FIter, _FIter, const _Tp&, const _Tp&);
|
||||
|
||||
template<typename _FIter, typename _Predicate, typename _Tp>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
replace_if(_FIter, _FIter, _Predicate, const _Tp&);
|
||||
|
||||
template<typename _FIter1, typename _FIter2>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_FIter1
|
||||
search(_FIter1, _FIter1, _FIter2, _FIter2);
|
||||
|
||||
template<typename _FIter1, typename _FIter2, typename _BinaryPredicate>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_FIter1
|
||||
search(_FIter1, _FIter1, _FIter2, _FIter2, _BinaryPredicate);
|
||||
|
||||
template<typename _FIter, typename _Size, typename _Tp>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_FIter
|
||||
search_n(_FIter, _FIter, _Size, const _Tp&);
|
||||
|
||||
template<typename _FIter, typename _Size, typename _Tp,
|
||||
typename _BinaryPredicate>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_FIter
|
||||
search_n(_FIter, _FIter, _Size, const _Tp&, _BinaryPredicate);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
set_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter,
|
||||
typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
set_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
set_intersection(_IIter1, _IIter1, _IIter2, _IIter2, _OIter);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter,
|
||||
typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
set_intersection(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
set_symmetric_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter,
|
||||
typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
set_symmetric_difference(_IIter1, _IIter1, _IIter2, _IIter2,
|
||||
_OIter, _Compare);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
set_union(_IIter1, _IIter1, _IIter2, _IIter2, _OIter);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter,
|
||||
typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
set_union(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare);
|
||||
|
||||
template<typename _RAIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
sort(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
sort(_RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _RAIter>
|
||||
void
|
||||
stable_sort(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
void
|
||||
stable_sort(_RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _IIter, typename _OIter, typename _UnaryOperation>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
transform(_IIter, _IIter, _OIter, _UnaryOperation);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter,
|
||||
typename _BinaryOperation>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
transform(_IIter1, _IIter1, _IIter2, _OIter, _BinaryOperation);
|
||||
|
||||
template<typename _IIter, typename _OIter>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
unique_copy(_IIter, _IIter, _OIter);
|
||||
|
||||
template<typename _IIter, typename _OIter, typename _BinaryPredicate>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
_OIter
|
||||
unique_copy(_IIter, _IIter, _OIter, _BinaryPredicate);
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_ALGO
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
||||
#ifdef _GLIBCXX_PARALLEL
|
||||
# include <parallel/algorithmfwd.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
// align implementation -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2014-2024 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/align.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{memory}
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_ALIGN_H
|
||||
#define _GLIBCXX_ALIGN_H 1
|
||||
|
||||
#include <bit> // std::has_single_bit
|
||||
#include <stdint.h> // uintptr_t
|
||||
#include <debug/assertions.h> // _GLIBCXX_DEBUG_ASSERT
|
||||
#include <bits/version.h>
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* @brief Fit aligned storage in buffer.
|
||||
*
|
||||
* This function tries to fit @a __size bytes of storage with alignment
|
||||
* @a __align into the buffer @a __ptr of size @a __space bytes. If such
|
||||
* a buffer fits then @a __ptr is changed to point to the first byte of the
|
||||
* aligned storage and @a __space is reduced by the bytes used for alignment.
|
||||
*
|
||||
* C++11 20.6.5 [ptr.align]
|
||||
*
|
||||
* @param __align A fundamental or extended alignment value.
|
||||
* @param __size Size of the aligned storage required.
|
||||
* @param __ptr Pointer to a buffer of @a __space bytes.
|
||||
* @param __space Size of the buffer pointed to by @a __ptr.
|
||||
* @return the updated pointer if the aligned storage fits, otherwise nullptr.
|
||||
*
|
||||
* @ingroup memory
|
||||
*/
|
||||
inline void*
|
||||
align(size_t __align, size_t __size, void*& __ptr, size_t& __space) noexcept
|
||||
{
|
||||
if (__space < __size)
|
||||
return nullptr;
|
||||
const auto __intptr = reinterpret_cast<uintptr_t>(__ptr);
|
||||
const auto __aligned = (__intptr - 1u + __align) & -__align;
|
||||
const auto __diff = __aligned - __intptr;
|
||||
if (__diff > (__space - __size))
|
||||
return nullptr;
|
||||
else
|
||||
{
|
||||
__space -= __diff;
|
||||
return __ptr = reinterpret_cast<void*>(__aligned);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __glibcxx_assume_aligned // C++ >= 20
|
||||
/** @brief Inform the compiler that a pointer is aligned.
|
||||
*
|
||||
* @tparam _Align An alignment value (i.e. a power of two)
|
||||
* @tparam _Tp An object type
|
||||
* @param __ptr A pointer that is aligned to _Align
|
||||
*
|
||||
* C++20 20.10.6 [ptr.align]
|
||||
*
|
||||
* @ingroup memory
|
||||
*/
|
||||
template<size_t _Align, class _Tp>
|
||||
[[nodiscard,__gnu__::__always_inline__]]
|
||||
constexpr _Tp*
|
||||
assume_aligned(_Tp* __ptr) noexcept
|
||||
{
|
||||
static_assert(std::has_single_bit(_Align));
|
||||
if (std::is_constant_evaluated())
|
||||
return __ptr;
|
||||
else
|
||||
{
|
||||
// This function is expected to be used in hot code, where
|
||||
// __glibcxx_assert would add unwanted overhead.
|
||||
_GLIBCXX_DEBUG_ASSERT((uintptr_t)__ptr % _Align == 0);
|
||||
return static_cast<_Tp*>(__builtin_assume_aligned(__ptr, _Align));
|
||||
}
|
||||
}
|
||||
#endif // __glibcxx_assume_aligned
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#endif /* _GLIBCXX_ALIGN_H */
|
||||
@@ -0,0 +1,951 @@
|
||||
// Allocator traits -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2011-2024 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/alloc_traits.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{memory}
|
||||
*/
|
||||
|
||||
#ifndef _ALLOC_TRAITS_H
|
||||
#define _ALLOC_TRAITS_H 1
|
||||
|
||||
#include <bits/stl_construct.h>
|
||||
#include <bits/memoryfwd.h>
|
||||
#if __cplusplus >= 201103L
|
||||
# include <bits/ptr_traits.h>
|
||||
# include <ext/numeric_traits.h>
|
||||
# if _GLIBCXX_HOSTED
|
||||
# include <bits/allocator.h>
|
||||
# endif
|
||||
# if __cpp_exceptions
|
||||
# include <bits/stl_iterator.h> // __make_move_if_noexcept_iterator
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
/// @cond undocumented
|
||||
struct __allocator_traits_base
|
||||
{
|
||||
template<typename _Tp, typename _Up, typename = void>
|
||||
struct __rebind : __replace_first_arg<_Tp, _Up>
|
||||
{
|
||||
static_assert(is_same<
|
||||
typename __replace_first_arg<_Tp, typename _Tp::value_type>::type,
|
||||
_Tp>::value,
|
||||
"allocator_traits<A>::rebind_alloc<A::value_type> must be A");
|
||||
};
|
||||
|
||||
template<typename _Tp, typename _Up>
|
||||
struct __rebind<_Tp, _Up,
|
||||
__void_t<typename _Tp::template rebind<_Up>::other>>
|
||||
{
|
||||
using type = typename _Tp::template rebind<_Up>::other;
|
||||
|
||||
static_assert(is_same<
|
||||
typename _Tp::template rebind<typename _Tp::value_type>::other,
|
||||
_Tp>::value,
|
||||
"allocator_traits<A>::rebind_alloc<A::value_type> must be A");
|
||||
};
|
||||
|
||||
protected:
|
||||
template<typename _Tp>
|
||||
using __pointer = typename _Tp::pointer;
|
||||
template<typename _Tp>
|
||||
using __c_pointer = typename _Tp::const_pointer;
|
||||
template<typename _Tp>
|
||||
using __v_pointer = typename _Tp::void_pointer;
|
||||
template<typename _Tp>
|
||||
using __cv_pointer = typename _Tp::const_void_pointer;
|
||||
template<typename _Tp>
|
||||
using __pocca = typename _Tp::propagate_on_container_copy_assignment;
|
||||
template<typename _Tp>
|
||||
using __pocma = typename _Tp::propagate_on_container_move_assignment;
|
||||
template<typename _Tp>
|
||||
using __pocs = typename _Tp::propagate_on_container_swap;
|
||||
template<typename _Tp>
|
||||
using __equal = __type_identity<typename _Tp::is_always_equal>;
|
||||
};
|
||||
|
||||
template<typename _Alloc, typename _Up>
|
||||
using __alloc_rebind
|
||||
= typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type;
|
||||
/// @endcond
|
||||
|
||||
/**
|
||||
* @brief Uniform interface to all allocator types.
|
||||
* @headerfile memory
|
||||
* @ingroup allocators
|
||||
* @since C++11
|
||||
*/
|
||||
template<typename _Alloc>
|
||||
struct allocator_traits : __allocator_traits_base
|
||||
{
|
||||
/// The allocator type
|
||||
typedef _Alloc allocator_type;
|
||||
/// The allocated type
|
||||
typedef typename _Alloc::value_type value_type;
|
||||
|
||||
/**
|
||||
* @brief The allocator's pointer type.
|
||||
*
|
||||
* @c Alloc::pointer if that type exists, otherwise @c value_type*
|
||||
*/
|
||||
using pointer = __detected_or_t<value_type*, __pointer, _Alloc>;
|
||||
|
||||
private:
|
||||
// Select _Func<_Alloc> or pointer_traits<pointer>::rebind<_Tp>
|
||||
template<template<typename> class _Func, typename _Tp, typename = void>
|
||||
struct _Ptr
|
||||
{
|
||||
using type = typename pointer_traits<pointer>::template rebind<_Tp>;
|
||||
};
|
||||
|
||||
template<template<typename> class _Func, typename _Tp>
|
||||
struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>>
|
||||
{
|
||||
using type = _Func<_Alloc>;
|
||||
};
|
||||
|
||||
// Select _A2::difference_type or pointer_traits<_Ptr>::difference_type
|
||||
template<typename _A2, typename _PtrT, typename = void>
|
||||
struct _Diff
|
||||
{ using type = typename pointer_traits<_PtrT>::difference_type; };
|
||||
|
||||
template<typename _A2, typename _PtrT>
|
||||
struct _Diff<_A2, _PtrT, __void_t<typename _A2::difference_type>>
|
||||
{ using type = typename _A2::difference_type; };
|
||||
|
||||
// Select _A2::size_type or make_unsigned<_DiffT>::type
|
||||
template<typename _A2, typename _DiffT, typename = void>
|
||||
struct _Size : make_unsigned<_DiffT> { };
|
||||
|
||||
template<typename _A2, typename _DiffT>
|
||||
struct _Size<_A2, _DiffT, __void_t<typename _A2::size_type>>
|
||||
{ using type = typename _A2::size_type; };
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief The allocator's const pointer type.
|
||||
*
|
||||
* @c Alloc::const_pointer if that type exists, otherwise
|
||||
* <tt> pointer_traits<pointer>::rebind<const value_type> </tt>
|
||||
*/
|
||||
using const_pointer = typename _Ptr<__c_pointer, const value_type>::type;
|
||||
|
||||
/**
|
||||
* @brief The allocator's void pointer type.
|
||||
*
|
||||
* @c Alloc::void_pointer if that type exists, otherwise
|
||||
* <tt> pointer_traits<pointer>::rebind<void> </tt>
|
||||
*/
|
||||
using void_pointer = typename _Ptr<__v_pointer, void>::type;
|
||||
|
||||
/**
|
||||
* @brief The allocator's const void pointer type.
|
||||
*
|
||||
* @c Alloc::const_void_pointer if that type exists, otherwise
|
||||
* <tt> pointer_traits<pointer>::rebind<const void> </tt>
|
||||
*/
|
||||
using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type;
|
||||
|
||||
/**
|
||||
* @brief The allocator's difference type
|
||||
*
|
||||
* @c Alloc::difference_type if that type exists, otherwise
|
||||
* <tt> pointer_traits<pointer>::difference_type </tt>
|
||||
*/
|
||||
using difference_type = typename _Diff<_Alloc, pointer>::type;
|
||||
|
||||
/**
|
||||
* @brief The allocator's size type
|
||||
*
|
||||
* @c Alloc::size_type if that type exists, otherwise
|
||||
* <tt> make_unsigned<difference_type>::type </tt>
|
||||
*/
|
||||
using size_type = typename _Size<_Alloc, difference_type>::type;
|
||||
|
||||
/**
|
||||
* @brief How the allocator is propagated on copy assignment
|
||||
*
|
||||
* @c Alloc::propagate_on_container_copy_assignment if that type exists,
|
||||
* otherwise @c false_type
|
||||
*/
|
||||
using propagate_on_container_copy_assignment
|
||||
= __detected_or_t<false_type, __pocca, _Alloc>;
|
||||
|
||||
/**
|
||||
* @brief How the allocator is propagated on move assignment
|
||||
*
|
||||
* @c Alloc::propagate_on_container_move_assignment if that type exists,
|
||||
* otherwise @c false_type
|
||||
*/
|
||||
using propagate_on_container_move_assignment
|
||||
= __detected_or_t<false_type, __pocma, _Alloc>;
|
||||
|
||||
/**
|
||||
* @brief How the allocator is propagated on swap
|
||||
*
|
||||
* @c Alloc::propagate_on_container_swap if that type exists,
|
||||
* otherwise @c false_type
|
||||
*/
|
||||
using propagate_on_container_swap
|
||||
= __detected_or_t<false_type, __pocs, _Alloc>;
|
||||
|
||||
/**
|
||||
* @brief Whether all instances of the allocator type compare equal.
|
||||
*
|
||||
* @c Alloc::is_always_equal if that type exists,
|
||||
* otherwise @c is_empty<Alloc>::type
|
||||
*/
|
||||
using is_always_equal
|
||||
= typename __detected_or_t<is_empty<_Alloc>, __equal, _Alloc>::type;
|
||||
|
||||
template<typename _Tp>
|
||||
using rebind_alloc = __alloc_rebind<_Alloc, _Tp>;
|
||||
template<typename _Tp>
|
||||
using rebind_traits = allocator_traits<rebind_alloc<_Tp>>;
|
||||
|
||||
private:
|
||||
template<typename _Alloc2>
|
||||
static constexpr auto
|
||||
_S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint, int)
|
||||
-> decltype(__a.allocate(__n, __hint))
|
||||
{ return __a.allocate(__n, __hint); }
|
||||
|
||||
template<typename _Alloc2>
|
||||
static constexpr pointer
|
||||
_S_allocate(_Alloc2& __a, size_type __n, const_void_pointer, ...)
|
||||
{ return __a.allocate(__n); }
|
||||
|
||||
template<typename _Tp, typename... _Args>
|
||||
struct __construct_helper
|
||||
{
|
||||
template<typename _Alloc2,
|
||||
typename = decltype(std::declval<_Alloc2*>()->construct(
|
||||
std::declval<_Tp*>(), std::declval<_Args>()...))>
|
||||
static true_type __test(int);
|
||||
|
||||
template<typename>
|
||||
static false_type __test(...);
|
||||
|
||||
using type = decltype(__test<_Alloc>(0));
|
||||
};
|
||||
|
||||
template<typename _Tp, typename... _Args>
|
||||
using __has_construct
|
||||
= typename __construct_helper<_Tp, _Args...>::type;
|
||||
|
||||
template<typename _Tp, typename... _Args>
|
||||
static _GLIBCXX14_CONSTEXPR _Require<__has_construct<_Tp, _Args...>>
|
||||
_S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
|
||||
noexcept(noexcept(__a.construct(__p, std::forward<_Args>(__args)...)))
|
||||
{ __a.construct(__p, std::forward<_Args>(__args)...); }
|
||||
|
||||
template<typename _Tp, typename... _Args>
|
||||
static _GLIBCXX14_CONSTEXPR
|
||||
_Require<__and_<__not_<__has_construct<_Tp, _Args...>>,
|
||||
is_constructible<_Tp, _Args...>>>
|
||||
_S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
|
||||
noexcept(std::is_nothrow_constructible<_Tp, _Args...>::value)
|
||||
{
|
||||
#if __cplusplus <= 201703L
|
||||
::new((void*)__p) _Tp(std::forward<_Args>(__args)...);
|
||||
#else
|
||||
std::construct_at(__p, std::forward<_Args>(__args)...);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename _Alloc2, typename _Tp>
|
||||
static _GLIBCXX14_CONSTEXPR auto
|
||||
_S_destroy(_Alloc2& __a, _Tp* __p, int)
|
||||
noexcept(noexcept(__a.destroy(__p)))
|
||||
-> decltype(__a.destroy(__p))
|
||||
{ __a.destroy(__p); }
|
||||
|
||||
template<typename _Alloc2, typename _Tp>
|
||||
static _GLIBCXX14_CONSTEXPR void
|
||||
_S_destroy(_Alloc2&, _Tp* __p, ...)
|
||||
noexcept(std::is_nothrow_destructible<_Tp>::value)
|
||||
{ std::_Destroy(__p); }
|
||||
|
||||
template<typename _Alloc2>
|
||||
static constexpr auto
|
||||
_S_max_size(_Alloc2& __a, int)
|
||||
-> decltype(__a.max_size())
|
||||
{ return __a.max_size(); }
|
||||
|
||||
template<typename _Alloc2>
|
||||
static constexpr size_type
|
||||
_S_max_size(_Alloc2&, ...)
|
||||
{
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 2466. allocator_traits::max_size() default behavior is incorrect
|
||||
return __gnu_cxx::__numeric_traits<size_type>::__max
|
||||
/ sizeof(value_type);
|
||||
}
|
||||
|
||||
template<typename _Alloc2>
|
||||
static constexpr auto
|
||||
_S_select(_Alloc2& __a, int)
|
||||
-> decltype(__a.select_on_container_copy_construction())
|
||||
{ return __a.select_on_container_copy_construction(); }
|
||||
|
||||
template<typename _Alloc2>
|
||||
static constexpr _Alloc2
|
||||
_S_select(_Alloc2& __a, ...)
|
||||
{ return __a; }
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Allocate memory.
|
||||
* @param __a An allocator.
|
||||
* @param __n The number of objects to allocate space for.
|
||||
*
|
||||
* Calls @c a.allocate(n)
|
||||
*/
|
||||
_GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer
|
||||
allocate(_Alloc& __a, size_type __n)
|
||||
{ return __a.allocate(__n); }
|
||||
|
||||
/**
|
||||
* @brief Allocate memory.
|
||||
* @param __a An allocator.
|
||||
* @param __n The number of objects to allocate space for.
|
||||
* @param __hint Aid to locality.
|
||||
* @return Memory of suitable size and alignment for @a n objects
|
||||
* of type @c value_type
|
||||
*
|
||||
* Returns <tt> a.allocate(n, hint) </tt> if that expression is
|
||||
* well-formed, otherwise returns @c a.allocate(n)
|
||||
*/
|
||||
_GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer
|
||||
allocate(_Alloc& __a, size_type __n, const_void_pointer __hint)
|
||||
{ return _S_allocate(__a, __n, __hint, 0); }
|
||||
|
||||
/**
|
||||
* @brief Deallocate memory.
|
||||
* @param __a An allocator.
|
||||
* @param __p Pointer to the memory to deallocate.
|
||||
* @param __n The number of objects space was allocated for.
|
||||
*
|
||||
* Calls <tt> a.deallocate(p, n) </tt>
|
||||
*/
|
||||
static _GLIBCXX20_CONSTEXPR void
|
||||
deallocate(_Alloc& __a, pointer __p, size_type __n)
|
||||
{ __a.deallocate(__p, __n); }
|
||||
|
||||
/**
|
||||
* @brief Construct an object of type `_Tp`
|
||||
* @param __a An allocator.
|
||||
* @param __p Pointer to memory of suitable size and alignment for Tp
|
||||
* @param __args Constructor arguments.
|
||||
*
|
||||
* Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt>
|
||||
* if that expression is well-formed, otherwise uses placement-new
|
||||
* to construct an object of type @a _Tp at location @a __p from the
|
||||
* arguments @a __args...
|
||||
*/
|
||||
template<typename _Tp, typename... _Args>
|
||||
static _GLIBCXX20_CONSTEXPR auto
|
||||
construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
|
||||
noexcept(noexcept(_S_construct(__a, __p,
|
||||
std::forward<_Args>(__args)...)))
|
||||
-> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...))
|
||||
{ _S_construct(__a, __p, std::forward<_Args>(__args)...); }
|
||||
|
||||
/**
|
||||
* @brief Destroy an object of type @a _Tp
|
||||
* @param __a An allocator.
|
||||
* @param __p Pointer to the object to destroy
|
||||
*
|
||||
* Calls @c __a.destroy(__p) if that expression is well-formed,
|
||||
* otherwise calls @c __p->~_Tp()
|
||||
*/
|
||||
template<typename _Tp>
|
||||
static _GLIBCXX20_CONSTEXPR void
|
||||
destroy(_Alloc& __a, _Tp* __p)
|
||||
noexcept(noexcept(_S_destroy(__a, __p, 0)))
|
||||
{ _S_destroy(__a, __p, 0); }
|
||||
|
||||
/**
|
||||
* @brief The maximum supported allocation size
|
||||
* @param __a An allocator.
|
||||
* @return @c __a.max_size() or @c numeric_limits<size_type>::max()
|
||||
*
|
||||
* Returns @c __a.max_size() if that expression is well-formed,
|
||||
* otherwise returns @c numeric_limits<size_type>::max()
|
||||
*/
|
||||
static _GLIBCXX20_CONSTEXPR size_type
|
||||
max_size(const _Alloc& __a) noexcept
|
||||
{ return _S_max_size(__a, 0); }
|
||||
|
||||
/**
|
||||
* @brief Obtain an allocator to use when copying a container.
|
||||
* @param __rhs An allocator.
|
||||
* @return @c __rhs.select_on_container_copy_construction() or @a __rhs
|
||||
*
|
||||
* Returns @c __rhs.select_on_container_copy_construction() if that
|
||||
* expression is well-formed, otherwise returns @a __rhs
|
||||
*/
|
||||
static _GLIBCXX20_CONSTEXPR _Alloc
|
||||
select_on_container_copy_construction(const _Alloc& __rhs)
|
||||
{ return _S_select(__rhs, 0); }
|
||||
};
|
||||
|
||||
#if _GLIBCXX_HOSTED
|
||||
/// Partial specialization for std::allocator.
|
||||
template<typename _Tp>
|
||||
struct allocator_traits<allocator<_Tp>>
|
||||
{
|
||||
/// The allocator type
|
||||
using allocator_type = allocator<_Tp>;
|
||||
|
||||
/// The allocated type
|
||||
using value_type = _Tp;
|
||||
|
||||
/// The allocator's pointer type.
|
||||
using pointer = _Tp*;
|
||||
|
||||
/// The allocator's const pointer type.
|
||||
using const_pointer = const _Tp*;
|
||||
|
||||
/// The allocator's void pointer type.
|
||||
using void_pointer = void*;
|
||||
|
||||
/// The allocator's const void pointer type.
|
||||
using const_void_pointer = const void*;
|
||||
|
||||
/// The allocator's difference type
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
/// The allocator's size type
|
||||
using size_type = std::size_t;
|
||||
|
||||
/// How the allocator is propagated on copy assignment
|
||||
using propagate_on_container_copy_assignment = false_type;
|
||||
|
||||
/// How the allocator is propagated on move assignment
|
||||
using propagate_on_container_move_assignment = true_type;
|
||||
|
||||
/// How the allocator is propagated on swap
|
||||
using propagate_on_container_swap = false_type;
|
||||
|
||||
/// Whether all instances of the allocator type compare equal.
|
||||
using is_always_equal = true_type;
|
||||
|
||||
template<typename _Up>
|
||||
using rebind_alloc = allocator<_Up>;
|
||||
|
||||
template<typename _Up>
|
||||
using rebind_traits = allocator_traits<allocator<_Up>>;
|
||||
|
||||
/**
|
||||
* @brief Allocate memory.
|
||||
* @param __a An allocator.
|
||||
* @param __n The number of objects to allocate space for.
|
||||
*
|
||||
* Calls @c a.allocate(n)
|
||||
*/
|
||||
[[__nodiscard__,__gnu__::__always_inline__]]
|
||||
static _GLIBCXX20_CONSTEXPR pointer
|
||||
allocate(allocator_type& __a, size_type __n)
|
||||
{ return __a.allocate(__n); }
|
||||
|
||||
/**
|
||||
* @brief Allocate memory.
|
||||
* @param __a An allocator.
|
||||
* @param __n The number of objects to allocate space for.
|
||||
* @param __hint Aid to locality.
|
||||
* @return Memory of suitable size and alignment for @a n objects
|
||||
* of type @c value_type
|
||||
*
|
||||
* Returns <tt> a.allocate(n, hint) </tt>
|
||||
*/
|
||||
[[__nodiscard__,__gnu__::__always_inline__]]
|
||||
static _GLIBCXX20_CONSTEXPR pointer
|
||||
allocate(allocator_type& __a, size_type __n,
|
||||
[[maybe_unused]] const_void_pointer __hint)
|
||||
{
|
||||
#if __cplusplus <= 201703L
|
||||
return __a.allocate(__n, __hint);
|
||||
#else
|
||||
return __a.allocate(__n);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deallocate memory.
|
||||
* @param __a An allocator.
|
||||
* @param __p Pointer to the memory to deallocate.
|
||||
* @param __n The number of objects space was allocated for.
|
||||
*
|
||||
* Calls <tt> a.deallocate(p, n) </tt>
|
||||
*/
|
||||
[[__gnu__::__always_inline__]]
|
||||
static _GLIBCXX20_CONSTEXPR void
|
||||
deallocate(allocator_type& __a, pointer __p, size_type __n)
|
||||
{ __a.deallocate(__p, __n); }
|
||||
|
||||
/**
|
||||
* @brief Construct an object of type `_Up`
|
||||
* @param __a An allocator.
|
||||
* @param __p Pointer to memory of suitable size and alignment for
|
||||
* an object of type `_Up`.
|
||||
* @param __args Constructor arguments.
|
||||
*
|
||||
* Calls `__a.construct(__p, std::forward<_Args>(__args)...)`
|
||||
* in C++11, C++14 and C++17. Changed in C++20 to call
|
||||
* `std::construct_at(__p, std::forward<_Args>(__args)...)` instead.
|
||||
*/
|
||||
template<typename _Up, typename... _Args>
|
||||
[[__gnu__::__always_inline__]]
|
||||
static _GLIBCXX20_CONSTEXPR void
|
||||
construct(allocator_type& __a __attribute__((__unused__)), _Up* __p,
|
||||
_Args&&... __args)
|
||||
noexcept(std::is_nothrow_constructible<_Up, _Args...>::value)
|
||||
{
|
||||
#if __cplusplus <= 201703L
|
||||
__a.construct(__p, std::forward<_Args>(__args)...);
|
||||
#else
|
||||
std::construct_at(__p, std::forward<_Args>(__args)...);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destroy an object of type @a _Up
|
||||
* @param __a An allocator.
|
||||
* @param __p Pointer to the object to destroy
|
||||
*
|
||||
* Calls @c __a.destroy(__p).
|
||||
*/
|
||||
template<typename _Up>
|
||||
[[__gnu__::__always_inline__]]
|
||||
static _GLIBCXX20_CONSTEXPR void
|
||||
destroy(allocator_type& __a __attribute__((__unused__)), _Up* __p)
|
||||
noexcept(is_nothrow_destructible<_Up>::value)
|
||||
{
|
||||
#if __cplusplus <= 201703L
|
||||
__a.destroy(__p);
|
||||
#else
|
||||
std::destroy_at(__p);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The maximum supported allocation size
|
||||
* @param __a An allocator.
|
||||
* @return @c __a.max_size()
|
||||
*/
|
||||
[[__gnu__::__always_inline__]]
|
||||
static _GLIBCXX20_CONSTEXPR size_type
|
||||
max_size(const allocator_type& __a __attribute__((__unused__))) noexcept
|
||||
{
|
||||
#if __cplusplus <= 201703L
|
||||
return __a.max_size();
|
||||
#else
|
||||
return size_t(-1) / sizeof(value_type);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Obtain an allocator to use when copying a container.
|
||||
* @param __rhs An allocator.
|
||||
* @return @c __rhs
|
||||
*/
|
||||
[[__gnu__::__always_inline__]]
|
||||
static _GLIBCXX20_CONSTEXPR allocator_type
|
||||
select_on_container_copy_construction(const allocator_type& __rhs)
|
||||
{ return __rhs; }
|
||||
};
|
||||
|
||||
/// Explicit specialization for std::allocator<void>.
|
||||
template<>
|
||||
struct allocator_traits<allocator<void>>
|
||||
{
|
||||
/// The allocator type
|
||||
using allocator_type = allocator<void>;
|
||||
|
||||
/// The allocated type
|
||||
using value_type = void;
|
||||
|
||||
/// The allocator's pointer type.
|
||||
using pointer = void*;
|
||||
|
||||
/// The allocator's const pointer type.
|
||||
using const_pointer = const void*;
|
||||
|
||||
/// The allocator's void pointer type.
|
||||
using void_pointer = void*;
|
||||
|
||||
/// The allocator's const void pointer type.
|
||||
using const_void_pointer = const void*;
|
||||
|
||||
/// The allocator's difference type
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
/// The allocator's size type
|
||||
using size_type = std::size_t;
|
||||
|
||||
/// How the allocator is propagated on copy assignment
|
||||
using propagate_on_container_copy_assignment = false_type;
|
||||
|
||||
/// How the allocator is propagated on move assignment
|
||||
using propagate_on_container_move_assignment = true_type;
|
||||
|
||||
/// How the allocator is propagated on swap
|
||||
using propagate_on_container_swap = false_type;
|
||||
|
||||
/// Whether all instances of the allocator type compare equal.
|
||||
using is_always_equal = true_type;
|
||||
|
||||
template<typename _Up>
|
||||
using rebind_alloc = allocator<_Up>;
|
||||
|
||||
template<typename _Up>
|
||||
using rebind_traits = allocator_traits<allocator<_Up>>;
|
||||
|
||||
/// allocate is ill-formed for allocator<void>
|
||||
static void*
|
||||
allocate(allocator_type&, size_type, const void* = nullptr) = delete;
|
||||
|
||||
/// deallocate is ill-formed for allocator<void>
|
||||
static void
|
||||
deallocate(allocator_type&, void*, size_type) = delete;
|
||||
|
||||
/**
|
||||
* @brief Construct an object of type `_Up`
|
||||
* @param __a An allocator.
|
||||
* @param __p Pointer to memory of suitable size and alignment for
|
||||
* an object of type `_Up`.
|
||||
* @param __args Constructor arguments.
|
||||
*
|
||||
* Calls `__a.construct(__p, std::forward<_Args>(__args)...)`
|
||||
* in C++11, C++14 and C++17. Changed in C++20 to call
|
||||
* `std::construct_at(__p, std::forward<_Args>(__args)...)` instead.
|
||||
*/
|
||||
template<typename _Up, typename... _Args>
|
||||
[[__gnu__::__always_inline__]]
|
||||
static _GLIBCXX20_CONSTEXPR void
|
||||
construct(allocator_type&, _Up* __p, _Args&&... __args)
|
||||
noexcept(std::is_nothrow_constructible<_Up, _Args...>::value)
|
||||
{ std::_Construct(__p, std::forward<_Args>(__args)...); }
|
||||
|
||||
/**
|
||||
* @brief Destroy an object of type `_Up`
|
||||
* @param __a An allocator.
|
||||
* @param __p Pointer to the object to destroy
|
||||
*
|
||||
* Invokes the destructor for `*__p`.
|
||||
*/
|
||||
template<typename _Up>
|
||||
[[__gnu__::__always_inline__]]
|
||||
static _GLIBCXX20_CONSTEXPR void
|
||||
destroy(allocator_type&, _Up* __p)
|
||||
noexcept(is_nothrow_destructible<_Up>::value)
|
||||
{ std::_Destroy(__p); }
|
||||
|
||||
/// max_size is ill-formed for allocator<void>
|
||||
static size_type
|
||||
max_size(const allocator_type&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Obtain an allocator to use when copying a container.
|
||||
* @param __rhs An allocator.
|
||||
* @return `__rhs`
|
||||
*/
|
||||
[[__gnu__::__always_inline__]]
|
||||
static _GLIBCXX20_CONSTEXPR allocator_type
|
||||
select_on_container_copy_construction(const allocator_type& __rhs)
|
||||
{ return __rhs; }
|
||||
};
|
||||
#endif
|
||||
|
||||
/// @cond undocumented
|
||||
#if __cplusplus < 201703L
|
||||
template<typename _Alloc>
|
||||
[[__gnu__::__always_inline__]]
|
||||
inline void
|
||||
__do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type)
|
||||
{ __one = __two; }
|
||||
|
||||
template<typename _Alloc>
|
||||
[[__gnu__::__always_inline__]]
|
||||
inline void
|
||||
__do_alloc_on_copy(_Alloc&, const _Alloc&, false_type)
|
||||
{ }
|
||||
#endif
|
||||
|
||||
template<typename _Alloc>
|
||||
[[__gnu__::__always_inline__]]
|
||||
_GLIBCXX14_CONSTEXPR inline void
|
||||
__alloc_on_copy(_Alloc& __one, const _Alloc& __two)
|
||||
{
|
||||
using __traits = allocator_traits<_Alloc>;
|
||||
using __pocca =
|
||||
typename __traits::propagate_on_container_copy_assignment::type;
|
||||
#if __cplusplus >= 201703L
|
||||
if constexpr (__pocca::value)
|
||||
__one = __two;
|
||||
#else
|
||||
__do_alloc_on_copy(__one, __two, __pocca());
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename _Alloc>
|
||||
[[__gnu__::__always_inline__]]
|
||||
constexpr _Alloc
|
||||
__alloc_on_copy(const _Alloc& __a)
|
||||
{
|
||||
typedef allocator_traits<_Alloc> __traits;
|
||||
return __traits::select_on_container_copy_construction(__a);
|
||||
}
|
||||
|
||||
#if __cplusplus < 201703L
|
||||
template<typename _Alloc>
|
||||
[[__gnu__::__always_inline__]]
|
||||
inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type)
|
||||
{ __one = std::move(__two); }
|
||||
|
||||
template<typename _Alloc>
|
||||
[[__gnu__::__always_inline__]]
|
||||
inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type)
|
||||
{ }
|
||||
#endif
|
||||
|
||||
template<typename _Alloc>
|
||||
[[__gnu__::__always_inline__]]
|
||||
_GLIBCXX14_CONSTEXPR inline void
|
||||
__alloc_on_move(_Alloc& __one, _Alloc& __two)
|
||||
{
|
||||
using __traits = allocator_traits<_Alloc>;
|
||||
using __pocma
|
||||
= typename __traits::propagate_on_container_move_assignment::type;
|
||||
#if __cplusplus >= 201703L
|
||||
if constexpr (__pocma::value)
|
||||
__one = std::move(__two);
|
||||
#else
|
||||
__do_alloc_on_move(__one, __two, __pocma());
|
||||
#endif
|
||||
}
|
||||
|
||||
#if __cplusplus < 201703L
|
||||
template<typename _Alloc>
|
||||
[[__gnu__::__always_inline__]]
|
||||
inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type)
|
||||
{
|
||||
using std::swap;
|
||||
swap(__one, __two);
|
||||
}
|
||||
|
||||
template<typename _Alloc>
|
||||
[[__gnu__::__always_inline__]]
|
||||
inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type)
|
||||
{ }
|
||||
#endif
|
||||
|
||||
template<typename _Alloc>
|
||||
[[__gnu__::__always_inline__]]
|
||||
_GLIBCXX14_CONSTEXPR inline void
|
||||
__alloc_on_swap(_Alloc& __one, _Alloc& __two)
|
||||
{
|
||||
using __traits = allocator_traits<_Alloc>;
|
||||
using __pocs = typename __traits::propagate_on_container_swap::type;
|
||||
#if __cplusplus >= 201703L
|
||||
if constexpr (__pocs::value)
|
||||
{
|
||||
using std::swap;
|
||||
swap(__one, __two);
|
||||
}
|
||||
#else
|
||||
__do_alloc_on_swap(__one, __two, __pocs());
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename _Alloc, typename _Tp,
|
||||
typename _ValueT = __remove_cvref_t<typename _Alloc::value_type>,
|
||||
typename = void>
|
||||
struct __is_alloc_insertable_impl
|
||||
: false_type
|
||||
{ };
|
||||
|
||||
template<typename _Alloc, typename _Tp, typename _ValueT>
|
||||
struct __is_alloc_insertable_impl<_Alloc, _Tp, _ValueT,
|
||||
__void_t<decltype(allocator_traits<_Alloc>::construct(
|
||||
std::declval<_Alloc&>(), std::declval<_ValueT*>(),
|
||||
std::declval<_Tp>()))>>
|
||||
: true_type
|
||||
{ };
|
||||
|
||||
// true if _Alloc::value_type is CopyInsertable into containers using _Alloc
|
||||
// (might be wrong if _Alloc::construct exists but is not constrained,
|
||||
// i.e. actually trying to use it would still be invalid. Use with caution.)
|
||||
template<typename _Alloc>
|
||||
struct __is_copy_insertable
|
||||
: __is_alloc_insertable_impl<_Alloc,
|
||||
typename _Alloc::value_type const&>::type
|
||||
{ };
|
||||
|
||||
#if _GLIBCXX_HOSTED
|
||||
// std::allocator<_Tp> just requires CopyConstructible
|
||||
template<typename _Tp>
|
||||
struct __is_copy_insertable<allocator<_Tp>>
|
||||
: is_copy_constructible<_Tp>
|
||||
{ };
|
||||
#endif
|
||||
|
||||
// true if _Alloc::value_type is MoveInsertable into containers using _Alloc
|
||||
// (might be wrong if _Alloc::construct exists but is not constrained,
|
||||
// i.e. actually trying to use it would still be invalid. Use with caution.)
|
||||
template<typename _Alloc>
|
||||
struct __is_move_insertable
|
||||
: __is_alloc_insertable_impl<_Alloc, typename _Alloc::value_type>::type
|
||||
{ };
|
||||
|
||||
#if _GLIBCXX_HOSTED
|
||||
// std::allocator<_Tp> just requires MoveConstructible
|
||||
template<typename _Tp>
|
||||
struct __is_move_insertable<allocator<_Tp>>
|
||||
: is_move_constructible<_Tp>
|
||||
{ };
|
||||
#endif
|
||||
|
||||
// Trait to detect Allocator-like types.
|
||||
template<typename _Alloc, typename = void>
|
||||
struct __is_allocator : false_type { };
|
||||
|
||||
template<typename _Alloc>
|
||||
struct __is_allocator<_Alloc,
|
||||
__void_t<typename _Alloc::value_type,
|
||||
decltype(std::declval<_Alloc&>().allocate(size_t{}))>>
|
||||
: true_type { };
|
||||
|
||||
template<typename _Alloc>
|
||||
using _RequireAllocator
|
||||
= typename enable_if<__is_allocator<_Alloc>::value, _Alloc>::type;
|
||||
|
||||
template<typename _Alloc>
|
||||
using _RequireNotAllocator
|
||||
= typename enable_if<!__is_allocator<_Alloc>::value, _Alloc>::type;
|
||||
|
||||
#if __cpp_concepts >= 201907L
|
||||
template<typename _Alloc>
|
||||
concept __allocator_like = requires (_Alloc& __a) {
|
||||
typename _Alloc::value_type;
|
||||
__a.deallocate(__a.allocate(1u), 1u);
|
||||
};
|
||||
#endif
|
||||
/// @endcond
|
||||
#endif // C++11
|
||||
|
||||
/// @cond undocumented
|
||||
|
||||
// To implement Option 3 of DR 431.
|
||||
template<typename _Alloc, bool = __is_empty(_Alloc)>
|
||||
struct __alloc_swap
|
||||
{ static void _S_do_it(_Alloc&, _Alloc&) _GLIBCXX_NOEXCEPT { } };
|
||||
|
||||
template<typename _Alloc>
|
||||
struct __alloc_swap<_Alloc, false>
|
||||
{
|
||||
static void
|
||||
_S_do_it(_Alloc& __one, _Alloc& __two) _GLIBCXX_NOEXCEPT
|
||||
{
|
||||
// Precondition: swappable allocators.
|
||||
if (__one != __two)
|
||||
swap(__one, __two);
|
||||
}
|
||||
};
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _Tp, bool
|
||||
= __or_<is_copy_constructible<typename _Tp::value_type>,
|
||||
is_nothrow_move_constructible<typename _Tp::value_type>>::value>
|
||||
struct __shrink_to_fit_aux
|
||||
{ static bool _S_do_it(_Tp&) noexcept { return false; } };
|
||||
|
||||
template<typename _Tp>
|
||||
struct __shrink_to_fit_aux<_Tp, true>
|
||||
{
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
static bool
|
||||
_S_do_it(_Tp& __c) noexcept
|
||||
{
|
||||
#if __cpp_exceptions
|
||||
try
|
||||
{
|
||||
_Tp(__make_move_if_noexcept_iterator(__c.begin()),
|
||||
__make_move_if_noexcept_iterator(__c.end()),
|
||||
__c.get_allocator()).swap(__c);
|
||||
return true;
|
||||
}
|
||||
catch(...)
|
||||
{ return false; }
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Destroy a range of objects using the supplied allocator. For
|
||||
* non-default allocators we do not optimize away invocation of
|
||||
* destroy() even if _Tp has a trivial destructor.
|
||||
*/
|
||||
|
||||
template<typename _ForwardIterator, typename _Allocator>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
_Destroy(_ForwardIterator __first, _ForwardIterator __last,
|
||||
_Allocator& __alloc)
|
||||
{
|
||||
for (; __first != __last; ++__first)
|
||||
#if __cplusplus < 201103L
|
||||
__alloc.destroy(std::__addressof(*__first));
|
||||
#else
|
||||
allocator_traits<_Allocator>::destroy(__alloc,
|
||||
std::__addressof(*__first));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if _GLIBCXX_HOSTED
|
||||
template<typename _ForwardIterator, typename _Tp>
|
||||
__attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR
|
||||
inline void
|
||||
_Destroy(_ForwardIterator __first, _ForwardIterator __last,
|
||||
allocator<_Tp>&)
|
||||
{
|
||||
std::_Destroy(__first, __last);
|
||||
}
|
||||
#endif
|
||||
/// @endcond
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
#endif // _ALLOC_TRAITS_H
|
||||
@@ -0,0 +1,295 @@
|
||||
// Allocators -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2024 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996-1997
|
||||
* Silicon Graphics Computer Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Silicon Graphics makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
/** @file bits/allocator.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{memory}
|
||||
*/
|
||||
|
||||
#ifndef _ALLOCATOR_H
|
||||
#define _ALLOCATOR_H 1
|
||||
|
||||
#include <bits/c++allocator.h> // Define the base class to std::allocator.
|
||||
#include <bits/memoryfwd.h>
|
||||
#if __cplusplus >= 201103L
|
||||
#include <type_traits>
|
||||
#endif
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* @addtogroup allocators
|
||||
* @{
|
||||
*/
|
||||
|
||||
// Since C++20 the primary template should be used for allocator<void>,
|
||||
// but then it would have a non-trivial default ctor and dtor for C++20,
|
||||
// but trivial for C++98-17, which would be an ABI incompatibility between
|
||||
// different standard dialects. So C++20 still uses the allocator<void>
|
||||
// explicit specialization, with the historical ABI properties, but with
|
||||
// the same members that are present in the primary template.
|
||||
|
||||
/** std::allocator<void> specialization.
|
||||
*
|
||||
* @headerfile memory
|
||||
*/
|
||||
template<>
|
||||
class allocator<void>
|
||||
{
|
||||
public:
|
||||
typedef void value_type;
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
|
||||
#if __cplusplus <= 201703L
|
||||
// These were removed for C++20, allocator_traits does the right thing.
|
||||
typedef void* pointer;
|
||||
typedef const void* const_pointer;
|
||||
|
||||
template<typename _Tp1>
|
||||
struct rebind
|
||||
{ typedef allocator<_Tp1> other; };
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 2103. std::allocator propagate_on_container_move_assignment
|
||||
using propagate_on_container_move_assignment = true_type;
|
||||
|
||||
using is_always_equal
|
||||
_GLIBCXX20_DEPRECATED_SUGGEST("std::allocator_traits::is_always_equal")
|
||||
= true_type;
|
||||
|
||||
#if __cplusplus >= 202002L
|
||||
// As noted above, these members are present for C++20 to provide the
|
||||
// same API as the primary template, but still trivial as in pre-C++20.
|
||||
allocator() = default;
|
||||
~allocator() = default;
|
||||
|
||||
template<typename _Up>
|
||||
__attribute__((__always_inline__))
|
||||
constexpr
|
||||
allocator(const allocator<_Up>&) noexcept { }
|
||||
|
||||
// No allocate member because it's ill-formed by LWG 3307.
|
||||
// No deallocate member because it would be undefined to call it
|
||||
// with any pointer which wasn't obtained from allocate.
|
||||
#endif // C++20
|
||||
#endif // C++11
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The @a standard allocator, as per C++03 [20.4.1].
|
||||
*
|
||||
* See https://gcc.gnu.org/onlinedocs/libstdc++/manual/memory.html#std.util.memory.allocator
|
||||
* for further details.
|
||||
*
|
||||
* @tparam _Tp Type of allocated object.
|
||||
*
|
||||
* @headerfile memory
|
||||
*/
|
||||
template<typename _Tp>
|
||||
class allocator : public __allocator_base<_Tp>
|
||||
{
|
||||
public:
|
||||
typedef _Tp value_type;
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
|
||||
#if __cplusplus <= 201703L
|
||||
// These were removed for C++20.
|
||||
typedef _Tp* pointer;
|
||||
typedef const _Tp* const_pointer;
|
||||
typedef _Tp& reference;
|
||||
typedef const _Tp& const_reference;
|
||||
|
||||
template<typename _Tp1>
|
||||
struct rebind
|
||||
{ typedef allocator<_Tp1> other; };
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 2103. std::allocator propagate_on_container_move_assignment
|
||||
using propagate_on_container_move_assignment = true_type;
|
||||
|
||||
using is_always_equal
|
||||
_GLIBCXX20_DEPRECATED_SUGGEST("std::allocator_traits::is_always_equal")
|
||||
= true_type;
|
||||
#endif
|
||||
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 3035. std::allocator's constructors should be constexpr
|
||||
__attribute__((__always_inline__))
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
allocator() _GLIBCXX_NOTHROW { }
|
||||
|
||||
__attribute__((__always_inline__))
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
allocator(const allocator& __a) _GLIBCXX_NOTHROW
|
||||
: __allocator_base<_Tp>(__a) { }
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
// Avoid implicit deprecation.
|
||||
allocator& operator=(const allocator&) = default;
|
||||
#endif
|
||||
|
||||
template<typename _Tp1>
|
||||
__attribute__((__always_inline__))
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
allocator(const allocator<_Tp1>&) _GLIBCXX_NOTHROW { }
|
||||
|
||||
__attribute__((__always_inline__))
|
||||
#if __cpp_constexpr_dynamic_alloc
|
||||
constexpr
|
||||
#endif
|
||||
~allocator() _GLIBCXX_NOTHROW { }
|
||||
|
||||
#if __cplusplus > 201703L
|
||||
[[nodiscard,__gnu__::__always_inline__]]
|
||||
constexpr _Tp*
|
||||
allocate(size_t __n)
|
||||
{
|
||||
if (std::__is_constant_evaluated())
|
||||
{
|
||||
if (__builtin_mul_overflow(__n, sizeof(_Tp), &__n))
|
||||
std::__throw_bad_array_new_length();
|
||||
return static_cast<_Tp*>(::operator new(__n));
|
||||
}
|
||||
|
||||
return __allocator_base<_Tp>::allocate(__n, 0);
|
||||
}
|
||||
|
||||
[[__gnu__::__always_inline__]]
|
||||
constexpr void
|
||||
deallocate(_Tp* __p, size_t __n)
|
||||
{
|
||||
if (std::__is_constant_evaluated())
|
||||
{
|
||||
::operator delete(__p);
|
||||
return;
|
||||
}
|
||||
__allocator_base<_Tp>::deallocate(__p, __n);
|
||||
}
|
||||
#endif // C++20
|
||||
|
||||
friend __attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR
|
||||
bool
|
||||
operator==(const allocator&, const allocator&) _GLIBCXX_NOTHROW
|
||||
{ return true; }
|
||||
|
||||
#if __cpp_impl_three_way_comparison < 201907L
|
||||
friend __attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR
|
||||
bool
|
||||
operator!=(const allocator&, const allocator&) _GLIBCXX_NOTHROW
|
||||
{ return false; }
|
||||
#endif
|
||||
|
||||
// Inherit everything else.
|
||||
};
|
||||
|
||||
/** Equality comparison for std::allocator objects
|
||||
*
|
||||
* @return true, for all std::allocator objects.
|
||||
* @relates std::allocator
|
||||
*/
|
||||
template<typename _T1, typename _T2>
|
||||
__attribute__((__always_inline__))
|
||||
inline _GLIBCXX20_CONSTEXPR bool
|
||||
operator==(const allocator<_T1>&, const allocator<_T2>&)
|
||||
_GLIBCXX_NOTHROW
|
||||
{ return true; }
|
||||
|
||||
#if __cpp_impl_three_way_comparison < 201907L
|
||||
template<typename _T1, typename _T2>
|
||||
__attribute__((__always_inline__))
|
||||
inline _GLIBCXX20_CONSTEXPR bool
|
||||
operator!=(const allocator<_T1>&, const allocator<_T2>&)
|
||||
_GLIBCXX_NOTHROW
|
||||
{ return false; }
|
||||
#endif
|
||||
|
||||
/// @cond undocumented
|
||||
|
||||
// Invalid allocator<cv T> partial specializations.
|
||||
// allocator_traits::rebind_alloc can be used to form a valid allocator type.
|
||||
template<typename _Tp>
|
||||
class allocator<const _Tp>
|
||||
{
|
||||
public:
|
||||
typedef _Tp value_type;
|
||||
allocator() { }
|
||||
template<typename _Up> allocator(const allocator<_Up>&) { }
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
class allocator<volatile _Tp>
|
||||
{
|
||||
public:
|
||||
typedef _Tp value_type;
|
||||
allocator() { }
|
||||
template<typename _Up> allocator(const allocator<_Up>&) { }
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
class allocator<const volatile _Tp>
|
||||
{
|
||||
public:
|
||||
typedef _Tp value_type;
|
||||
allocator() { }
|
||||
template<typename _Up> allocator(const allocator<_Up>&) { }
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
/// @} group allocator
|
||||
|
||||
// Inhibit implicit instantiations for required instantiations,
|
||||
// which are defined via explicit instantiations elsewhere.
|
||||
#if _GLIBCXX_EXTERN_TEMPLATE
|
||||
extern template class allocator<char>;
|
||||
extern template class allocator<wchar_t>;
|
||||
#endif
|
||||
|
||||
// Undefine.
|
||||
#undef __allocator_base
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,66 @@
|
||||
// -*- C++ -*- header.
|
||||
|
||||
// Copyright (C) 2008-2024 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/atomic_lockfree_defines.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{atomic}
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_ATOMIC_LOCK_FREE_H
|
||||
#define _GLIBCXX_ATOMIC_LOCK_FREE_H 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
/**
|
||||
* @addtogroup atomics
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Lock-free property.
|
||||
*
|
||||
* 0 indicates that the types are never lock-free.
|
||||
* 1 indicates that the types are sometimes lock-free.
|
||||
* 2 indicates that the types are always lock-free.
|
||||
*/
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
#define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE
|
||||
#define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE
|
||||
#define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE
|
||||
#ifdef _GLIBCXX_USE_CHAR8_T
|
||||
#define ATOMIC_CHAR8_T_LOCK_FREE __GCC_ATOMIC_CHAR8_T_LOCK_FREE
|
||||
#endif
|
||||
#define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE
|
||||
#define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE
|
||||
#define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE
|
||||
#define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE
|
||||
#define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE
|
||||
#define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE
|
||||
#define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE
|
||||
#endif
|
||||
|
||||
/// @} group atomics
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,40 @@
|
||||
// Low-level type for atomic operations -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2004-2024 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file atomic_word.h
|
||||
* This file is a GNU extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_ATOMIC_WORD_H
|
||||
#define _GLIBCXX_ATOMIC_WORD_H 1
|
||||
|
||||
typedef int _Atomic_word;
|
||||
|
||||
|
||||
// This is a memory order acquire fence.
|
||||
#define _GLIBCXX_READ_MEM_BARRIER __atomic_thread_fence (__ATOMIC_ACQUIRE)
|
||||
// This is a memory order release fence.
|
||||
#define _GLIBCXX_WRITE_MEM_BARRIER __atomic_thread_fence (__ATOMIC_RELEASE)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,148 @@
|
||||
// Wrapper of C-language FILE struct -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2000-2024 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
//
|
||||
// ISO C++ 14882: 27.8 File-based streams
|
||||
//
|
||||
|
||||
/** @file bits/basic_file.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{ios}
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_BASIC_FILE_STDIO_H
|
||||
#define _GLIBCXX_BASIC_FILE_STDIO_H 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include <bits/c++config.h>
|
||||
#include <bits/c++io.h> // for __c_lock and __c_file
|
||||
#include <bits/move.h> // for swap
|
||||
#include <ios>
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
// Generic declaration.
|
||||
template<typename _CharT>
|
||||
class __basic_file;
|
||||
|
||||
// Specialization.
|
||||
template<>
|
||||
class __basic_file<char>
|
||||
{
|
||||
// Underlying data source/sink.
|
||||
__c_file* _M_cfile;
|
||||
|
||||
// True iff we opened _M_cfile, and thus must close it ourselves.
|
||||
bool _M_cfile_created;
|
||||
|
||||
public:
|
||||
__basic_file(__c_lock* __lock = 0) throw ();
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
__basic_file(__basic_file&& __rv, __c_lock* = 0) noexcept
|
||||
: _M_cfile(__rv._M_cfile), _M_cfile_created(__rv._M_cfile_created)
|
||||
{
|
||||
__rv._M_cfile = nullptr;
|
||||
__rv._M_cfile_created = false;
|
||||
}
|
||||
|
||||
__basic_file& operator=(const __basic_file&) = delete;
|
||||
__basic_file& operator=(__basic_file&&) = delete;
|
||||
|
||||
void
|
||||
swap(__basic_file& __f) noexcept
|
||||
{
|
||||
std::swap(_M_cfile, __f._M_cfile);
|
||||
std::swap(_M_cfile_created, __f._M_cfile_created);
|
||||
}
|
||||
#endif
|
||||
|
||||
__basic_file*
|
||||
open(const char* __name, ios_base::openmode __mode, int __prot = 0664);
|
||||
|
||||
#if _GLIBCXX_HAVE__WFOPEN && _GLIBCXX_USE_WCHAR_T
|
||||
__basic_file*
|
||||
open(const wchar_t* __name, ios_base::openmode __mode);
|
||||
#endif
|
||||
|
||||
__basic_file*
|
||||
sys_open(__c_file* __file, ios_base::openmode);
|
||||
|
||||
__basic_file*
|
||||
sys_open(int __fd, ios_base::openmode __mode) throw ();
|
||||
|
||||
__basic_file*
|
||||
close();
|
||||
|
||||
_GLIBCXX_PURE bool
|
||||
is_open() const throw ();
|
||||
|
||||
_GLIBCXX_PURE int
|
||||
fd() throw ();
|
||||
|
||||
_GLIBCXX_PURE __c_file*
|
||||
file() throw ();
|
||||
|
||||
~__basic_file();
|
||||
|
||||
streamsize
|
||||
xsputn(const char* __s, streamsize __n);
|
||||
|
||||
streamsize
|
||||
xsputn_2(const char* __s1, streamsize __n1,
|
||||
const char* __s2, streamsize __n2);
|
||||
|
||||
streamsize
|
||||
xsgetn(char* __s, streamsize __n);
|
||||
|
||||
streamoff
|
||||
seekoff(streamoff __off, ios_base::seekdir __way) throw ();
|
||||
|
||||
int
|
||||
sync();
|
||||
|
||||
streamsize
|
||||
showmanyc();
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
#ifdef _GLIBCXX_USE_STDIO_PURE
|
||||
using native_handle_type = __c_file*; // FILE*
|
||||
#elif _GLIBCXX_USE__GET_OSFHANDLE
|
||||
using native_handle_type = void*; // HANDLE
|
||||
#else
|
||||
using native_handle_type = int; // POSIX file descriptor
|
||||
#endif
|
||||
|
||||
native_handle_type
|
||||
native_handle() const noexcept;
|
||||
#endif
|
||||
};
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,883 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2004-2024 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
//
|
||||
|
||||
/** @file bits/boost_concept_check.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{iterator}
|
||||
*/
|
||||
|
||||
// GCC Note: based on version 1.12.0 of the Boost library.
|
||||
|
||||
#ifndef _BOOST_CONCEPT_CHECK_H
|
||||
#define _BOOST_CONCEPT_CHECK_H 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include <bits/c++config.h>
|
||||
#include <bits/stl_iterator_base_types.h> // for traits and tags
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||
struct _Bit_iterator;
|
||||
struct _Bit_const_iterator;
|
||||
_GLIBCXX_END_NAMESPACE_CONTAINER
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
namespace __gnu_debug
|
||||
{
|
||||
template<typename _Iterator, typename _Sequence, typename _Category>
|
||||
class _Safe_iterator;
|
||||
}
|
||||
|
||||
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
|
||||
|
||||
#define _IsUnused __attribute__ ((__unused__))
|
||||
|
||||
// When the C-C code is in use, we would like this function to do as little
|
||||
// as possible at runtime, use as few resources as possible, and hopefully
|
||||
// be elided out of existence... hmmm.
|
||||
template <class _Concept>
|
||||
_GLIBCXX14_CONSTEXPR inline void __function_requires()
|
||||
{
|
||||
void (_Concept::*__x)() _IsUnused = &_Concept::__constraints;
|
||||
}
|
||||
|
||||
// No definition: if this is referenced, there's a problem with
|
||||
// the instantiating type not being one of the required integer types.
|
||||
// Unfortunately, this results in a link-time error, not a compile-time error.
|
||||
void __error_type_must_be_an_integer_type();
|
||||
void __error_type_must_be_an_unsigned_integer_type();
|
||||
void __error_type_must_be_a_signed_integer_type();
|
||||
|
||||
// ??? Should the "concept_checking*" structs begin with more than _ ?
|
||||
#define _GLIBCXX_CLASS_REQUIRES(_type_var, _ns, _concept) \
|
||||
typedef void (_ns::_concept <_type_var>::* _func##_type_var##_concept)(); \
|
||||
template <_func##_type_var##_concept _Tp1> \
|
||||
struct _concept_checking##_type_var##_concept { }; \
|
||||
typedef _concept_checking##_type_var##_concept< \
|
||||
&_ns::_concept <_type_var>::__constraints> \
|
||||
_concept_checking_typedef##_type_var##_concept
|
||||
|
||||
#define _GLIBCXX_CLASS_REQUIRES2(_type_var1, _type_var2, _ns, _concept) \
|
||||
typedef void (_ns::_concept <_type_var1,_type_var2>::* _func##_type_var1##_type_var2##_concept)(); \
|
||||
template <_func##_type_var1##_type_var2##_concept _Tp1> \
|
||||
struct _concept_checking##_type_var1##_type_var2##_concept { }; \
|
||||
typedef _concept_checking##_type_var1##_type_var2##_concept< \
|
||||
&_ns::_concept <_type_var1,_type_var2>::__constraints> \
|
||||
_concept_checking_typedef##_type_var1##_type_var2##_concept
|
||||
|
||||
#define _GLIBCXX_CLASS_REQUIRES3(_type_var1, _type_var2, _type_var3, _ns, _concept) \
|
||||
typedef void (_ns::_concept <_type_var1,_type_var2,_type_var3>::* _func##_type_var1##_type_var2##_type_var3##_concept)(); \
|
||||
template <_func##_type_var1##_type_var2##_type_var3##_concept _Tp1> \
|
||||
struct _concept_checking##_type_var1##_type_var2##_type_var3##_concept { }; \
|
||||
typedef _concept_checking##_type_var1##_type_var2##_type_var3##_concept< \
|
||||
&_ns::_concept <_type_var1,_type_var2,_type_var3>::__constraints> \
|
||||
_concept_checking_typedef##_type_var1##_type_var2##_type_var3##_concept
|
||||
|
||||
#define _GLIBCXX_CLASS_REQUIRES4(_type_var1, _type_var2, _type_var3, _type_var4, _ns, _concept) \
|
||||
typedef void (_ns::_concept <_type_var1,_type_var2,_type_var3,_type_var4>::* _func##_type_var1##_type_var2##_type_var3##_type_var4##_concept)(); \
|
||||
template <_func##_type_var1##_type_var2##_type_var3##_type_var4##_concept _Tp1> \
|
||||
struct _concept_checking##_type_var1##_type_var2##_type_var3##_type_var4##_concept { }; \
|
||||
typedef _concept_checking##_type_var1##_type_var2##_type_var3##_type_var4##_concept< \
|
||||
&_ns::_concept <_type_var1,_type_var2,_type_var3,_type_var4>::__constraints> \
|
||||
_concept_checking_typedef##_type_var1##_type_var2##_type_var3##_type_var4##_concept
|
||||
|
||||
|
||||
template <class _Tp1, class _Tp2>
|
||||
struct _Aux_require_same { };
|
||||
|
||||
template <class _Tp>
|
||||
struct _Aux_require_same<_Tp,_Tp> { typedef _Tp _Type; };
|
||||
|
||||
template <class _Tp1, class _Tp2>
|
||||
struct _SameTypeConcept
|
||||
{
|
||||
void __constraints() {
|
||||
typedef typename _Aux_require_same<_Tp1, _Tp2>::_Type _Required;
|
||||
}
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct _IntegerConcept {
|
||||
void __constraints() {
|
||||
__error_type_must_be_an_integer_type();
|
||||
}
|
||||
};
|
||||
template <> struct _IntegerConcept<short> { void __constraints() {} };
|
||||
template <> struct _IntegerConcept<unsigned short> { void __constraints(){} };
|
||||
template <> struct _IntegerConcept<int> { void __constraints() {} };
|
||||
template <> struct _IntegerConcept<unsigned int> { void __constraints() {} };
|
||||
template <> struct _IntegerConcept<long> { void __constraints() {} };
|
||||
template <> struct _IntegerConcept<unsigned long> { void __constraints() {} };
|
||||
template <> struct _IntegerConcept<long long> { void __constraints() {} };
|
||||
template <> struct _IntegerConcept<unsigned long long>
|
||||
{ void __constraints() {} };
|
||||
|
||||
template <class _Tp>
|
||||
struct _SignedIntegerConcept {
|
||||
void __constraints() {
|
||||
__error_type_must_be_a_signed_integer_type();
|
||||
}
|
||||
};
|
||||
template <> struct _SignedIntegerConcept<short> { void __constraints() {} };
|
||||
template <> struct _SignedIntegerConcept<int> { void __constraints() {} };
|
||||
template <> struct _SignedIntegerConcept<long> { void __constraints() {} };
|
||||
template <> struct _SignedIntegerConcept<long long> { void __constraints(){}};
|
||||
|
||||
template <class _Tp>
|
||||
struct _UnsignedIntegerConcept {
|
||||
void __constraints() {
|
||||
__error_type_must_be_an_unsigned_integer_type();
|
||||
}
|
||||
};
|
||||
template <> struct _UnsignedIntegerConcept<unsigned short>
|
||||
{ void __constraints() {} };
|
||||
template <> struct _UnsignedIntegerConcept<unsigned int>
|
||||
{ void __constraints() {} };
|
||||
template <> struct _UnsignedIntegerConcept<unsigned long>
|
||||
{ void __constraints() {} };
|
||||
template <> struct _UnsignedIntegerConcept<unsigned long long>
|
||||
{ void __constraints() {} };
|
||||
|
||||
//===========================================================================
|
||||
// Basic Concepts
|
||||
|
||||
template <class _Tp>
|
||||
struct _DefaultConstructibleConcept
|
||||
{
|
||||
void __constraints() {
|
||||
_Tp __a _IsUnused; // require default constructor
|
||||
}
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct _AssignableConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__a = __a; // require assignment operator
|
||||
__const_constraints(__a);
|
||||
}
|
||||
void __const_constraints(const _Tp& __b) {
|
||||
__a = __b; // const required for argument to assignment
|
||||
}
|
||||
_Tp __a;
|
||||
// possibly should be "Tp* a;" and then dereference "a" in constraint
|
||||
// functions? present way would require a default ctor, i think...
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct _CopyConstructibleConcept
|
||||
{
|
||||
void __constraints() {
|
||||
_Tp __a(__b); // require copy constructor
|
||||
_Tp* __ptr _IsUnused = &__a; // require address of operator
|
||||
__const_constraints(__a);
|
||||
}
|
||||
void __const_constraints(const _Tp& __a) {
|
||||
_Tp __c _IsUnused(__a); // require const copy constructor
|
||||
const _Tp* __ptr _IsUnused = &__a; // require const address of operator
|
||||
}
|
||||
_Tp __b;
|
||||
};
|
||||
|
||||
// The SGI STL version of Assignable requires copy constructor and operator=
|
||||
template <class _Tp>
|
||||
struct _SGIAssignableConcept
|
||||
{
|
||||
void __constraints() {
|
||||
_Tp __b _IsUnused(__a);
|
||||
__a = __a; // require assignment operator
|
||||
__const_constraints(__a);
|
||||
}
|
||||
void __const_constraints(const _Tp& __b) {
|
||||
_Tp __c _IsUnused(__b);
|
||||
__a = __b; // const required for argument to assignment
|
||||
}
|
||||
_Tp __a;
|
||||
};
|
||||
|
||||
template <class _From, class _To>
|
||||
struct _ConvertibleConcept
|
||||
{
|
||||
void __constraints() {
|
||||
_To __y _IsUnused = __x;
|
||||
}
|
||||
_From __x;
|
||||
};
|
||||
|
||||
// The C++ standard requirements for many concepts talk about return
|
||||
// types that must be "convertible to bool". The problem with this
|
||||
// requirement is that it leaves the door open for evil proxies that
|
||||
// define things like operator|| with strange return types. Two
|
||||
// possible solutions are:
|
||||
// 1) require the return type to be exactly bool
|
||||
// 2) stay with convertible to bool, and also
|
||||
// specify stuff about all the logical operators.
|
||||
// For now we just test for convertible to bool.
|
||||
template <class _Tp>
|
||||
void __aux_require_boolean_expr(const _Tp& __t) {
|
||||
bool __x _IsUnused = __t;
|
||||
}
|
||||
|
||||
// FIXME
|
||||
template <class _Tp>
|
||||
struct _EqualityComparableConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__aux_require_boolean_expr(__a == __b);
|
||||
}
|
||||
_Tp __a, __b;
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct _LessThanComparableConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__aux_require_boolean_expr(__a < __b);
|
||||
}
|
||||
_Tp __a, __b;
|
||||
};
|
||||
|
||||
// This is equivalent to SGI STL's LessThanComparable.
|
||||
template <class _Tp>
|
||||
struct _ComparableConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__aux_require_boolean_expr(__a < __b);
|
||||
__aux_require_boolean_expr(__a > __b);
|
||||
__aux_require_boolean_expr(__a <= __b);
|
||||
__aux_require_boolean_expr(__a >= __b);
|
||||
}
|
||||
_Tp __a, __b;
|
||||
};
|
||||
|
||||
#define _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(_OP,_NAME) \
|
||||
template <class _First, class _Second> \
|
||||
struct _NAME { \
|
||||
void __constraints() { (void)__constraints_(); } \
|
||||
bool __constraints_() { \
|
||||
return __a _OP __b; \
|
||||
} \
|
||||
_First __a; \
|
||||
_Second __b; \
|
||||
}
|
||||
|
||||
#define _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(_OP,_NAME) \
|
||||
template <class _Ret, class _First, class _Second> \
|
||||
struct _NAME { \
|
||||
void __constraints() { (void)__constraints_(); } \
|
||||
_Ret __constraints_() { \
|
||||
return __a _OP __b; \
|
||||
} \
|
||||
_First __a; \
|
||||
_Second __b; \
|
||||
}
|
||||
|
||||
_GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, _EqualOpConcept);
|
||||
_GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(!=, _NotEqualOpConcept);
|
||||
_GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<, _LessThanOpConcept);
|
||||
_GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<=, _LessEqualOpConcept);
|
||||
_GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>, _GreaterThanOpConcept);
|
||||
_GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>=, _GreaterEqualOpConcept);
|
||||
|
||||
_GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(+, _PlusOpConcept);
|
||||
_GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(*, _TimesOpConcept);
|
||||
_GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(/, _DivideOpConcept);
|
||||
_GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(-, _SubtractOpConcept);
|
||||
_GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(%, _ModOpConcept);
|
||||
|
||||
#undef _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT
|
||||
#undef _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT
|
||||
|
||||
//===========================================================================
|
||||
// Function Object Concepts
|
||||
|
||||
template <class _Func, class _Return>
|
||||
struct _GeneratorConcept
|
||||
{
|
||||
void __constraints() {
|
||||
const _Return& __r _IsUnused = __f();// require operator() member function
|
||||
}
|
||||
_Func __f;
|
||||
};
|
||||
|
||||
|
||||
template <class _Func>
|
||||
struct _GeneratorConcept<_Func,void>
|
||||
{
|
||||
void __constraints() {
|
||||
__f(); // require operator() member function
|
||||
}
|
||||
_Func __f;
|
||||
};
|
||||
|
||||
template <class _Func, class _Return, class _Arg>
|
||||
struct _UnaryFunctionConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__r = __f(__arg); // require operator()
|
||||
}
|
||||
_Func __f;
|
||||
_Arg __arg;
|
||||
_Return __r;
|
||||
};
|
||||
|
||||
template <class _Func, class _Arg>
|
||||
struct _UnaryFunctionConcept<_Func, void, _Arg> {
|
||||
void __constraints() {
|
||||
__f(__arg); // require operator()
|
||||
}
|
||||
_Func __f;
|
||||
_Arg __arg;
|
||||
};
|
||||
|
||||
template <class _Func, class _Return, class _First, class _Second>
|
||||
struct _BinaryFunctionConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__r = __f(__first, __second); // require operator()
|
||||
}
|
||||
_Func __f;
|
||||
_First __first;
|
||||
_Second __second;
|
||||
_Return __r;
|
||||
};
|
||||
|
||||
template <class _Func, class _First, class _Second>
|
||||
struct _BinaryFunctionConcept<_Func, void, _First, _Second>
|
||||
{
|
||||
void __constraints() {
|
||||
__f(__first, __second); // require operator()
|
||||
}
|
||||
_Func __f;
|
||||
_First __first;
|
||||
_Second __second;
|
||||
};
|
||||
|
||||
template <class _Func, class _Arg>
|
||||
struct _UnaryPredicateConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__aux_require_boolean_expr(__f(__arg)); // require op() returning bool
|
||||
}
|
||||
_Func __f;
|
||||
_Arg __arg;
|
||||
};
|
||||
|
||||
template <class _Func, class _First, class _Second>
|
||||
struct _BinaryPredicateConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__aux_require_boolean_expr(__f(__a, __b)); // require op() returning bool
|
||||
}
|
||||
_Func __f;
|
||||
_First __a;
|
||||
_Second __b;
|
||||
};
|
||||
|
||||
// use this when functor is used inside a container class like std::set
|
||||
template <class _Func, class _First, class _Second>
|
||||
struct _Const_BinaryPredicateConcept {
|
||||
void __constraints() {
|
||||
__const_constraints(__f);
|
||||
}
|
||||
void __const_constraints(const _Func& __fun) {
|
||||
__function_requires<_BinaryPredicateConcept<_Func, _First, _Second> >();
|
||||
// operator() must be a const member function
|
||||
__aux_require_boolean_expr(__fun(__a, __b));
|
||||
}
|
||||
_Func __f;
|
||||
_First __a;
|
||||
_Second __b;
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
// Iterator Concepts
|
||||
|
||||
template <class _Tp>
|
||||
struct _TrivialIteratorConcept
|
||||
{
|
||||
void __constraints() {
|
||||
// __function_requires< _DefaultConstructibleConcept<_Tp> >();
|
||||
__function_requires< _AssignableConcept<_Tp> >();
|
||||
__function_requires< _EqualityComparableConcept<_Tp> >();
|
||||
// typedef typename std::iterator_traits<_Tp>::value_type _V;
|
||||
(void)*__i; // require dereference operator
|
||||
}
|
||||
_Tp __i;
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct _Mutable_TrivialIteratorConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__function_requires< _TrivialIteratorConcept<_Tp> >();
|
||||
*__i = *__j; // require dereference and assignment
|
||||
}
|
||||
_Tp __i, __j;
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct _InputIteratorConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__function_requires< _TrivialIteratorConcept<_Tp> >();
|
||||
// require iterator_traits typedef's
|
||||
typedef typename std::iterator_traits<_Tp>::difference_type _Diff;
|
||||
// __function_requires< _SignedIntegerConcept<_Diff> >();
|
||||
typedef typename std::iterator_traits<_Tp>::reference _Ref;
|
||||
typedef typename std::iterator_traits<_Tp>::pointer _Pt;
|
||||
typedef typename std::iterator_traits<_Tp>::iterator_category _Cat;
|
||||
__function_requires< _ConvertibleConcept<
|
||||
typename std::iterator_traits<_Tp>::iterator_category,
|
||||
std::input_iterator_tag> >();
|
||||
++__i; // require preincrement operator
|
||||
__i++; // require postincrement operator
|
||||
}
|
||||
_Tp __i;
|
||||
};
|
||||
|
||||
template <class _Tp, class _ValueT>
|
||||
struct _OutputIteratorConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__function_requires< _AssignableConcept<_Tp> >();
|
||||
++__i; // require preincrement operator
|
||||
__i++; // require postincrement operator
|
||||
*__i++ = __val(); // require postincrement and assignment
|
||||
}
|
||||
_Tp __i;
|
||||
// Use a function pointer here so no definition of the function needed.
|
||||
// Just need something that returns a _ValueT (which might be a reference).
|
||||
_ValueT (*__val)();
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
struct _Is_vector_bool_iterator
|
||||
{ static const bool __value = false; };
|
||||
|
||||
#ifdef _GLIBCXX_DEBUG
|
||||
namespace __cont = ::std::_GLIBCXX_STD_C;
|
||||
#else
|
||||
namespace __cont = ::std;
|
||||
#endif
|
||||
|
||||
// Trait to identify vector<bool>::iterator
|
||||
template <>
|
||||
struct _Is_vector_bool_iterator<__cont::_Bit_iterator>
|
||||
{ static const bool __value = true; };
|
||||
|
||||
// And for vector<bool>::const_iterator.
|
||||
template <>
|
||||
struct _Is_vector_bool_iterator<__cont::_Bit_const_iterator>
|
||||
{ static const bool __value = true; };
|
||||
|
||||
// And for __gnu_debug::vector<bool> iterators too.
|
||||
template <typename _It, typename _Seq, typename _Tag>
|
||||
struct _Is_vector_bool_iterator<__gnu_debug::_Safe_iterator<_It, _Seq, _Tag> >
|
||||
: _Is_vector_bool_iterator<_It> { };
|
||||
|
||||
template <class _Tp, bool = _Is_vector_bool_iterator<_Tp>::__value>
|
||||
struct _ForwardIteratorReferenceConcept
|
||||
{
|
||||
void __constraints() {
|
||||
#if __cplusplus >= 201103L
|
||||
typedef typename std::iterator_traits<_Tp>::reference _Ref;
|
||||
static_assert(std::is_reference<_Ref>::value,
|
||||
"reference type of a forward iterator must be a real reference");
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template <class _Tp, bool = _Is_vector_bool_iterator<_Tp>::__value>
|
||||
struct _Mutable_ForwardIteratorReferenceConcept
|
||||
{
|
||||
void __constraints() {
|
||||
typedef typename std::iterator_traits<_Tp>::reference _Ref;
|
||||
typedef typename std::iterator_traits<_Tp>::value_type _Val;
|
||||
__function_requires< _SameTypeConcept<_Ref, _Val&> >();
|
||||
}
|
||||
};
|
||||
|
||||
// vector<bool> iterators are not real forward iterators, but we ignore that.
|
||||
template <class _Tp>
|
||||
struct _ForwardIteratorReferenceConcept<_Tp, true>
|
||||
{
|
||||
void __constraints() { }
|
||||
};
|
||||
|
||||
// vector<bool> iterators are not real forward iterators, but we ignore that.
|
||||
template <class _Tp>
|
||||
struct _Mutable_ForwardIteratorReferenceConcept<_Tp, true>
|
||||
{
|
||||
void __constraints() { }
|
||||
};
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
|
||||
template <class _Tp>
|
||||
struct _ForwardIteratorConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__function_requires< _InputIteratorConcept<_Tp> >();
|
||||
__function_requires< _DefaultConstructibleConcept<_Tp> >();
|
||||
__function_requires< _ConvertibleConcept<
|
||||
typename std::iterator_traits<_Tp>::iterator_category,
|
||||
std::forward_iterator_tag> >();
|
||||
__function_requires< _ForwardIteratorReferenceConcept<_Tp> >();
|
||||
_Tp& __j = ++__i;
|
||||
const _Tp& __k = __i++;
|
||||
typedef typename std::iterator_traits<_Tp>::reference _Ref;
|
||||
_Ref __r = *__k;
|
||||
_Ref __r2 = *__i++;
|
||||
}
|
||||
_Tp __i;
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct _Mutable_ForwardIteratorConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__function_requires< _ForwardIteratorConcept<_Tp> >();
|
||||
typedef typename std::iterator_traits<_Tp>::reference _Ref;
|
||||
typedef typename std::iterator_traits<_Tp>::value_type _Val;
|
||||
__function_requires< _Mutable_ForwardIteratorReferenceConcept<_Tp> >();
|
||||
}
|
||||
_Tp __i;
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct _BidirectionalIteratorConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__function_requires< _ForwardIteratorConcept<_Tp> >();
|
||||
__function_requires< _ConvertibleConcept<
|
||||
typename std::iterator_traits<_Tp>::iterator_category,
|
||||
std::bidirectional_iterator_tag> >();
|
||||
_Tp& __j = --__i; // require predecrement operator
|
||||
const _Tp& __k = __i--; // require postdecrement operator
|
||||
typedef typename std::iterator_traits<_Tp>::reference _Ref;
|
||||
_Ref __r = *__j--;
|
||||
}
|
||||
_Tp __i;
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct _Mutable_BidirectionalIteratorConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__function_requires< _BidirectionalIteratorConcept<_Tp> >();
|
||||
__function_requires< _Mutable_ForwardIteratorConcept<_Tp> >();
|
||||
}
|
||||
_Tp __i;
|
||||
};
|
||||
|
||||
|
||||
template <class _Tp>
|
||||
struct _RandomAccessIteratorConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__function_requires< _BidirectionalIteratorConcept<_Tp> >();
|
||||
__function_requires< _ComparableConcept<_Tp> >();
|
||||
__function_requires< _ConvertibleConcept<
|
||||
typename std::iterator_traits<_Tp>::iterator_category,
|
||||
std::random_access_iterator_tag> >();
|
||||
typedef typename std::iterator_traits<_Tp>::reference _Ref;
|
||||
|
||||
_Tp& __j = __i += __n; // require assignment addition operator
|
||||
__i = __i + __n; __i = __n + __i; // require addition with difference type
|
||||
_Tp& __k = __i -= __n; // require assignment subtraction op
|
||||
__i = __i - __n; // require subtraction with
|
||||
// difference type
|
||||
__n = __i - __j; // require difference operator
|
||||
_Ref __r = __i[__n]; // require element access operator
|
||||
}
|
||||
_Tp __a, __b;
|
||||
_Tp __i, __j;
|
||||
typename std::iterator_traits<_Tp>::difference_type __n;
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct _Mutable_RandomAccessIteratorConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__function_requires< _RandomAccessIteratorConcept<_Tp> >();
|
||||
__function_requires< _Mutable_BidirectionalIteratorConcept<_Tp> >();
|
||||
}
|
||||
_Tp __i;
|
||||
typename std::iterator_traits<_Tp>::difference_type __n;
|
||||
};
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
//===========================================================================
|
||||
// Container Concepts
|
||||
|
||||
template <class _Container>
|
||||
struct _ContainerConcept
|
||||
{
|
||||
typedef typename _Container::value_type _Value_type;
|
||||
typedef typename _Container::difference_type _Difference_type;
|
||||
typedef typename _Container::size_type _Size_type;
|
||||
typedef typename _Container::const_reference _Const_reference;
|
||||
typedef typename _Container::const_pointer _Const_pointer;
|
||||
typedef typename _Container::const_iterator _Const_iterator;
|
||||
|
||||
void __constraints() {
|
||||
__function_requires< _InputIteratorConcept<_Const_iterator> >();
|
||||
__function_requires< _AssignableConcept<_Container> >();
|
||||
const _Container __c;
|
||||
__i = __c.begin();
|
||||
__i = __c.end();
|
||||
__n = __c.size();
|
||||
__n = __c.max_size();
|
||||
__b = __c.empty();
|
||||
}
|
||||
bool __b;
|
||||
_Const_iterator __i;
|
||||
_Size_type __n;
|
||||
};
|
||||
|
||||
template <class _Container>
|
||||
struct _Mutable_ContainerConcept
|
||||
{
|
||||
typedef typename _Container::value_type _Value_type;
|
||||
typedef typename _Container::reference _Reference;
|
||||
typedef typename _Container::iterator _Iterator;
|
||||
typedef typename _Container::pointer _Pointer;
|
||||
|
||||
void __constraints() {
|
||||
__function_requires< _ContainerConcept<_Container> >();
|
||||
__function_requires< _AssignableConcept<_Value_type> >();
|
||||
__function_requires< _InputIteratorConcept<_Iterator> >();
|
||||
|
||||
__i = __c.begin();
|
||||
__i = __c.end();
|
||||
__c.swap(__c2);
|
||||
}
|
||||
_Iterator __i;
|
||||
_Container __c, __c2;
|
||||
};
|
||||
|
||||
template <class _ForwardContainer>
|
||||
struct _ForwardContainerConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__function_requires< _ContainerConcept<_ForwardContainer> >();
|
||||
typedef typename _ForwardContainer::const_iterator _Const_iterator;
|
||||
__function_requires< _ForwardIteratorConcept<_Const_iterator> >();
|
||||
}
|
||||
};
|
||||
|
||||
template <class _ForwardContainer>
|
||||
struct _Mutable_ForwardContainerConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__function_requires< _ForwardContainerConcept<_ForwardContainer> >();
|
||||
__function_requires< _Mutable_ContainerConcept<_ForwardContainer> >();
|
||||
typedef typename _ForwardContainer::iterator _Iterator;
|
||||
__function_requires< _Mutable_ForwardIteratorConcept<_Iterator> >();
|
||||
}
|
||||
};
|
||||
|
||||
template <class _ReversibleContainer>
|
||||
struct _ReversibleContainerConcept
|
||||
{
|
||||
typedef typename _ReversibleContainer::const_iterator _Const_iterator;
|
||||
typedef typename _ReversibleContainer::const_reverse_iterator
|
||||
_Const_reverse_iterator;
|
||||
|
||||
void __constraints() {
|
||||
__function_requires< _ForwardContainerConcept<_ReversibleContainer> >();
|
||||
__function_requires< _BidirectionalIteratorConcept<_Const_iterator> >();
|
||||
__function_requires<
|
||||
_BidirectionalIteratorConcept<_Const_reverse_iterator> >();
|
||||
|
||||
const _ReversibleContainer __c;
|
||||
_Const_reverse_iterator __i = __c.rbegin();
|
||||
__i = __c.rend();
|
||||
}
|
||||
};
|
||||
|
||||
template <class _ReversibleContainer>
|
||||
struct _Mutable_ReversibleContainerConcept
|
||||
{
|
||||
typedef typename _ReversibleContainer::iterator _Iterator;
|
||||
typedef typename _ReversibleContainer::reverse_iterator _Reverse_iterator;
|
||||
|
||||
void __constraints() {
|
||||
__function_requires<_ReversibleContainerConcept<_ReversibleContainer> >();
|
||||
__function_requires<
|
||||
_Mutable_ForwardContainerConcept<_ReversibleContainer> >();
|
||||
__function_requires<_Mutable_BidirectionalIteratorConcept<_Iterator> >();
|
||||
__function_requires<
|
||||
_Mutable_BidirectionalIteratorConcept<_Reverse_iterator> >();
|
||||
|
||||
_Reverse_iterator __i = __c.rbegin();
|
||||
__i = __c.rend();
|
||||
}
|
||||
_ReversibleContainer __c;
|
||||
};
|
||||
|
||||
template <class _RandomAccessContainer>
|
||||
struct _RandomAccessContainerConcept
|
||||
{
|
||||
typedef typename _RandomAccessContainer::size_type _Size_type;
|
||||
typedef typename _RandomAccessContainer::const_reference _Const_reference;
|
||||
typedef typename _RandomAccessContainer::const_iterator _Const_iterator;
|
||||
typedef typename _RandomAccessContainer::const_reverse_iterator
|
||||
_Const_reverse_iterator;
|
||||
|
||||
void __constraints() {
|
||||
__function_requires<
|
||||
_ReversibleContainerConcept<_RandomAccessContainer> >();
|
||||
__function_requires< _RandomAccessIteratorConcept<_Const_iterator> >();
|
||||
__function_requires<
|
||||
_RandomAccessIteratorConcept<_Const_reverse_iterator> >();
|
||||
|
||||
const _RandomAccessContainer __c;
|
||||
_Const_reference __r _IsUnused = __c[__n];
|
||||
}
|
||||
_Size_type __n;
|
||||
};
|
||||
|
||||
template <class _RandomAccessContainer>
|
||||
struct _Mutable_RandomAccessContainerConcept
|
||||
{
|
||||
typedef typename _RandomAccessContainer::size_type _Size_type;
|
||||
typedef typename _RandomAccessContainer::reference _Reference;
|
||||
typedef typename _RandomAccessContainer::iterator _Iterator;
|
||||
typedef typename _RandomAccessContainer::reverse_iterator _Reverse_iterator;
|
||||
|
||||
void __constraints() {
|
||||
__function_requires<
|
||||
_RandomAccessContainerConcept<_RandomAccessContainer> >();
|
||||
__function_requires<
|
||||
_Mutable_ReversibleContainerConcept<_RandomAccessContainer> >();
|
||||
__function_requires< _Mutable_RandomAccessIteratorConcept<_Iterator> >();
|
||||
__function_requires<
|
||||
_Mutable_RandomAccessIteratorConcept<_Reverse_iterator> >();
|
||||
|
||||
_Reference __r _IsUnused = __c[__i];
|
||||
}
|
||||
_Size_type __i;
|
||||
_RandomAccessContainer __c;
|
||||
};
|
||||
|
||||
// A Sequence is inherently mutable
|
||||
template <class _Sequence>
|
||||
struct _SequenceConcept
|
||||
{
|
||||
typedef typename _Sequence::reference _Reference;
|
||||
typedef typename _Sequence::const_reference _Const_reference;
|
||||
|
||||
void __constraints() {
|
||||
// Matt Austern's book puts DefaultConstructible here, the C++
|
||||
// standard places it in Container
|
||||
// function_requires< DefaultConstructible<Sequence> >();
|
||||
__function_requires< _Mutable_ForwardContainerConcept<_Sequence> >();
|
||||
__function_requires< _DefaultConstructibleConcept<_Sequence> >();
|
||||
|
||||
_Sequence
|
||||
__c _IsUnused(__n, __t),
|
||||
__c2 _IsUnused(__first, __last);
|
||||
|
||||
__c.insert(__p, __t);
|
||||
__c.insert(__p, __n, __t);
|
||||
__c.insert(__p, __first, __last);
|
||||
|
||||
__c.erase(__p);
|
||||
__c.erase(__p, __q);
|
||||
|
||||
_Reference __r _IsUnused = __c.front();
|
||||
|
||||
__const_constraints(__c);
|
||||
}
|
||||
void __const_constraints(const _Sequence& __c) {
|
||||
_Const_reference __r _IsUnused = __c.front();
|
||||
}
|
||||
typename _Sequence::value_type __t;
|
||||
typename _Sequence::size_type __n;
|
||||
typename _Sequence::value_type *__first, *__last;
|
||||
typename _Sequence::iterator __p, __q;
|
||||
};
|
||||
|
||||
template <class _FrontInsertionSequence>
|
||||
struct _FrontInsertionSequenceConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__function_requires< _SequenceConcept<_FrontInsertionSequence> >();
|
||||
|
||||
__c.push_front(__t);
|
||||
__c.pop_front();
|
||||
}
|
||||
_FrontInsertionSequence __c;
|
||||
typename _FrontInsertionSequence::value_type __t;
|
||||
};
|
||||
|
||||
template <class _BackInsertionSequence>
|
||||
struct _BackInsertionSequenceConcept
|
||||
{
|
||||
typedef typename _BackInsertionSequence::reference _Reference;
|
||||
typedef typename _BackInsertionSequence::const_reference _Const_reference;
|
||||
|
||||
void __constraints() {
|
||||
__function_requires< _SequenceConcept<_BackInsertionSequence> >();
|
||||
|
||||
__c.push_back(__t);
|
||||
__c.pop_back();
|
||||
_Reference __r _IsUnused = __c.back();
|
||||
}
|
||||
void __const_constraints(const _BackInsertionSequence& __c) {
|
||||
_Const_reference __r _IsUnused = __c.back();
|
||||
};
|
||||
_BackInsertionSequence __c;
|
||||
typename _BackInsertionSequence::value_type __t;
|
||||
};
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
#undef _IsUnused
|
||||
|
||||
#endif // _GLIBCXX_BOOST_CONCEPT_CHECK
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright (C) 2007-2024 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/c++0x_warning.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{iosfwd}
|
||||
*/
|
||||
|
||||
#ifndef _CXX0X_WARNING_H
|
||||
#define _CXX0X_WARNING_H 1
|
||||
|
||||
#if __cplusplus < 201103L
|
||||
#error This file requires compiler and library support \
|
||||
for the ISO C++ 2011 standard. This support must be enabled \
|
||||
with the -std=c++11 or -std=gnu++11 compiler options.
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,64 @@
|
||||
// Base to std::allocator -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2004-2024 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/c++allocator.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{memory}
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_CXX_ALLOCATOR_H
|
||||
#define _GLIBCXX_CXX_ALLOCATOR_H 1
|
||||
|
||||
#include <bits/new_allocator.h>
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
namespace std
|
||||
{
|
||||
/**
|
||||
* @brief An alias to the base class for std::allocator.
|
||||
*
|
||||
* Used to set the std::allocator base class to std::__new_allocator.
|
||||
*
|
||||
* @ingroup allocators
|
||||
* @tparam _Tp Type of allocated object.
|
||||
*/
|
||||
template<typename _Tp>
|
||||
using __allocator_base = __new_allocator<_Tp>;
|
||||
}
|
||||
#else
|
||||
// Define __new_allocator as the base class to std::allocator.
|
||||
# define __allocator_base __new_allocator
|
||||
#endif
|
||||
|
||||
#ifndef _GLIBCXX_SANITIZE_STD_ALLOCATOR
|
||||
# if defined(__SANITIZE_ADDRESS__)
|
||||
# define _GLIBCXX_SANITIZE_STD_ALLOCATOR 1
|
||||
# elif defined __has_feature
|
||||
# if __has_feature(address_sanitizer)
|
||||
# define _GLIBCXX_SANITIZE_STD_ALLOCATOR 1
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,57 @@
|
||||
// Underlying io library details -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2000-2024 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/c++io.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{ios}
|
||||
*/
|
||||
|
||||
// c_io_stdio.h - Defines for using "C" stdio.h
|
||||
|
||||
#ifndef _GLIBCXX_CXX_IO_H
|
||||
#define _GLIBCXX_CXX_IO_H 1
|
||||
|
||||
#include <cstdio>
|
||||
#include <bits/gthr.h>
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
#ifdef __GTHREAD_LEGACY_MUTEX_T
|
||||
// The layout of __gthread_mutex_t changed in GCC 13, but libstdc++ doesn't
|
||||
// actually use the basic_filebuf::_M_lock member, so define it consistently
|
||||
// with the old __gthread_mutex_t to avoid an unnecessary layout change:
|
||||
typedef __GTHREAD_LEGACY_MUTEX_T __c_lock;
|
||||
#else
|
||||
typedef __gthread_mutex_t __c_lock;
|
||||
#endif
|
||||
|
||||
// for basic_file.h
|
||||
typedef FILE __c_file;
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,92 @@
|
||||
// Wrapper for underlying C-language localization -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2024 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/c++locale.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{locale}
|
||||
*/
|
||||
|
||||
//
|
||||
// ISO C++ 14882: 22.8 Standard locale categories.
|
||||
//
|
||||
|
||||
// Written by Benjamin Kosnik <bkoz@redhat.com>
|
||||
|
||||
#ifndef _GLIBCXX_CXX_LOCALE_H
|
||||
#define _GLIBCXX_CXX_LOCALE_H 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include <clocale>
|
||||
|
||||
#define _GLIBCXX_NUM_CATEGORIES 0
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
typedef int* __c_locale;
|
||||
|
||||
// Convert numeric value of type double and long double to string and
|
||||
// return length of string. If vsnprintf is available use it, otherwise
|
||||
// fall back to the unsafe vsprintf which, in general, can be dangerous
|
||||
// and should be avoided.
|
||||
inline int
|
||||
__convert_from_v(const __c_locale&, char* __out,
|
||||
const int __size __attribute__((__unused__)),
|
||||
const char* __fmt, ...)
|
||||
{
|
||||
char* __old = std::setlocale(LC_NUMERIC, 0);
|
||||
char* __sav = 0;
|
||||
if (__builtin_strcmp(__old, "C"))
|
||||
{
|
||||
const size_t __len = __builtin_strlen(__old) + 1;
|
||||
__sav = new char[__len];
|
||||
__builtin_memcpy(__sav, __old, __len);
|
||||
std::setlocale(LC_NUMERIC, "C");
|
||||
}
|
||||
|
||||
__builtin_va_list __args;
|
||||
__builtin_va_start(__args, __fmt);
|
||||
|
||||
#if _GLIBCXX_USE_C99_STDIO && !_GLIBCXX_HAVE_BROKEN_VSNPRINTF
|
||||
const int __ret = __builtin_vsnprintf(__out, __size, __fmt, __args);
|
||||
#else
|
||||
const int __ret = __builtin_vsprintf(__out, __fmt, __args);
|
||||
#endif
|
||||
|
||||
__builtin_va_end(__args);
|
||||
|
||||
if (__sav)
|
||||
{
|
||||
std::setlocale(LC_NUMERIC, __sav);
|
||||
delete [] __sav;
|
||||
}
|
||||
return __ret;
|
||||
}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,81 @@
|
||||
// Concept-checking control -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2024 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/concept_check.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{iterator}
|
||||
*/
|
||||
|
||||
#ifndef _CONCEPT_CHECK_H
|
||||
#define _CONCEPT_CHECK_H 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include <bits/c++config.h>
|
||||
|
||||
// All places in libstdc++-v3 where these are used, or /might/ be used, or
|
||||
// don't need to be used, or perhaps /should/ be used, are commented with
|
||||
// "concept requirements" (and maybe some more text). So grep like crazy
|
||||
// if you're looking for additional places to use these.
|
||||
|
||||
// Concept-checking code is off by default unless users turn it on via
|
||||
// configure options or editing c++config.h.
|
||||
// It is not supported for freestanding implementations.
|
||||
|
||||
#if !defined(_GLIBCXX_CONCEPT_CHECKS)
|
||||
|
||||
#define __glibcxx_function_requires(...)
|
||||
#define __glibcxx_class_requires(_a,_b)
|
||||
#define __glibcxx_class_requires2(_a,_b,_c)
|
||||
#define __glibcxx_class_requires3(_a,_b,_c,_d)
|
||||
#define __glibcxx_class_requires4(_a,_b,_c,_d,_e)
|
||||
|
||||
#else // the checks are on
|
||||
|
||||
#include <bits/boost_concept_check.h>
|
||||
|
||||
// Note that the obvious and elegant approach of
|
||||
//
|
||||
//#define glibcxx_function_requires(C) debug::function_requires< debug::C >()
|
||||
//
|
||||
// won't work due to concept templates with more than one parameter, e.g.,
|
||||
// BinaryPredicateConcept. The preprocessor tries to split things up on
|
||||
// the commas in the template argument list. We can't use an inner pair of
|
||||
// parenthesis to hide the commas, because "debug::(Temp<Foo,Bar>)" isn't
|
||||
// a valid instantiation pattern. Thus, we steal a feature from C99.
|
||||
|
||||
#define __glibcxx_function_requires(...) \
|
||||
__gnu_cxx::__function_requires< __gnu_cxx::__VA_ARGS__ >();
|
||||
#define __glibcxx_class_requires(_a,_C) \
|
||||
_GLIBCXX_CLASS_REQUIRES(_a, __gnu_cxx, _C);
|
||||
#define __glibcxx_class_requires2(_a,_b,_C) \
|
||||
_GLIBCXX_CLASS_REQUIRES2(_a, _b, __gnu_cxx, _C);
|
||||
#define __glibcxx_class_requires3(_a,_b,_c,_C) \
|
||||
_GLIBCXX_CLASS_REQUIRES3(_a, _b, _c, __gnu_cxx, _C);
|
||||
#define __glibcxx_class_requires4(_a,_b,_c,_d,_C) \
|
||||
_GLIBCXX_CLASS_REQUIRES4(_a, _b, _c, _d, __gnu_cxx, _C);
|
||||
|
||||
#endif // enable/disable
|
||||
|
||||
#endif // _GLIBCXX_CONCEPT_CHECK
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user