├── .gitignore ├── .travis.yml ├── README.md ├── bin ├── dmd └── rdmd ├── dmd-dscripten.d ├── ldc2.conf ├── rdmd-dscripten.d ├── rt ├── core │ ├── stdc │ │ ├── config.d │ │ ├── errno.d │ │ ├── fenv.d │ │ ├── math.d │ │ ├── stddef.d │ │ ├── stdio.d │ │ ├── stdlib.d │ │ └── time.d │ └── sys │ │ └── posix │ │ ├── stdio.d │ │ ├── sys │ │ └── types.d │ │ └── unistd.d ├── dscripten │ ├── emscripten.d │ ├── memory.d │ ├── standard.d │ ├── test.d │ └── typeinfo.d ├── gc │ ├── config.d │ ├── gcinterface.d │ ├── impl │ │ └── manual │ │ │ └── gc.d │ └── proxy.d ├── mainloop.c ├── object.d ├── rt │ ├── config.d │ ├── deh.d │ ├── dmain2.d │ ├── dwarfeh.d │ ├── invariant_.d │ ├── lifetime.d │ ├── typeinfo │ │ ├── ti_Acdouble.d │ │ ├── ti_Acfloat.d │ │ ├── ti_Acreal.d │ │ ├── ti_Adouble.d │ │ ├── ti_Afloat.d │ │ ├── ti_Ag.d │ │ ├── ti_Aint.d │ │ ├── ti_Along.d │ │ ├── ti_Areal.d │ │ ├── ti_Ashort.d │ │ ├── ti_C.d │ │ ├── ti_byte.d │ │ ├── ti_cdouble.d │ │ ├── ti_cent.d │ │ ├── ti_cfloat.d │ │ ├── ti_char.d │ │ ├── ti_creal.d │ │ ├── ti_dchar.d │ │ ├── ti_delegate.d │ │ ├── ti_double.d │ │ ├── ti_float.d │ │ ├── ti_idouble.d │ │ ├── ti_ifloat.d │ │ ├── ti_int.d │ │ ├── ti_ireal.d │ │ ├── ti_long.d │ │ ├── ti_n.d │ │ ├── ti_ptr.d │ │ ├── ti_real.d │ │ ├── ti_short.d │ │ ├── ti_ubyte.d │ │ ├── ti_ucent.d │ │ ├── ti_uint.d │ │ ├── ti_ulong.d │ │ ├── ti_ushort.d │ │ ├── ti_void.d │ │ └── ti_wchar.d │ └── util │ │ ├── container │ │ ├── array.d │ │ ├── common.d │ │ └── hashtab.d │ │ ├── hash.d │ │ └── typeinfo.d ├── runtime.c ├── std │ ├── ascii.d │ ├── experimental │ │ └── allocator │ │ │ ├── building_blocks │ │ │ └── free_list.d │ │ │ ├── mallocator.d │ │ │ └── package.d │ ├── math.d │ ├── stdio.d │ └── system.d └── stdx │ └── allocator │ ├── mallocator.d │ └── package.d └── test ├── .gitignore ├── run-tests.sh ├── t0001-basic ├── output.exp ├── run-test.sh └── test.d ├── t0002-c ├── output.exp ├── run-test.sh ├── test.c └── test.d ├── t0003-c-types ├── output.exp ├── run-test.sh ├── test.c └── test.d ├── t0004-c-includes ├── output.exp ├── run-test.sh ├── test.c └── test.d ├── t0100-phobos ├── output.exp ├── run-test.sh └── test.d ├── t0101-d-main ├── output.exp ├── run-test.sh └── test.d ├── t0102-writeln ├── output.exp ├── run-test.sh └── test.d ├── t0200-wasm ├── output.exp ├── run-test.sh └── test.d └── test-lib.sh /.gitignore: -------------------------------------------------------------------------------- 1 | /dmd-dscripten 2 | /rdmd-dscripten 3 | *.o 4 | *.bc 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: d 2 | d: dmd-2.076.0 3 | 4 | sudo: false 5 | 6 | install: 7 | # Get the toolchain 8 | # Instead of building it from source, like so: 9 | # - git clone https://github.com/Ace17/dscripten 10 | # - cd dscripten && ./fetch_toolchain 11 | # - cd /tmp && tar Jcvf toolchains.tar.xz --exclude toolchains/emscripten/.git --exclude toolchains/emscripten/tests toolchains 12 | # We get a prebuilt tarball, as building it from source takes VERY long (more than Travis' 60 minutes limit all by itself). 13 | - curl -fsS https://thecybershadow.net/d/toolchains.tar.xz | tar Jxv -C /tmp 14 | 15 | # Initialize and create ~/.emscripten 16 | # Prepend /usr/bin here too, to avoid pyenv bug: https://github.com/pyenv/pyenv/issues/1158 17 | - PATH=/tmp/toolchains/llvm-js/bin:/usr/bin:$PATH /tmp/toolchains/emscripten/emcc --version 18 | 19 | script: 20 | - export DSCRIPTEN_RDMD=$(which rdmd) 21 | - cd test && ./run-tests.sh 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Dscripten Build Tools [![Build Status](https://travis-ci.org/CyberShadow/dscripten-tools.svg?branch=master)](https://travis-ci.org/CyberShadow/dscripten-tools) 2 | ===================== 3 | 4 | These allow using [dscripten](https://github.com/Ace17/dscripten) to 5 | compile D code to JavaScript (asm.js) with typical D workflow (dmd and 6 | rdmd). 7 | 8 | Setup 9 | ----- 10 | 11 | 1. Run dscripten's `fetch_toolchain` script to download, patch and build LDC and Emscripten. 12 | 2. Build the tools in this directory (e.g. `dmd dmd-dscripten.d && dmd rdmd-dscripten.d`). 13 | 3. (Optional) Set up your environment (see the [Configuration](#configuration) section below). 14 | 15 | Usage 16 | ----- 17 | 18 | There are two ways to use this toolchain: 19 | 20 | 1. Invoke the tools directly (e.g. `path/to/rdmd-dscripten --compiler=path/to/dmd-dscripten --build-only worker.d`) 21 | 2. Prepend the `bin` directory to your `PATH`, so that it overrides the standard `dmd` and `rdmd` binaries. 22 | 23 | Because these tools attempt to implement the same command-line interface as dmd/rdmd, the second method can be used with any programs (e.g. build tools, error highlighting in editors) without needing to configure them. For example, Dub can be used to build programs in its `--rdmd` mode. 24 | 25 | In addition to the usual switches and `.d` files, `dmd-dscripten` also understands how to handle `.c`, `.llvm` and `.bc` files on its command line, and will appropriately compile or otherwise include them into the compilation. See the test suite for examples. 26 | 27 | Configuration 28 | ------------- 29 | 30 | The tools read a few environment variables: 31 | 32 | - `DSCRIPTEN_RDMD` - path to real `rdmd` binary (default: `/usr/bin/rdmd`) 33 | - `DSCRIPTEN_TOOLCHAINS` - path to toolchains build by `fetch_toolchain` (default: `/tmp/toolchains`) 34 | - `LLVMJS` - path to Dscripten's LDC (default: `$DSCRIPTEN_TOOLCHAINS/llvm-js`) 35 | - `EMSCRIPTEN` - path to Dscripten's Emscripten (default: `$DSCRIPTEN_TOOLCHAINS/emscripten`) 36 | - `DSCRIPTEN_TOOLS` - path to the root of this repository (default: `thisExePath.dirName` - the directory the tool's executable is in) 37 | 38 | Example 39 | ------- 40 | 41 | ### `worker.html` 42 | 43 | ```html 44 | 45 | 46 | Dscripten WebWorker test 47 | 48 | 49 | 58 | 59 | 60 |
61 | 62 | 63 | ``` 64 | 65 | ### `worker.d` 66 | 67 | ```d 68 | module worker; 69 | 70 | import core.stdc.stdio; 71 | import core.stdc.string; 72 | 73 | import dscripten.standard; 74 | import dscripten.emscripten; 75 | 76 | import ldc.attributes; 77 | 78 | @assumeUsed 79 | extern(C) 80 | void myFunc(char* data, int size) 81 | { 82 | foreach (i; 0..10) 83 | { 84 | char[32] buf; 85 | sprintf(buf.ptr, "Working... %d", i); 86 | workerRespondProvisionally(buf.ptr[0..strlen(buf.ptr)]); 87 | } 88 | workerRespond("Done!"); 89 | } 90 | ``` 91 | 92 | Compile with: 93 | 94 | ```shell 95 | $ rdmd-dscripten --compiler=dmd-dscripten --build-only worker.d 96 | ``` 97 | 98 | This will create `worker.js`. 99 | 100 | For more examples, see [the testsuite](https://github.com/CyberShadow/dscripten-tools/tree/master/test). 101 | -------------------------------------------------------------------------------- /bin/dmd: -------------------------------------------------------------------------------- 1 | ../dmd-dscripten -------------------------------------------------------------------------------- /bin/rdmd: -------------------------------------------------------------------------------- 1 | ../rdmd-dscripten -------------------------------------------------------------------------------- /dmd-dscripten.d: -------------------------------------------------------------------------------- 1 | /** 2 | Simple DMD driver to build programs targeting the dscripten 3 | toolchain. 4 | 5 | https://github.com/Ace17/dscripten 6 | 7 | Currently geared towards "headless" scripts running from a web 8 | worker (output extension is .js only). 9 | **/ 10 | 11 | module dmd_dscripten; 12 | 13 | import core.sys.posix.unistd : isatty; 14 | 15 | import std.algorithm.comparison; 16 | import std.algorithm.iteration; 17 | import std.algorithm.mutation; 18 | import std.algorithm.searching; 19 | import std.array; 20 | import std.digest.digest; 21 | import std.digest.md; 22 | import std.exception; 23 | import std.file; 24 | import std.format; 25 | import std.path; 26 | import std.process; 27 | import std.stdio : stdout, stderr; 28 | 29 | void main(string[] args) 30 | { 31 | bool verbose = args[1..$].canFind("-v") && isatty(stdout.fileno); 32 | if (verbose) stderr.writeln("dmd-dscripten: Args: ", args[1..$]); 33 | 34 | auto toolchainsPath = environment.get("DSCRIPTEN_TOOLCHAINS", "/tmp/toolchains"); 35 | auto llvmJSPath = environment.get("LLVMJS", toolchainsPath.buildPath("llvm-js")); 36 | auto emscriptenPath = environment.get("EMSCRIPTEN", toolchainsPath.buildPath("emscripten")); 37 | auto toolsPath = environment.get("DSCRIPTEN_TOOLS", thisExePath.dirName); 38 | 39 | auto compiler = llvmJSPath.buildPath("bin", "ldmd2"); 40 | auto compilerOpts = args[1..$]; 41 | 42 | void run(string[] args) 43 | { 44 | if (verbose) stderr.writeln("dmd-dscripten: Exec: ", args); 45 | auto result = spawnProcess(args, ["LD_LIBRARY_PATH" : llvmJSPath.buildPath("lib")]).wait(); 46 | enforce(result == 0, "%s exited with status %d".format(args[0].baseName, result)); 47 | } 48 | 49 | compilerOpts = compilerOpts.map!( 50 | opt => opt.skipOver("@") ? readResponseFile(opt) : [opt]).join; 51 | 52 | // Not only are the produced files not (directly) executable, 53 | // -run changes how the command-line is parsed, 54 | // so detect and forbid it explicitly to avoid any possible weird error messages. 55 | enforce(!compilerOpts.canFind("-run"), "Can't use -run with dscripten!"); 56 | 57 | enum objsLink = ".dscripten-objs"; scope(exit) cleanLink(objsLink); 58 | enum rootLink = ".dscripten-root"; scope(exit) cleanLink(rootLink); 59 | 60 | // Include ourselves in the verbose output for rdmd to pick up, 61 | // so that changes in the tools causes a rebuild. 62 | if (compilerOpts.canFind("-v")) 63 | { 64 | stdout.writeln("binary ", toolsPath.buildPath("dmd-dscripten")); 65 | stdout.writeln("binary ", toolsPath.buildPath("rdmd-dscripten")); 66 | } 67 | 68 | // Add runtime to import paths 69 | string objDir, outputFile; 70 | compilerOpts.extract!(opt => opt.startsWith("-of")).each!(opt => outputFile = opt[3..$]); 71 | bool build = compilerOpts.canFind!(arg => !arg.startsWith("-")) && !compilerOpts.canFind("-o-"); 72 | 73 | if (build) 74 | { 75 | enforce(outputFile, "Building with no outputFile?"); 76 | compilerOpts.extract!(opt => opt.startsWith("-od")).each!(opt => objDir = opt[3..$]); 77 | enforce(objDir, "Building with no objDir?"); 78 | 79 | // Ensure the object directory is empty, as we will be globbing it later. 80 | if (objDir.exists && !objDir.dirEntries("*.bc", SpanMode.depth, false).empty) 81 | { 82 | if (objDir.startsWith("/tmp/.rdmd-")) 83 | { 84 | rmdirRecurse(objDir); 85 | mkdir(objDir); 86 | } 87 | else 88 | throw new Exception("Dirty object directory: " ~ objDir); 89 | } 90 | 91 | // rdmd will never add object.d, so add it ourselves 92 | compilerOpts ~= toolsPath.buildPath("rt", "object.d"); 93 | 94 | // Ugly work-around for missing -oq 95 | cleanLink(objsLink); symlink(objDir, objsLink); 96 | cleanLink(rootLink); symlink("/" , rootLink); 97 | 98 | foreach (ref arg; compilerOpts) 99 | if (!arg.startsWith("-") && arg.endsWith(".d") && exists(arg)) 100 | arg = rootLink ~ absolutePath(arg); 101 | 102 | compilerOpts = ["-output-bc", "-od" ~ objsLink, "-op"] ~ compilerOpts; 103 | } 104 | 105 | // Recognize .c / .llvm / .bc files on the command line, and include them in the compilation accordingly. 106 | auto cFiles = compilerOpts.extract!(arg => !arg.startsWith("-") && arg.endsWith(".c")); 107 | auto llvmFiles = compilerOpts.extract!(arg => !arg.startsWith("-") && arg.endsWith(".llvm")); 108 | auto bcFiles = compilerOpts.extract!(arg => !arg.startsWith("-") && arg.endsWith(".bc")); 109 | 110 | // Extract additional emcc options 111 | string[] emccExtra = compilerOpts.extract!((ref arg) => arg.skipOver("--emcc=")); 112 | foreach (opt; compilerOpts.extract!((ref arg) => arg.skipOver("--emcc-s="))) 113 | emccExtra ~= ["-s", opt]; 114 | 115 | bool wasm; 116 | if (compilerOpts.extract!(arg => arg == "--wasm")) 117 | wasm = true; 118 | 119 | if (wasm) 120 | compilerOpts ~= [ 121 | "-disable-loop-vectorization", 122 | ]; 123 | 124 | enum target = "asmjs-unknown-emscripten"; 125 | compilerOpts = [ 126 | "-mtriple=" ~ target, 127 | "-version=dscripten", 128 | "-conf=" ~ toolsPath.buildPath("ldc2.conf"), 129 | "-I" ~ toolsPath.buildPath("rt"), 130 | "-I" ~ llvmJSPath.buildPath("include", "d"), 131 | ] ~ compilerOpts; 132 | 133 | run([compiler] ~ compilerOpts); 134 | 135 | if (compilerOpts.canFind!(opt => opt.among("-h", "--help"))) 136 | { 137 | stderr.writeln(); 138 | stderr.writeln("Additional dmd-dscripten options:"); 139 | stderr.writeln(" --wasm configure for WebAssembly output"); 140 | stderr.writeln(" --emcc=SWITCH pass SWITCH on to emcc's command line"); 141 | stderr.writeln(" --emcc-s=OPTION shorthand for --emcc=-s --emcc=OPTION"); 142 | stderr.writeln(); 143 | stderr.writeln("dmd-dscripten can also accept additional *.c, *.llvm and *.bc files"); 144 | stderr.writeln("to include in the build."); 145 | } 146 | 147 | if (build) 148 | { 149 | auto objFiles = dirEntries(objDir, "*.bc", SpanMode.depth, false).map!(de => de.name).array; 150 | 151 | foreach (cFile; cFiles) 152 | { 153 | auto bcFile = objDir.buildPath("c-" ~ toHexString(md5Of(cFile)) ~ ".bc"); 154 | run([ 155 | emscriptenPath.buildPath("emcc"), 156 | "-c", 157 | cFile, 158 | "-o", bcFile, 159 | // TODO: optimize? 160 | ]); 161 | bcFiles ~= bcFile; 162 | } 163 | 164 | foreach (llvmFile; llvmFiles) 165 | { 166 | auto bcFile = objDir.buildPath("llvm-" ~ toHexString(md5Of(llvmFile)) ~ ".bc"); 167 | run([ 168 | llvmJSPath.buildPath("bin", "llvm-as"), 169 | llvmFile, 170 | "-o=" ~ bcFile, 171 | ]); 172 | bcFiles ~= bcFile; 173 | } 174 | 175 | objFiles ~= bcFiles; 176 | auto linkedObjFile = objDir.buildPath("_all.bc"); 177 | 178 | auto llvmLinker = llvmJSPath.buildPath("bin", "llvm-link"); 179 | 180 | run([llvmLinker] ~ objFiles ~ ["-o=" ~ linkedObjFile]); 181 | 182 | // Maybe call 'opt' to optimize (LTO) here? 183 | 184 | auto emccArgs = [ 185 | emscriptenPath.buildPath("emcc"), 186 | ]; 187 | 188 | // TODO: make this customizable somehow 189 | // It doesn't hurt for any use case, though, just adds some 190 | // WebWorker-specific declarations to the .js output. 191 | if (true) 192 | emccArgs ~= [ 193 | "-s", "BUILD_AS_WORKER=1", 194 | ]; 195 | 196 | bool optimize; 197 | 198 | if (compilerOpts.canFind("-O")) 199 | optimize = true; 200 | 201 | if (wasm) 202 | { 203 | // Works around error: 204 | // failed to asynchronously prepare wasm: LinkError: 205 | // WebAssembly Instantiation: Import #6 module="env" 206 | // function="core.cpuid.__ModuleInfo" error: global import 207 | // must be a number 208 | optimize = true; 209 | } 210 | 211 | if (optimize) 212 | emccArgs ~= "-O3"; 213 | 214 | emccArgs ~= [ 215 | "--memory-init-file", "0", 216 | "--target=" ~ target, 217 | "-S", 218 | "-w", linkedObjFile, 219 | "-o", outputFile ~ ".js", 220 | ]; 221 | 222 | if (wasm) 223 | emccArgs ~= ["-s", "WASM=1"]; 224 | 225 | emccArgs ~= emccExtra; 226 | 227 | run(emccArgs); 228 | if (exists(outputFile ~ ".js")) 229 | rename(outputFile ~ ".js", outputFile); 230 | } 231 | } 232 | 233 | /// Remove and return all elements of `arr` matching `pred`. 234 | string[] extract(alias pred)(ref string[] arr) 235 | { 236 | string[] result; 237 | size_t i = 0; 238 | while (i < arr.length) 239 | { 240 | auto e = arr[i]; 241 | if (pred(e)) 242 | { 243 | result ~= e; 244 | arr = arr.remove(i); 245 | } 246 | else 247 | i++; 248 | } 249 | return result; 250 | } 251 | 252 | void cleanLink(string link) 253 | { 254 | try 255 | remove(link); 256 | catch (Exception) {} 257 | } 258 | 259 | string[] readResponseFile(string fileName) 260 | { 261 | auto s = fileName.readText; 262 | string[] result; 263 | string arg; 264 | bool inQuote, backslash; 265 | foreach (c; s) 266 | { 267 | if (backslash) 268 | { 269 | arg ~= c; 270 | backslash = false; 271 | } 272 | else 273 | if (c == '\\') 274 | backslash = true; 275 | else 276 | if (c == '"') 277 | inQuote = !inQuote; 278 | else 279 | if ((c == ' ' || c == '\r' || c == '\n') && !inQuote) 280 | { 281 | if (arg.length) 282 | result ~= arg; 283 | arg = null; 284 | } 285 | else 286 | arg ~= c; 287 | } 288 | if (arg.length) 289 | result ~= arg; 290 | return result; 291 | } 292 | -------------------------------------------------------------------------------- /ldc2.conf: -------------------------------------------------------------------------------- 1 | default: 2 | { 3 | switches = []; 4 | }; 5 | -------------------------------------------------------------------------------- /rdmd-dscripten.d: -------------------------------------------------------------------------------- 1 | /** 2 | Simple rdmd wrapper to build programs targeting the dscripten 3 | toolchain. 4 | 5 | https://github.com/Ace17/dscripten 6 | 7 | Currently geared towards "headless" scripts running from a web 8 | worker (output extension is .js only). 9 | **/ 10 | 11 | module rdmd_dscripten; 12 | 13 | import std.algorithm.searching; 14 | import std.path; 15 | import std.process; 16 | import std.range.primitives; 17 | import std.stdio; 18 | 19 | void main(string[] args) 20 | { 21 | bool verbose = args[1..$].canFind("--chatty"); 22 | if (verbose) stderr.writeln("rdmd-dscripten: Args: ", args[1..$]); 23 | 24 | auto realRDMD = environment.get("DSCRIPTEN_RDMD", "/usr/bin/rdmd"); 25 | 26 | auto rdmdOpts = args[1..$]; 27 | 28 | // Force .js file extension. 29 | // rdmd can't figure it out otherwise. 30 | auto nonOptions = args[1..$].find!(arg => !arg.startsWith("-")); 31 | if (!nonOptions.empty) 32 | { 33 | auto mainFile = nonOptions.front; 34 | auto jsFile = mainFile.setExtension(".js"); 35 | rdmdOpts = ["-of" ~ jsFile] ~ rdmdOpts; 36 | } 37 | 38 | // Compile code in Druntime/Phobos modules. 39 | // Needed to use non-templated functions/types. 40 | // Normally, they are in libphobos.a or such, but there is no 41 | // equivalent in our case. 42 | // If necessary, this can be canceled out again by using --exclude 43 | // on this rdmd's command line. 44 | rdmdOpts = [ 45 | "--include=std", 46 | "--include=etc", 47 | "--include=core", 48 | ] ~ rdmdOpts; 49 | 50 | auto cmdLine = [realRDMD] ~ rdmdOpts; 51 | if (verbose) stderr.writeln("rdmd-dscripten: Exec: ", cmdLine); 52 | execv(cmdLine[0], cmdLine); 53 | throw new Exception("Failed to exec into " ~ realRDMD); 54 | } 55 | -------------------------------------------------------------------------------- /rt/core/stdc/config.d: -------------------------------------------------------------------------------- 1 | /** 2 | * D header file for C99. 3 | * 4 | * Copyright: Copyright Sean Kelly 2005 - 2009. 5 | * License: Distributed under the 6 | * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0). 7 | * (See accompanying file LICENSE) 8 | * Authors: Sean Kelly 9 | * Source: $(DRUNTIMESRC core/stdc/_config.d) 10 | * Standards: ISO/IEC 9899:1999 (E) 11 | */ 12 | 13 | module core.stdc.config; 14 | 15 | version (OSX) 16 | version = Darwin; 17 | else version (iOS) 18 | version = Darwin; 19 | else version (TVOS) 20 | version = Darwin; 21 | else version (WatchOS) 22 | version = Darwin; 23 | 24 | extern (C): 25 | @trusted: // Types only. 26 | nothrow: 27 | @nogc: 28 | 29 | version( Windows ) 30 | { 31 | struct __c_long 32 | { 33 | pure nothrow @nogc @safe: 34 | this(int x) { lng = x; } 35 | int lng; 36 | alias lng this; 37 | } 38 | 39 | struct __c_ulong 40 | { 41 | pure nothrow @nogc @safe: 42 | this(uint x) { lng = x; } 43 | uint lng; 44 | alias lng this; 45 | } 46 | 47 | /* 48 | * This is cpp_long instead of c_long because: 49 | * 1. Implicit casting of an int to __c_long doesn't happen, because D doesn't 50 | * allow constructor calls in implicit conversions. 51 | * 2. long lng; 52 | * cast(__c_long)lng; 53 | * does not work because lng has to be implicitly cast to an int in the constructor, 54 | * and since that truncates it is not done. 55 | * Both of these break existing code, so until we find a resolution the types are named 56 | * cpp_xxxx. 57 | */ 58 | 59 | alias __c_long cpp_long; 60 | alias __c_ulong cpp_ulong; 61 | 62 | alias int c_long; 63 | alias uint c_ulong; 64 | } 65 | else version( Posix ) 66 | { 67 | static if( (void*).sizeof > int.sizeof ) 68 | { 69 | alias long c_long; 70 | alias ulong c_ulong; 71 | } 72 | else 73 | { 74 | struct __c_long 75 | { 76 | pure nothrow @nogc @safe: 77 | this(int x) { lng = x; } 78 | int lng; 79 | alias lng this; 80 | } 81 | 82 | struct __c_ulong 83 | { 84 | pure nothrow @nogc @safe: 85 | this(uint x) { lng = x; } 86 | uint lng; 87 | alias lng this; 88 | } 89 | 90 | alias __c_long cpp_long; 91 | alias __c_ulong cpp_ulong; 92 | 93 | alias int c_long; 94 | alias uint c_ulong; 95 | } 96 | } 97 | else version( dscripten ) 98 | { 99 | alias int c_long; 100 | alias uint c_ulong; 101 | } 102 | 103 | version( CRuntime_Microsoft ) 104 | { 105 | /* long double is 64 bits, not 80 bits, but is mangled differently 106 | * than double. To distinguish double from long double, create a wrapper to represent 107 | * long double, then recognize that wrapper specially in the compiler 108 | * to generate the correct name mangling and correct function call/return 109 | * ABI conformance. 110 | */ 111 | struct __c_long_double 112 | { 113 | pure nothrow @nogc @safe: 114 | this(double d) { ld = d; } 115 | double ld; 116 | alias ld this; 117 | } 118 | 119 | alias __c_long_double c_long_double; 120 | } 121 | else version( DigitalMars ) 122 | { 123 | version( X86 ) 124 | { 125 | alias real c_long_double; 126 | } 127 | else version( X86_64 ) 128 | { 129 | version( linux ) 130 | alias real c_long_double; 131 | else version( FreeBSD ) 132 | alias real c_long_double; 133 | else version( OpenBSD ) 134 | alias real c_long_double; 135 | else version( NetBSD ) 136 | alias real c_long_double; 137 | else version( Solaris ) 138 | alias real c_long_double; 139 | else version( Darwin ) 140 | alias real c_long_double; 141 | } 142 | } 143 | else version( GNU ) 144 | alias real c_long_double; 145 | else version( LDC ) 146 | alias real c_long_double; 147 | else version( SDC ) 148 | { 149 | version( X86 ) 150 | alias real c_long_double; 151 | else version( X86_64 ) 152 | alias real c_long_double; 153 | } 154 | 155 | static assert(is(c_long_double), "c_long_double needs to be declared for this platform/architecture."); 156 | -------------------------------------------------------------------------------- /rt/core/stdc/stddef.d: -------------------------------------------------------------------------------- 1 | /** 2 | * D header file for C99. 3 | * 4 | * $(C_HEADER_DESCRIPTION pubs.opengroup.org/onlinepubs/009695399/basedefs/_stddef.h.html, _stddef.h) 5 | * 6 | * Copyright: Copyright Sean Kelly 2005 - 2009. 7 | * License: Distributed under the 8 | * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0). 9 | * (See accompanying file LICENSE) 10 | * Authors: Sean Kelly 11 | * Source: $(DRUNTIMESRC core/stdc/_stddef.d) 12 | * Standards: ISO/IEC 9899:1999 (E) 13 | */ 14 | 15 | module core.stdc.stddef; 16 | 17 | extern (C): 18 | @trusted: // Types only. 19 | nothrow: 20 | @nogc: 21 | 22 | // size_t and ptrdiff_t are defined in the object module. 23 | 24 | version( Windows ) 25 | { 26 | /// 27 | alias wchar wchar_t; 28 | } 29 | else version( Posix ) 30 | { 31 | /// 32 | alias dchar wchar_t; 33 | } 34 | else version( dscripten ) 35 | { 36 | alias dchar wchar_t; 37 | } 38 | -------------------------------------------------------------------------------- /rt/core/stdc/stdlib.d: -------------------------------------------------------------------------------- 1 | /** 2 | * D header file for C99. 3 | * 4 | * $(C_HEADER_DESCRIPTION pubs.opengroup.org/onlinepubs/009695399/basedefs/_stdlib.h.html, _stdlib.h) 5 | * 6 | * Copyright: Copyright Sean Kelly 2005 - 2014. 7 | * License: Distributed under the 8 | * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0). 9 | * (See accompanying file LICENSE) 10 | * Authors: Sean Kelly 11 | * Standards: ISO/IEC 9899:1999 (E) 12 | * Source: $(DRUNTIMESRC src/core/stdc/_stdlib.d) 13 | */ 14 | 15 | module core.stdc.stdlib; 16 | 17 | private import core.stdc.config; 18 | public import core.stdc.stddef; // for wchar_t 19 | 20 | version (OSX) 21 | version = Darwin; 22 | else version (iOS) 23 | version = Darwin; 24 | else version (TVOS) 25 | version = Darwin; 26 | else version (WatchOS) 27 | version = Darwin; 28 | 29 | extern (C): 30 | @system: 31 | 32 | /* Placed outside @nogc in order to not constrain what the callback does. 33 | */ 34 | /// 35 | alias int function(scope const void*, scope const void*) _compare_fp_t; 36 | /// 37 | inout(void)* bsearch(scope const void* key, scope inout(void)* base, size_t nmemb, size_t size, _compare_fp_t compar); 38 | /// 39 | void qsort(scope void* base, size_t nmemb, size_t size, _compare_fp_t compar); 40 | 41 | 42 | nothrow: 43 | @nogc: 44 | 45 | /// 46 | struct div_t 47 | { 48 | int quot, 49 | rem; 50 | } 51 | 52 | /// 53 | struct ldiv_t 54 | { 55 | int quot, 56 | rem; 57 | } 58 | 59 | /// 60 | struct lldiv_t 61 | { 62 | long quot, 63 | rem; 64 | } 65 | 66 | /// 67 | enum EXIT_SUCCESS = 0; 68 | /// 69 | enum EXIT_FAILURE = 1; 70 | /// 71 | enum MB_CUR_MAX = 1; 72 | 73 | /// 74 | version(Windows) enum RAND_MAX = 0x7fff; 75 | else version(CRuntime_Glibc) enum RAND_MAX = 0x7fffffff; 76 | else version(Darwin) enum RAND_MAX = 0x7fffffff; 77 | else version(FreeBSD) enum RAND_MAX = 0x7fffffff; 78 | else version(NetBSD) enum RAND_MAX = 0x7fffffff; 79 | else version(OpenBSD) enum RAND_MAX = 0x7fffffff; 80 | else version(Solaris) enum RAND_MAX = 0x7fff; 81 | else version(CRuntime_Bionic) enum RAND_MAX = 0x7fffffff; 82 | else version(dscripten) enum RAND_MAX = 0x7fffffff; // TODO! 83 | else static assert( false, "Unsupported platform" ); 84 | 85 | /// 86 | double atof(scope const char* nptr); 87 | /// 88 | int atoi(scope const char* nptr); 89 | /// 90 | c_long atol(scope const char* nptr); 91 | /// 92 | long atoll(scope const char* nptr); 93 | 94 | /// 95 | double strtod(scope inout(char)* nptr, scope inout(char)** endptr); 96 | /// 97 | float strtof(scope inout(char)* nptr, scope inout(char)** endptr); 98 | /// 99 | c_long strtol(scope inout(char)* nptr, scope inout(char)** endptr, int base); 100 | /// 101 | long strtoll(scope inout(char)* nptr, scope inout(char)** endptr, int base); 102 | /// 103 | c_ulong strtoul(scope inout(char)* nptr, scope inout(char)** endptr, int base); 104 | /// 105 | ulong strtoull(scope inout(char)* nptr, scope inout(char)** endptr, int base); 106 | 107 | version (CRuntime_Microsoft) 108 | { 109 | // strtold exists starting from VS2013, so we give it D linkage to avoid link errors 110 | /// 111 | extern (D) real strtold(scope inout(char)* nptr, inout(char)** endptr) 112 | { // Fake it 'till we make it 113 | return strtod(nptr, endptr); 114 | } 115 | } 116 | else version (MinGW) 117 | { 118 | /// 119 | real __mingw_strtold(scope inout(char)* nptr, scope inout(char)** endptr); 120 | /// 121 | alias __mingw_strtold strtold; 122 | } 123 | else version (CRuntime_Bionic) 124 | { 125 | /// 126 | real strtold(scope inout(char)* nptr, scope inout(char)** endptr) 127 | { // Fake it again till we make it 128 | return strtod(nptr, endptr); 129 | } 130 | } 131 | else 132 | { 133 | /// 134 | real strtold(scope inout(char)* nptr, scope inout(char)** endptr); 135 | } 136 | 137 | // No unsafe pointer manipulation. 138 | @trusted 139 | { 140 | version(CRuntime_Bionic) 141 | { 142 | import core.sys.posix.stdlib: lrand48, srand48; 143 | /// 144 | alias core.sys.posix.stdlib.lrand48 rand; 145 | /// 146 | alias core.sys.posix.stdlib.srand48 srand; 147 | } 148 | else 149 | { 150 | /// 151 | int rand(); 152 | /// 153 | void srand(uint seed); 154 | } 155 | } 156 | 157 | // We don't mark these @trusted. Given that they return a void*, one has 158 | // to do a pointer cast to do anything sensible with the result. Thus, 159 | // functions using these already have to be @trusted, allowing them to 160 | // call @system stuff anyway. 161 | /// 162 | void* malloc(size_t size); 163 | /// 164 | void* calloc(size_t nmemb, size_t size); 165 | /// 166 | void* realloc(void* ptr, size_t size); 167 | /// 168 | void free(void* ptr); 169 | 170 | /// 171 | void abort() @safe; 172 | /// 173 | void exit(int status); 174 | /// 175 | int atexit(void function() func); 176 | /// 177 | void _Exit(int status); 178 | 179 | /// 180 | char* getenv(scope const char* name); 181 | /// 182 | int system(scope const char* string); 183 | 184 | // These only operate on integer values. 185 | @trusted 186 | { 187 | /// 188 | pure int abs(int j); 189 | /// 190 | pure c_long labs(c_long j); 191 | /// 192 | pure long llabs(long j); 193 | 194 | /// 195 | div_t div(int numer, int denom); 196 | /// 197 | ldiv_t ldiv(c_long numer, c_long denom); 198 | /// 199 | lldiv_t lldiv(long numer, long denom); 200 | } 201 | 202 | /// 203 | int mblen(scope const char* s, size_t n); 204 | /// 205 | int mbtowc(scope wchar_t* pwc, scope const char* s, size_t n); 206 | /// 207 | int wctomb(scope char* s, wchar_t wc); 208 | /// 209 | size_t mbstowcs(scope wchar_t* pwcs, scope const char* s, size_t n); 210 | /// 211 | size_t wcstombs(scope char* s, scope const wchar_t* pwcs, size_t n); 212 | 213 | /// 214 | version( DigitalMars ) 215 | { 216 | // See malloc comment about @trusted. 217 | void* alloca(size_t size) pure; // non-standard 218 | } 219 | else version( GNU ) 220 | { 221 | void* alloca(size_t size) pure; // compiler intrinsic 222 | } 223 | else version( LDC ) 224 | { 225 | pragma(LDC_alloca) 226 | void* alloca(size_t size) pure; 227 | } 228 | 229 | version( CRuntime_Microsoft ) 230 | { 231 | /// 232 | ulong _strtoui64(scope inout(char)*, scope inout(char)**,int); 233 | /// 234 | ulong _wcstoui64(scope inout(wchar)*, scope inout(wchar)**,int); 235 | 236 | /// 237 | long _strtoi64(scope inout(char)*, scope inout(char)**,int); 238 | /// 239 | long _wcstoi64(scope inout(wchar)*, scope inout(wchar)**,int); 240 | } 241 | -------------------------------------------------------------------------------- /rt/core/stdc/time.d: -------------------------------------------------------------------------------- 1 | /** 2 | * D header file for C99. 3 | * 4 | * $(C_HEADER_DESCRIPTION pubs.opengroup.org/onlinepubs/009695399/basedefs/_time.h.html, _time.h) 5 | * 6 | * Copyright: Copyright Sean Kelly 2005 - 2009. 7 | * License: Distributed under the 8 | * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0). 9 | * (See accompanying file LICENSE) 10 | * Authors: Sean Kelly, 11 | * Alex Rønne Petersen 12 | * Source: $(DRUNTIMESRC core/stdc/_time.d) 13 | * Standards: ISO/IEC 9899:1999 (E) 14 | */ 15 | 16 | module core.stdc.time; 17 | 18 | private import core.stdc.config; 19 | 20 | version (OSX) 21 | version = Darwin; 22 | else version (iOS) 23 | version = Darwin; 24 | else version (TVOS) 25 | version = Darwin; 26 | else version (WatchOS) 27 | version = Darwin; 28 | 29 | extern (C): 30 | @trusted: // There are only a few functions here that use unsafe C strings. 31 | nothrow: 32 | @nogc: 33 | 34 | version( Windows ) 35 | { 36 | /// 37 | struct tm 38 | { 39 | int tm_sec; /// seconds after the minute - [0, 60] 40 | int tm_min; /// minutes after the hour - [0, 59] 41 | int tm_hour; /// hours since midnight - [0, 23] 42 | int tm_mday; /// day of the month - [1, 31] 43 | int tm_mon; /// months since January - [0, 11] 44 | int tm_year; /// years since 1900 45 | int tm_wday; /// days since Sunday - [0, 6] 46 | int tm_yday; /// days since January 1 - [0, 365] 47 | int tm_isdst; /// Daylight Saving Time flag 48 | } 49 | } 50 | else version( Posix ) 51 | { 52 | /// 53 | struct tm 54 | { 55 | int tm_sec; /// seconds after the minute [0-60] 56 | int tm_min; /// minutes after the hour [0-59] 57 | int tm_hour; /// hours since midnight [0-23] 58 | int tm_mday; /// day of the month [1-31] 59 | int tm_mon; /// months since January [0-11] 60 | int tm_year; /// years since 1900 61 | int tm_wday; /// days since Sunday [0-6] 62 | int tm_yday; /// days since January 1 [0-365] 63 | int tm_isdst; /// Daylight Savings Time flag 64 | c_long tm_gmtoff; /// offset from CUT in seconds 65 | char* tm_zone; /// timezone abbreviation 66 | } 67 | } 68 | else version( dscripten ) 69 | { 70 | // TODO 71 | struct tm 72 | { 73 | int tm_sec; /// seconds after the minute [0-60] 74 | int tm_min; /// minutes after the hour [0-59] 75 | int tm_hour; /// hours since midnight [0-23] 76 | int tm_mday; /// day of the month [1-31] 77 | int tm_mon; /// months since January [0-11] 78 | int tm_year; /// years since 1900 79 | int tm_wday; /// days since Sunday [0-6] 80 | int tm_yday; /// days since January 1 [0-365] 81 | int tm_isdst; /// Daylight Savings Time flag 82 | } 83 | } 84 | 85 | version ( Posix ) 86 | { 87 | public import core.sys.posix.sys.types : time_t, clock_t; 88 | } 89 | else version ( Windows ) 90 | { 91 | /// 92 | alias c_long time_t; 93 | /// 94 | alias c_long clock_t; 95 | } 96 | else version ( dscripten ) 97 | { 98 | alias int time_t; // TODO 99 | alias int clock_t; // TODO 100 | } 101 | 102 | /// 103 | version( Windows ) 104 | { 105 | enum clock_t CLOCKS_PER_SEC = 1000; 106 | } 107 | else version( OSX ) 108 | { 109 | enum clock_t CLOCKS_PER_SEC = 100; 110 | } 111 | else version( Darwin ) // other Darwins (iOS, TVOS, WatchOS) 112 | { 113 | enum clock_t CLOCKS_PER_SEC = 1_000_000; 114 | } 115 | else version( FreeBSD ) 116 | { 117 | enum clock_t CLOCKS_PER_SEC = 128; 118 | } 119 | else version( NetBSD ) 120 | { 121 | enum clock_t CLOCKS_PER_SEC = 100; 122 | } 123 | else version( OpenBSD ) 124 | { 125 | enum clock_t CLOCKS_PER_SEC = 100; 126 | } 127 | else version (CRuntime_Glibc) 128 | { 129 | enum clock_t CLOCKS_PER_SEC = 1_000_000; 130 | } 131 | else version (CRuntime_Bionic) 132 | { 133 | enum clock_t CLOCKS_PER_SEC = 1_000_000; 134 | } 135 | 136 | /// 137 | clock_t clock(); 138 | /// 139 | double difftime(time_t time1, time_t time0); 140 | /// 141 | time_t mktime(tm* timeptr); 142 | /// 143 | time_t time(time_t* timer); 144 | /// 145 | char* asctime(in tm* timeptr); 146 | /// 147 | char* ctime(in time_t* timer); 148 | /// 149 | tm* gmtime(in time_t* timer); 150 | /// 151 | tm* localtime(in time_t* timer); 152 | /// 153 | @system size_t strftime(char* s, size_t maxsize, in char* format, in tm* timeptr); 154 | 155 | version( Windows ) 156 | { 157 | /// 158 | void tzset(); // non-standard 159 | /// 160 | void _tzset(); // non-standard 161 | /// 162 | @system char* _strdate(char* s); // non-standard 163 | /// 164 | @system char* _strtime(char* s); // non-standard 165 | 166 | /// 167 | extern __gshared const(char)*[2] tzname; // non-standard 168 | } 169 | else version( Darwin ) 170 | { 171 | /// 172 | void tzset(); // non-standard 173 | /// 174 | extern __gshared const(char)*[2] tzname; // non-standard 175 | } 176 | else version( CRuntime_Glibc ) 177 | { 178 | /// 179 | void tzset(); // non-standard 180 | /// 181 | extern __gshared const(char)*[2] tzname; // non-standard 182 | } 183 | else version( FreeBSD ) 184 | { 185 | /// 186 | void tzset(); // non-standard 187 | /// 188 | extern __gshared const(char)*[2] tzname; // non-standard 189 | } 190 | else version( NetBSD ) 191 | { 192 | /// 193 | void tzset(); // non-standard 194 | /// 195 | extern __gshared const(char)*[2] tzname; // non-standard 196 | } 197 | else version( OpenBSD ) 198 | { 199 | /// 200 | void tzset(); // non-standard 201 | /// 202 | extern __gshared const(char)*[2] tzname; // non-standard 203 | } 204 | else version (Solaris) 205 | { 206 | /// 207 | void tzset(); 208 | /// 209 | extern __gshared const(char)*[2] tzname; 210 | } 211 | else version( CRuntime_Bionic ) 212 | { 213 | /// 214 | void tzset(); 215 | /// 216 | extern __gshared const(char)*[2] tzname; 217 | } 218 | else version( dscripten ) 219 | { 220 | } 221 | else 222 | { 223 | static assert(false, "Unsupported platform"); 224 | } 225 | -------------------------------------------------------------------------------- /rt/core/sys/posix/stdio.d: -------------------------------------------------------------------------------- 1 | /** 2 | * D header file for POSIX. 3 | * 4 | * Copyright: Copyright Sean Kelly 2005 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Sean Kelly 7 | * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition 8 | */ 9 | 10 | /* Copyright Sean Kelly 2005 - 2009. 11 | * Distributed under the Boost Software License, Version 1.0. 12 | * (See accompanying file LICENSE or copy at 13 | * http://www.boost.org/LICENSE_1_0.txt) 14 | */ 15 | module core.sys.posix.stdio; 16 | 17 | private import core.sys.posix.config; 18 | public import core.stdc.stdio; 19 | public import core.sys.posix.sys.types; // for off_t 20 | 21 | version (OSX) 22 | version = Darwin; 23 | else version (iOS) 24 | version = Darwin; 25 | else version (TVOS) 26 | version = Darwin; 27 | else version (WatchOS) 28 | version = Darwin; 29 | 30 | version (Posix) 31 | version = Posixish; 32 | else 33 | version (dscripten) 34 | version = Posixish; 35 | 36 | version (Posixish): 37 | extern (C): 38 | 39 | nothrow: 40 | @nogc: 41 | 42 | // 43 | // Required (defined in core.stdc.stdio) 44 | // 45 | /* 46 | BUFSIZ 47 | _IOFBF 48 | _IOLBF 49 | _IONBF 50 | L_tmpnam 51 | SEEK_CUR 52 | SEEK_END 53 | SEEK_SET 54 | FILENAME_MAX 55 | FOPEN_MAX 56 | TMP_MAX 57 | EOF 58 | NULL 59 | stderr 60 | stdin 61 | stdout 62 | FILE 63 | fpos_t 64 | size_t 65 | 66 | void clearerr(FILE*); 67 | int fclose(FILE*); 68 | int feof(FILE*); 69 | int ferror(FILE*); 70 | int fflush(FILE*); 71 | int fgetc(FILE*); 72 | int fgetpos(FILE*, fpos_t *); 73 | char* fgets(char*, int, FILE*); 74 | FILE* fopen(in char*, in char*); 75 | int fprintf(FILE*, in char*, ...); 76 | int fputc(int, FILE*); 77 | int fputs(in char*, FILE*); 78 | size_t fread(void *, size_t, size_t, FILE*); 79 | FILE* freopen(in char*, in char*, FILE*); 80 | int fscanf(FILE*, in char*, ...); 81 | int fseek(FILE*, c_long, int); 82 | int fsetpos(FILE*, in fpos_t*); 83 | c_long ftell(FILE*); 84 | size_t fwrite(in void *, size_t, size_t, FILE*); 85 | int getc(FILE*); 86 | int getchar(); 87 | char* gets(char*); 88 | void perror(in char*); 89 | int printf(in char*, ...); 90 | int putc(int, FILE*); 91 | int putchar(int); 92 | int puts(in char*); 93 | int remove(in char*); 94 | int rename(in char*, in char*); 95 | void rewind(FILE*); 96 | int scanf(in char*, ...); 97 | void setbuf(FILE*, char*); 98 | int setvbuf(FILE*, char*, int, size_t); 99 | int snprintf(char*, size_t, in char*, ...); 100 | int sprintf(char*, in char*, ...); 101 | int sscanf(in char*, in char*, int ...); 102 | FILE* tmpfile(); 103 | char* tmpnam(char*); 104 | int ungetc(int, FILE*); 105 | int vfprintf(FILE*, in char*, va_list); 106 | int vfscanf(FILE*, in char*, va_list); 107 | int vprintf(in char*, va_list); 108 | int vscanf(in char*, va_list); 109 | int vsnprintf(char*, size_t, in char*, va_list); 110 | int vsprintf(char*, in char*, va_list); 111 | int vsscanf(in char*, in char*, va_list arg); 112 | */ 113 | 114 | version( CRuntime_Glibc ) 115 | { 116 | /* 117 | * actually, if __USE_FILE_OFFSET64 && !_LARGEFILE64_SOURCE 118 | * the *64 functions shouldn't be visible, but the aliases should 119 | * still be supported 120 | */ 121 | static if( __USE_FILE_OFFSET64 ) 122 | { 123 | int fgetpos64(FILE*, fpos_t *); 124 | alias fgetpos64 fgetpos; 125 | 126 | FILE* fopen64(in char*, in char*); 127 | alias fopen64 fopen; 128 | 129 | FILE* freopen64(in char*, in char*, FILE*); 130 | alias freopen64 freopen; 131 | 132 | int fseek(FILE*, c_long, int); 133 | 134 | int fsetpos64(FILE*, in fpos_t*); 135 | alias fsetpos64 fsetpos; 136 | 137 | FILE* tmpfile64(); 138 | alias tmpfile64 tmpfile; 139 | } 140 | else 141 | { 142 | int fgetpos(FILE*, fpos_t *); 143 | FILE* fopen(in char*, in char*); 144 | FILE* freopen(in char*, in char*, FILE*); 145 | int fseek(FILE*, c_long, int); 146 | int fsetpos(FILE*, in fpos_t*); 147 | FILE* tmpfile(); 148 | } 149 | } 150 | else version( CRuntime_Bionic ) 151 | { 152 | int fgetpos(FILE*, fpos_t *); 153 | FILE* fopen(in char*, in char*); 154 | FILE* freopen(in char*, in char*, FILE*); 155 | int fseek(FILE*, c_long, int); 156 | int fsetpos(FILE*, in fpos_t*); 157 | } 158 | 159 | // 160 | // C Extension (CX) 161 | // 162 | /* 163 | L_ctermid 164 | 165 | char* ctermid(char*); 166 | FILE* fdopen(int, in char*); 167 | int fileno(FILE*); 168 | int fseeko(FILE*, off_t, int); 169 | off_t ftello(FILE*); 170 | char* gets(char*); 171 | int pclose(FILE*); 172 | FILE* popen(in char*, in char*); 173 | */ 174 | 175 | version( CRuntime_Glibc ) 176 | { 177 | enum L_ctermid = 9; 178 | 179 | static if( __USE_FILE_OFFSET64 ) 180 | { 181 | int fseeko64(FILE*, off_t, int); 182 | alias fseeko64 fseeko; 183 | } 184 | else 185 | { 186 | int fseeko(FILE*, off_t, int); 187 | } 188 | 189 | static if( __USE_FILE_OFFSET64 ) 190 | { 191 | off_t ftello64(FILE*); 192 | alias ftello64 ftello; 193 | } 194 | else 195 | { 196 | off_t ftello(FILE*); 197 | } 198 | } 199 | else version( dscripten ) 200 | { 201 | int fseeko(FILE*, off_t, int); 202 | off_t ftello(FILE*); 203 | } 204 | else version( Posix ) 205 | { 206 | int fseeko(FILE*, off_t, int); 207 | off_t ftello(FILE*); 208 | } 209 | 210 | char* ctermid(char*); 211 | FILE* fdopen(int, in char*); 212 | int fileno(FILE*); 213 | //int fseeko(FILE*, off_t, int); 214 | //off_t ftello(FILE*); 215 | char* gets(char*); 216 | int pclose(FILE*); 217 | FILE* popen(in char*, in char*); 218 | 219 | 220 | // memstream functions are conforming to POSIX.1-2008. These functions are 221 | // not specified in POSIX.1-2001 and are not widely available on other 222 | // systems. 223 | version( CRuntime_Glibc ) // as of glibc 1.0x 224 | version = HaveMemstream; 225 | else version( FreeBSD ) // as of FreeBSD 9.2 226 | version = HaveMemstream; 227 | else version( OpenBSD ) // as of OpenBSD 5.4 228 | version = HaveMemstream; 229 | 230 | version( HaveMemstream ) 231 | { 232 | FILE* fmemopen(in void* buf, in size_t size, in char* mode); 233 | FILE* open_memstream(char** ptr, size_t* sizeloc); 234 | FILE* open_wmemstream(wchar_t** ptr, size_t* sizeloc); 235 | } 236 | 237 | // 238 | // Thread-Safe Functions (TSF) 239 | // 240 | /* 241 | void flockfile(FILE*); 242 | int ftrylockfile(FILE*); 243 | void funlockfile(FILE*); 244 | int getc_unlocked(FILE*); 245 | int getchar_unlocked(); 246 | int putc_unlocked(int, FILE*); 247 | int putchar_unlocked(int); 248 | */ 249 | 250 | version( CRuntime_Glibc ) 251 | { 252 | void flockfile(FILE*); 253 | int ftrylockfile(FILE*); 254 | void funlockfile(FILE*); 255 | int getc_unlocked(FILE*); 256 | int getchar_unlocked(); 257 | int putc_unlocked(int, FILE*); 258 | int putchar_unlocked(int); 259 | } 260 | else version( OpenBSD ) 261 | { 262 | void flockfile(FILE*); 263 | int ftrylockfile(FILE*); 264 | void funlockfile(FILE*); 265 | int getc_unlocked(FILE*); 266 | int getchar_unlocked(); 267 | int putc_unlocked(int, FILE*); 268 | int putchar_unlocked(int); 269 | } 270 | else version( Solaris ) 271 | { 272 | void flockfile(FILE*); 273 | int ftrylockfile(FILE*); 274 | void funlockfile(FILE*); 275 | int getc_unlocked(FILE*); 276 | int getchar_unlocked(); 277 | int putc_unlocked(int, FILE*); 278 | int putchar_unlocked(int); 279 | } 280 | 281 | // 282 | // XOpen (XSI) 283 | // 284 | /* 285 | P_tmpdir 286 | va_list (defined in core.stdc.stdarg) 287 | 288 | char* tempnam(in char*, in char*); 289 | */ 290 | 291 | char* tempnam(in char*, in char*); 292 | 293 | version( CRuntime_Glibc ) 294 | { 295 | enum P_tmpdir = "/tmp"; 296 | } 297 | version( Darwin ) 298 | { 299 | enum P_tmpdir = "/var/tmp"; 300 | } 301 | version( FreeBSD ) 302 | { 303 | enum P_tmpdir = "/var/tmp/"; 304 | } 305 | version(NetBSD) 306 | { 307 | enum P_tmpdir = "/var/tmp/"; 308 | } 309 | version( OpenBSD ) 310 | { 311 | enum P_tmpdir = "/tmp/"; 312 | } 313 | version( Solaris ) 314 | { 315 | enum P_tmpdir = "/var/tmp/"; 316 | } 317 | 318 | version( HaveMemstream ) 319 | unittest 320 | { /* fmemopen */ 321 | import core.stdc.string : memcmp; 322 | byte[10] buf; 323 | auto f = fmemopen(buf.ptr, 10, "w"); 324 | assert(f !is null); 325 | assert(fprintf(f, "hello") == "hello".length); 326 | assert(fflush(f) == 0); 327 | assert(memcmp(buf.ptr, "hello".ptr, "hello".length) == 0); 328 | //assert(buf 329 | assert(fclose(f) == 0); 330 | } 331 | 332 | version( HaveMemstream ) 333 | unittest 334 | { /* Note: open_memstream is only useful for writing */ 335 | import core.stdc.string : memcmp; 336 | char* ptr = null; 337 | char[6] testdata = ['h', 'e', 'l', 'l', 'o', 0]; 338 | size_t sz = 0; 339 | auto f = open_memstream(&ptr, &sz); 340 | assert(f !is null); 341 | assert(fprintf(f, "%s", testdata.ptr) == 5); 342 | assert(fflush(f) == 0); 343 | assert(memcmp(ptr, testdata.ptr, testdata.length) == 0); 344 | assert(fclose(f) == 0); 345 | } 346 | 347 | version( HaveMemstream ) 348 | unittest 349 | { /* Note: open_wmemstream is only useful for writing */ 350 | import core.stdc.string : memcmp; 351 | import core.stdc.wchar_ : fwprintf; 352 | wchar_t* ptr = null; 353 | wchar_t[6] testdata = ['h', 'e', 'l', 'l', 'o', 0]; 354 | size_t sz = 0; 355 | auto f = open_wmemstream(&ptr, &sz); 356 | assert(f !is null); 357 | assert(fwprintf(f, testdata.ptr) == 5); 358 | assert(fflush(f) == 0); 359 | assert(memcmp(ptr, testdata.ptr, testdata.length*wchar_t.sizeof) == 0); 360 | assert(fclose(f) == 0); 361 | } 362 | 363 | 364 | ssize_t getdelim (char** lineptr, size_t* n, int delimiter, FILE* stream); 365 | ssize_t getline (char** lineptr, size_t* n, FILE* stream); 366 | -------------------------------------------------------------------------------- /rt/dscripten/emscripten.d: -------------------------------------------------------------------------------- 1 | /// Emscripten API. 2 | 3 | module dscripten.emscripten; 4 | 5 | pragma(LDC_no_moduleinfo); 6 | 7 | extern(C) void emscripten_worker_respond_provisionally(const char *, size_t); 8 | extern(C) void emscripten_worker_respond(const char *, size_t); 9 | 10 | void workerRespondProvisionally(const(void)[] buf) 11 | { 12 | emscripten_worker_respond_provisionally(cast(const(char)*)buf.ptr, buf.length); 13 | } 14 | 15 | void workerRespond(const(void)[] buf) 16 | { 17 | emscripten_worker_respond(cast(const(char)*)buf.ptr, buf.length); 18 | } 19 | -------------------------------------------------------------------------------- /rt/dscripten/memory.d: -------------------------------------------------------------------------------- 1 | module dscripten.memory; 2 | 3 | // Pull these in: 4 | import rt.lifetime; 5 | import rt.config; 6 | import gc.proxy; 7 | import ldc.arrayinit; 8 | 9 | // Call this in your extern(C) main 10 | extern(C) void gc_init(); 11 | -------------------------------------------------------------------------------- /rt/dscripten/standard.d: -------------------------------------------------------------------------------- 1 | // minimalistic D standard library 2 | module dscripten.standard; 3 | 4 | pragma(LDC_no_moduleinfo); 5 | 6 | extern(C) void* _Dmodule_ref; 7 | 8 | void deleteStruct(T)(T * r) nothrow 9 | { 10 | .destroy(*r); 11 | free(r); 12 | } 13 | 14 | void deleteObject(T)(T o) if(is(T == class)) 15 | { 16 | static if(hasMember!(T, "__dtor")) 17 | { 18 | o.__dtor(); 19 | } 20 | free(cast(void*)o); 21 | } 22 | 23 | struct vector (T) 24 | { 25 | this(int n) 26 | { 27 | for(int i = 0; i < n; ++i) 28 | push_back(T.init); 29 | } 30 | 31 | ~this() 32 | { 33 | clear(); 34 | } 35 | 36 | void push_back()(auto ref T val) 37 | { 38 | ++len; 39 | buffer = cast(T*) realloc(buffer, len* T.sizeof); 40 | buffer[len - 1] = val; 41 | } 42 | 43 | void opIndexAssign()(auto ref T val, int idx) 44 | { 45 | buffer[idx] = val; 46 | } 47 | 48 | void clear() 49 | { 50 | foreach(element; this.opSlice()) 51 | destroy(element); 52 | 53 | free(buffer); 54 | buffer = null; 55 | len = 0; 56 | } 57 | 58 | T[] opSlice() 59 | { 60 | return buffer[0 .. len]; 61 | } 62 | 63 | int size() const 64 | { 65 | return len; 66 | } 67 | 68 | bool empty() const 69 | { 70 | return len == 0; 71 | } 72 | 73 | T* data() 74 | { 75 | return buffer; 76 | } 77 | 78 | private: 79 | T* buffer; 80 | int len; 81 | } 82 | 83 | T[] newArray(T)(int length) 84 | { 85 | void* block = calloc(T.sizeof, length); 86 | return cast(T[])block[0 .. T.sizeof * length]; 87 | } 88 | 89 | void deleteArray(T)(in T[] arr) 90 | { 91 | free(cast(void*)arr.ptr); 92 | } 93 | 94 | /////////////////////////////////////////////////////////////////////////////// 95 | // meta 96 | 97 | template hasMember(T, string name) 98 | { 99 | static if (is(T == struct) || is(T == class) || is(T == union) || is(T == interface)) 100 | { 101 | enum bool hasMember = 102 | staticIndexOf!(name, __traits(allMembers, T)) != -1 || 103 | __traits(compiles, { mixin("alias Sym = Identity!(T."~name~");"); }); 104 | } 105 | else 106 | { 107 | enum bool hasMember = false; 108 | } 109 | } 110 | 111 | template staticIndexOf(T, TList...) 112 | { 113 | enum staticIndexOf = genericIndexOf!(T, TList).index; 114 | } 115 | 116 | template staticIndexOf(alias T, TList...) 117 | { 118 | enum staticIndexOf = genericIndexOf!(T, TList).index; 119 | } 120 | 121 | template genericIndexOf(args...) 122 | if (args.length >= 1) 123 | { 124 | alias e = Alias!(args[0]); 125 | alias tuple = args[1 .. $]; 126 | 127 | static if (tuple.length) 128 | { 129 | alias head = Alias!(tuple[0]); 130 | alias tail = tuple[1 .. $]; 131 | 132 | static if (isSame!(e, head)) 133 | { 134 | enum index = 0; 135 | } 136 | else 137 | { 138 | enum next = genericIndexOf!(e, tail).index; 139 | enum index = (next == -1) ? -1 : 1 + next; 140 | } 141 | } 142 | else 143 | { 144 | enum index = -1; 145 | } 146 | } 147 | 148 | template Alias(alias a) 149 | { 150 | static if (__traits(compiles, { alias x = a; })) 151 | alias Alias = a; 152 | else static if (__traits(compiles, { enum x = a; })) 153 | enum Alias = a; 154 | else 155 | static assert(0, "Cannot alias " ~ a.stringof); 156 | } 157 | 158 | template Alias(a...) 159 | { 160 | alias Alias = a; 161 | } 162 | 163 | template isSame(ab...) 164 | if (ab.length == 2) 165 | { 166 | static if (__traits(compiles, expectType!(ab[0]), 167 | expectType!(ab[1]))) 168 | { 169 | enum isSame = is(ab[0] == ab[1]); 170 | } 171 | else static if (!__traits(compiles, expectType!(ab[0])) && 172 | !__traits(compiles, expectType!(ab[1])) && 173 | __traits(compiles, expectBool!(ab[0] == ab[1]))) 174 | { 175 | static if (!__traits(compiles, &ab[0]) || 176 | !__traits(compiles, &ab[1])) 177 | enum isSame = (ab[0] == ab[1]); 178 | else 179 | enum isSame = __traits(isSame, ab[0], ab[1]); 180 | } 181 | else 182 | { 183 | enum isSame = __traits(isSame, ab[0], ab[1]); 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /rt/dscripten/test.d: -------------------------------------------------------------------------------- 1 | // tests that the minimalistic D runtime/helpers actually works 2 | pragma(LDC_no_moduleinfo); 3 | import standard; 4 | 5 | extern(C) 6 | int main() 7 | { 8 | runTest!("struct: ctor/dtor", testStructCtorAndDtor); 9 | 10 | runTest!("class: empty", testEmptyClass); 11 | runTest!("class: ctor/dtor", testClassCtorAndDtor); 12 | runTest!("class: derived", testDerivedClass); 13 | 14 | runTest!("floating point: basic", testFloatingPoint); 15 | runTest!("arrays: copy", testArrayCopy); 16 | runTest!("arrays: dynamic", testArrayDynamic); 17 | 18 | runTest!("delegates", testDelegate); 19 | 20 | return 0; 21 | } 22 | 23 | /////////////////////////////////////////////////////////////////////////////// 24 | 25 | float g_f; // global nan-initialized float compile-test 26 | 27 | void testFloatingPoint() 28 | { 29 | check(g_f != g_f); 30 | 31 | float f; 32 | check(f != f); 33 | } 34 | 35 | void testEmptyClass() 36 | { 37 | static class E 38 | { 39 | } 40 | 41 | auto o = new E; 42 | check(o !is null); 43 | deleteObject(o); 44 | } 45 | 46 | void testClassCtorAndDtor() 47 | { 48 | static class C 49 | { 50 | static bool called; 51 | static bool constructed; 52 | static bool destroyed; 53 | 54 | this() nothrow 55 | { 56 | constructed = true; 57 | } 58 | 59 | ~this() nothrow 60 | { 61 | destroyed = true; 62 | } 63 | 64 | void f() nothrow 65 | { 66 | called = true; 67 | } 68 | } 69 | 70 | auto c = new C; 71 | check(C.constructed); 72 | c.f(); 73 | check(C.called); 74 | 75 | deleteObject(c); 76 | check(C.destroyed); 77 | } 78 | 79 | void testDerivedClass() 80 | { 81 | static class Base 82 | { 83 | void f() 84 | { 85 | } 86 | } 87 | 88 | // construction/destruction 89 | static class D : Base 90 | { 91 | static bool derivedObjectConstructed; 92 | static bool called; 93 | 94 | this() 95 | { 96 | derivedObjectConstructed = true; 97 | } 98 | 99 | override void f() 100 | { 101 | called = true; 102 | } 103 | } 104 | 105 | // polymorphism 106 | { 107 | Base c = new D; 108 | check(D.derivedObjectConstructed); 109 | 110 | c.f(); 111 | check(D.called); 112 | 113 | deleteObject(c); 114 | } 115 | } 116 | 117 | void testStructCtorAndDtor() nothrow 118 | { 119 | static struct MyStruct 120 | { 121 | int initialized = 7654; 122 | bool ctorCalled; 123 | int ctorArg; 124 | this(int arg_) nothrow 125 | { 126 | ctorCalled = true; 127 | ctorArg = arg_; 128 | } 129 | 130 | static bool dtorCalled; 131 | 132 | ~this() nothrow 133 | { 134 | dtorCalled = true; 135 | } 136 | } 137 | 138 | // statically allocated struct 139 | { 140 | { 141 | auto s = MyStruct(123); 142 | check(s.initialized == 7654); 143 | check(s.ctorCalled); 144 | check(s.ctorArg == 123); 145 | check(!s.dtorCalled); 146 | } 147 | check(MyStruct.dtorCalled); 148 | } 149 | 150 | // dynamically allocated struct 151 | MyStruct.dtorCalled = false; 152 | { 153 | auto s = new MyStruct(123); 154 | assertEquals(7654, s.initialized); 155 | check(s.ctorCalled); 156 | assertEquals(123, s.ctorArg); 157 | check(!s.dtorCalled); 158 | 159 | deleteStruct(s); 160 | } 161 | check(MyStruct.dtorCalled); 162 | } 163 | 164 | void testArrayCopy() 165 | { 166 | int[10] tab; 167 | tab[] = 4; 168 | assertEquals(4, tab[0]); 169 | assertEquals(4, tab[9]); 170 | 171 | int[10] tab2; 172 | tab2 = tab; 173 | assertEquals(4, tab2[0]); 174 | assertEquals(4, tab2[9]); 175 | } 176 | 177 | void testArrayDynamic() 178 | { 179 | int[] tab = newArray!int(256); 180 | assertEquals(256, cast(int)tab.length); 181 | assert(tab.ptr); 182 | assertEquals(0, tab[0]); 183 | tab[1] = 1234; 184 | 185 | deleteArray(tab); 186 | } 187 | 188 | void testDelegate() 189 | { 190 | static class C 191 | { 192 | int a; 193 | void f() 194 | { 195 | ++a; 196 | } 197 | } 198 | 199 | static void callMe(void delegate() func) 200 | { 201 | for(int i=0;i < 123;++i) 202 | func(); 203 | } 204 | 205 | auto c = new C; 206 | callMe(&c.f); 207 | assertEquals(123, c.a); 208 | } 209 | 210 | /////////////////////////////////////////////////////////////////////////////// 211 | void runTest(string name, alias f)() 212 | { 213 | printf("Test: %s\n", name.ptr); 214 | f(); 215 | } 216 | 217 | void assertEquals(int expected, int actual, string file=__FILE__, int line=__LINE__) nothrow 218 | { 219 | if(expected == actual) 220 | return; 221 | 222 | printf("At %s(%d): expected %d, got %d\n", file.ptr, line, expected, actual); 223 | exit(1); 224 | } 225 | 226 | void check(bool condition, string file=__FILE__, int line=__LINE__) nothrow 227 | { 228 | if(condition) 229 | return; 230 | 231 | printf("At %s(%d): assertion failure\n", file.ptr, line); 232 | exit(1); 233 | } 234 | 235 | -------------------------------------------------------------------------------- /rt/dscripten/typeinfo.d: -------------------------------------------------------------------------------- 1 | module dscripten.typeinfo; 2 | 3 | // Pull these in. TODO should probably compile them unconditionally somehow 4 | import rt.typeinfo.ti_Acdouble; 5 | import rt.typeinfo.ti_Acfloat; 6 | import rt.typeinfo.ti_Acreal; 7 | import rt.typeinfo.ti_Adouble; 8 | import rt.typeinfo.ti_Afloat; 9 | import rt.typeinfo.ti_Ag; 10 | import rt.typeinfo.ti_Aint; 11 | import rt.typeinfo.ti_Along; 12 | import rt.typeinfo.ti_Areal; 13 | import rt.typeinfo.ti_Ashort; 14 | import rt.typeinfo.ti_byte; 15 | import rt.typeinfo.ti_C; 16 | import rt.typeinfo.ti_cdouble; 17 | import rt.typeinfo.ti_cent; 18 | import rt.typeinfo.ti_cfloat; 19 | import rt.typeinfo.ti_char; 20 | import rt.typeinfo.ti_creal; 21 | import rt.typeinfo.ti_dchar; 22 | import rt.typeinfo.ti_delegate; 23 | import rt.typeinfo.ti_double; 24 | import rt.typeinfo.ti_float; 25 | import rt.typeinfo.ti_idouble; 26 | import rt.typeinfo.ti_ifloat; 27 | import rt.typeinfo.ti_int; 28 | import rt.typeinfo.ti_ireal; 29 | import rt.typeinfo.ti_long; 30 | import rt.typeinfo.ti_n; 31 | import rt.typeinfo.ti_ptr; 32 | import rt.typeinfo.ti_real; 33 | import rt.typeinfo.ti_short; 34 | import rt.typeinfo.ti_ubyte; 35 | import rt.typeinfo.ti_ucent; 36 | import rt.typeinfo.ti_uint; 37 | import rt.typeinfo.ti_ulong; 38 | import rt.typeinfo.ti_ushort; 39 | import rt.typeinfo.ti_void; 40 | import rt.typeinfo.ti_wchar; 41 | -------------------------------------------------------------------------------- /rt/gc/config.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains the garbage collector configuration. 3 | * 4 | * Copyright: Copyright Digital Mars 2016 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | */ 7 | 8 | module gc.config; 9 | 10 | import core.stdc.stdio; 11 | import core.internal.parseoptions; 12 | 13 | __gshared Config config; 14 | 15 | struct Config 16 | { 17 | bool disable; // start disabled 18 | ubyte profile; // enable profiling with summary when terminating program 19 | string gc = "manual"; // select gc implementation conservative|manual 20 | 21 | size_t initReserve; // initial reserve (MB) 22 | size_t minPoolSize = 1; // initial and minimum pool size (MB) 23 | size_t maxPoolSize = 64; // maximum pool size (MB) 24 | size_t incPoolSize = 3; // pool size increment (MB) 25 | float heapSizeFactor = 2.0; // heap size to used memory ratio 26 | 27 | @nogc nothrow: 28 | 29 | bool initialize() 30 | { 31 | return initConfigOptions(this, "gcopt"); 32 | } 33 | 34 | void help() @nogc nothrow 35 | { 36 | string s = "GC options are specified as whitespace separated assignments: 37 | disable:0|1 - start disabled (%d) 38 | profile:0|1|2 - enable profiling with summary when terminating program (%d) 39 | gc:conservative|manual - select gc implementation (default = conservative) 40 | 41 | initReserve:N - initial memory to reserve in MB (%lld) 42 | minPoolSize:N - initial and minimum pool size in MB (%lld) 43 | maxPoolSize:N - maximum pool size in MB (%lld) 44 | incPoolSize:N - pool size increment MB (%lld) 45 | heapSizeFactor:N - targeted heap size to used memory ratio (%g) 46 | "; 47 | printf(s.ptr, disable, profile, cast(long)initReserve, cast(long)minPoolSize, 48 | cast(long)maxPoolSize, cast(long)incPoolSize, heapSizeFactor); 49 | } 50 | 51 | string errorName() @nogc nothrow { return "GC"; } 52 | } 53 | -------------------------------------------------------------------------------- /rt/gc/gcinterface.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains the internal GC interface. 3 | * 4 | * Copyright: Copyright Digital Mars 2016. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright, Sean Kelly, Jeremy DeHaan 7 | */ 8 | 9 | /* Copyright Digital Mars 2016. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module gc.gcinterface; 15 | 16 | static import core.memory; 17 | alias BlkAttr = core.memory.GC.BlkAttr; 18 | alias BlkInfo = core.memory.GC.BlkInfo; 19 | 20 | alias RootIterator = int delegate(scope int delegate(ref Root) nothrow dg); 21 | alias RangeIterator = int delegate(scope int delegate(ref Range) nothrow dg); 22 | 23 | 24 | struct Root 25 | { 26 | void* proot; 27 | alias proot this; 28 | } 29 | 30 | struct Range 31 | { 32 | void* pbot; 33 | void* ptop; 34 | TypeInfo ti; // should be tail const, but doesn't exist for references 35 | alias pbot this; // only consider pbot for relative ordering (opCmp) 36 | } 37 | 38 | interface GC 39 | { 40 | 41 | /* 42 | * 43 | */ 44 | void Dtor(); 45 | 46 | /** 47 | * 48 | */ 49 | void enable(); 50 | 51 | /** 52 | * 53 | */ 54 | void disable(); 55 | 56 | /** 57 | * 58 | */ 59 | void collect() nothrow; 60 | 61 | /** 62 | * 63 | */ 64 | void collectNoStack() nothrow; 65 | 66 | /** 67 | * minimize free space usage 68 | */ 69 | void minimize() nothrow; 70 | 71 | /** 72 | * 73 | */ 74 | uint getAttr(void* p) nothrow; 75 | 76 | /** 77 | * 78 | */ 79 | uint setAttr(void* p, uint mask) nothrow; 80 | 81 | /** 82 | * 83 | */ 84 | uint clrAttr(void* p, uint mask) nothrow; 85 | 86 | /** 87 | * 88 | */ 89 | void* malloc(size_t size, uint bits, const TypeInfo ti) nothrow; 90 | 91 | /* 92 | * 93 | */ 94 | BlkInfo qalloc(size_t size, uint bits, const TypeInfo ti) nothrow; 95 | 96 | /* 97 | * 98 | */ 99 | void* calloc(size_t size, uint bits, const TypeInfo ti) nothrow; 100 | 101 | /* 102 | * 103 | */ 104 | void* realloc(void* p, size_t size, uint bits, const TypeInfo ti) nothrow; 105 | 106 | /** 107 | * Attempt to in-place enlarge the memory block pointed to by p by at least 108 | * minsize bytes, up to a maximum of maxsize additional bytes. 109 | * This does not attempt to move the memory block (like realloc() does). 110 | * 111 | * Returns: 112 | * 0 if could not extend p, 113 | * total size of entire memory block if successful. 114 | */ 115 | size_t extend(void* p, size_t minsize, size_t maxsize, const TypeInfo ti) nothrow; 116 | 117 | /** 118 | * 119 | */ 120 | size_t reserve(size_t size) nothrow; 121 | 122 | /** 123 | * 124 | */ 125 | void free(void* p) nothrow @nogc; 126 | 127 | /** 128 | * Determine the base address of the block containing p. If p is not a gc 129 | * allocated pointer, return null. 130 | */ 131 | void* addrOf(void* p) nothrow @nogc; 132 | 133 | /** 134 | * Determine the allocated size of pointer p. If p is an interior pointer 135 | * or not a gc allocated pointer, return 0. 136 | */ 137 | size_t sizeOf(void* p) nothrow @nogc; 138 | 139 | /** 140 | * Determine the base address of the block containing p. If p is not a gc 141 | * allocated pointer, return null. 142 | */ 143 | BlkInfo query(void* p) nothrow; 144 | 145 | /** 146 | * Retrieve statistics about garbage collection. 147 | * Useful for debugging and tuning. 148 | */ 149 | core.memory.GC.Stats stats() nothrow; 150 | 151 | /** 152 | * add p to list of roots 153 | */ 154 | void addRoot(void* p) nothrow @nogc; 155 | 156 | /** 157 | * remove p from list of roots 158 | */ 159 | void removeRoot(void* p) nothrow @nogc; 160 | 161 | /** 162 | * 163 | */ 164 | @property RootIterator rootIter() @nogc; 165 | 166 | /** 167 | * add range to scan for roots 168 | */ 169 | void addRange(void* p, size_t sz, const TypeInfo ti) nothrow @nogc; 170 | 171 | /** 172 | * remove range 173 | */ 174 | void removeRange(void* p) nothrow @nogc; 175 | 176 | /** 177 | * 178 | */ 179 | @property RangeIterator rangeIter() @nogc; 180 | 181 | /** 182 | * run finalizers 183 | */ 184 | void runFinalizers(in void[] segment) nothrow; 185 | 186 | /* 187 | * 188 | */ 189 | bool inFinalizer() nothrow; 190 | } 191 | -------------------------------------------------------------------------------- /rt/gc/impl/manual/gc.d: -------------------------------------------------------------------------------- 1 | /** 2 | * This module contains a minimal garbage collector implementation according to 3 | * published requirements. This library is mostly intended to serve as an 4 | * example, but it is usable in applications which do not rely on a garbage 5 | * collector to clean up memory (ie. when dynamic array resizing is not used, 6 | * and all memory allocated with 'new' is freed deterministically with 7 | * 'delete'). 8 | * 9 | * Please note that block attribute data must be tracked, or at a minimum, the 10 | * FINALIZE bit must be tracked for any allocated memory block because calling 11 | * rt_finalize on a non-object block can result in an access violation. In the 12 | * allocator below, this tracking is done via a leading uint bitmask. A real 13 | * allocator may do better to store this data separately, similar to the basic 14 | * GC. 15 | * 16 | * Copyright: Copyright Sean Kelly 2005 - 2016. 17 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 18 | * Authors: Sean Kelly 19 | */ 20 | 21 | /* Copyright Sean Kelly 2005 - 2016. 22 | * Distributed under the Boost Software License, Version 1.0. 23 | * (See accompanying file LICENSE or copy at 24 | * http://www.boost.org/LICENSE_1_0.txt) 25 | */ 26 | module gc.impl.manual.gc; 27 | 28 | import gc.config; 29 | import gc.gcinterface; 30 | 31 | import rt.util.container.array; 32 | 33 | import cstdlib = core.stdc.stdlib : calloc, free, malloc, realloc; 34 | static import core.memory; 35 | 36 | extern (C) void onOutOfMemoryError(void* pretend_sideffect = null) @trusted pure nothrow @nogc; /* dmd @@@BUG11461@@@ */ 37 | 38 | class ManualGC : GC 39 | { 40 | __gshared Array!Root roots; 41 | __gshared Array!Range ranges; 42 | 43 | static void initialize(ref GC gc) 44 | { 45 | import core.stdc.string; 46 | 47 | if (config.gc != "manual") 48 | return; 49 | 50 | auto p = cstdlib.malloc(__traits(classInstanceSize, ManualGC)); 51 | if (!p) 52 | onOutOfMemoryError(); 53 | 54 | auto init = typeid(ManualGC).initializer(); 55 | assert(init.length == __traits(classInstanceSize, ManualGC)); 56 | auto instance = cast(ManualGC) memcpy(p, init.ptr, init.length); 57 | instance.__ctor(); 58 | 59 | gc = instance; 60 | } 61 | 62 | static void finalize(ref GC gc) 63 | { 64 | if (config.gc != "manual") 65 | return; 66 | 67 | auto instance = cast(ManualGC) gc; 68 | instance.Dtor(); 69 | cstdlib.free(cast(void*) instance); 70 | } 71 | 72 | this() 73 | { 74 | } 75 | 76 | void Dtor() 77 | { 78 | } 79 | 80 | void enable() 81 | { 82 | } 83 | 84 | void disable() 85 | { 86 | } 87 | 88 | void collect() nothrow 89 | { 90 | } 91 | 92 | void collectNoStack() nothrow 93 | { 94 | } 95 | 96 | void minimize() nothrow 97 | { 98 | } 99 | 100 | uint getAttr(void* p) nothrow 101 | { 102 | return 0; 103 | } 104 | 105 | uint setAttr(void* p, uint mask) nothrow 106 | { 107 | return 0; 108 | } 109 | 110 | uint clrAttr(void* p, uint mask) nothrow 111 | { 112 | return 0; 113 | } 114 | 115 | void* malloc(size_t size, uint bits, const TypeInfo ti) nothrow 116 | { 117 | void* p = cstdlib.malloc(size); 118 | 119 | if (size && p is null) 120 | onOutOfMemoryError(); 121 | return p; 122 | } 123 | 124 | BlkInfo qalloc(size_t size, uint bits, const TypeInfo ti) nothrow 125 | { 126 | BlkInfo retval; 127 | retval.base = malloc(size, bits, ti); 128 | retval.size = size; 129 | retval.attr = bits; 130 | return retval; 131 | } 132 | 133 | void* calloc(size_t size, uint bits, const TypeInfo ti) nothrow 134 | { 135 | void* p = cstdlib.calloc(1, size); 136 | 137 | if (size && p is null) 138 | onOutOfMemoryError(); 139 | return p; 140 | } 141 | 142 | void* realloc(void* p, size_t size, uint bits, const TypeInfo ti) nothrow 143 | { 144 | p = cstdlib.realloc(p, size); 145 | 146 | if (size && p is null) 147 | onOutOfMemoryError(); 148 | return p; 149 | } 150 | 151 | size_t extend(void* p, size_t minsize, size_t maxsize, const TypeInfo ti) nothrow 152 | { 153 | return 0; 154 | } 155 | 156 | size_t reserve(size_t size) nothrow 157 | { 158 | return 0; 159 | } 160 | 161 | void free(void* p) nothrow @nogc 162 | { 163 | cstdlib.free(p); 164 | } 165 | 166 | /** 167 | * Determine the base address of the block containing p. If p is not a gc 168 | * allocated pointer, return null. 169 | */ 170 | void* addrOf(void* p) nothrow @nogc 171 | { 172 | return null; 173 | } 174 | 175 | /** 176 | * Determine the allocated size of pointer p. If p is an interior pointer 177 | * or not a gc allocated pointer, return 0. 178 | */ 179 | size_t sizeOf(void* p) nothrow @nogc 180 | { 181 | return 0; 182 | } 183 | 184 | /** 185 | * Determine the base address of the block containing p. If p is not a gc 186 | * allocated pointer, return null. 187 | */ 188 | BlkInfo query(void* p) nothrow 189 | { 190 | return BlkInfo.init; 191 | } 192 | 193 | core.memory.GC.Stats stats() nothrow 194 | { 195 | return typeof(return).init; 196 | } 197 | 198 | void addRoot(void* p) nothrow @nogc 199 | { 200 | roots.insertBack(Root(p)); 201 | } 202 | 203 | void removeRoot(void* p) nothrow @nogc 204 | { 205 | foreach (ref r; roots) 206 | { 207 | if (r is p) 208 | { 209 | r = roots.back; 210 | roots.popBack(); 211 | return; 212 | } 213 | } 214 | assert(false); 215 | } 216 | 217 | @property RootIterator rootIter() return @nogc 218 | { 219 | return &rootsApply; 220 | } 221 | 222 | private int rootsApply(scope int delegate(ref Root) nothrow dg) 223 | { 224 | foreach (ref r; roots) 225 | { 226 | if (auto result = dg(r)) 227 | return result; 228 | } 229 | return 0; 230 | } 231 | 232 | void addRange(void* p, size_t sz, const TypeInfo ti = null) nothrow @nogc 233 | { 234 | ranges.insertBack(Range(p, p + sz, cast() ti)); 235 | } 236 | 237 | void removeRange(void* p) nothrow @nogc 238 | { 239 | foreach (ref r; ranges) 240 | { 241 | if (r.pbot is p) 242 | { 243 | r = ranges.back; 244 | ranges.popBack(); 245 | return; 246 | } 247 | } 248 | assert(false); 249 | } 250 | 251 | @property RangeIterator rangeIter() return @nogc 252 | { 253 | return &rangesApply; 254 | } 255 | 256 | private int rangesApply(scope int delegate(ref Range) nothrow dg) 257 | { 258 | foreach (ref r; ranges) 259 | { 260 | if (auto result = dg(r)) 261 | return result; 262 | } 263 | return 0; 264 | } 265 | 266 | void runFinalizers(in void[] segment) nothrow 267 | { 268 | } 269 | 270 | bool inFinalizer() nothrow 271 | { 272 | return false; 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /rt/gc/proxy.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains the external GC interface. 3 | * 4 | * Copyright: Copyright Digital Mars 2005 - 2016. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright, Sean Kelly 7 | */ 8 | 9 | /* Copyright Digital Mars 2005 - 2016. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module gc.proxy; 15 | 16 | //import gc.impl.conservative.gc; 17 | import gc.impl.manual.gc; 18 | import gc.config; 19 | import gc.gcinterface; 20 | 21 | static import core.memory; 22 | 23 | private 24 | { 25 | static import core.memory; 26 | alias BlkInfo = core.memory.GC.BlkInfo; 27 | 28 | // extern (C) void thread_init(); 29 | // extern (C) void thread_term(); 30 | 31 | __gshared GC instance; 32 | __gshared GC proxiedGC; // used to iterate roots of Windows DLLs 33 | 34 | } 35 | 36 | 37 | extern (C) 38 | { 39 | 40 | void gc_init() 41 | { 42 | config.initialize(); 43 | ManualGC.initialize(instance); 44 | //ConservativeGC.initialize(instance); 45 | if (instance is null) 46 | { 47 | import core.stdc.stdio : fprintf, stderr; 48 | import core.stdc.stdlib : exit; 49 | 50 | fprintf(stderr, "No GC was initialized, please recheck the name of the selected GC ('%.*s').\n", cast(int)config.gc.length, config.gc.ptr); 51 | exit(1); 52 | } 53 | 54 | // NOTE: The GC must initialize the thread library 55 | // before its first collection. 56 | // thread_init(); 57 | } 58 | 59 | void gc_term() 60 | { 61 | // NOTE: There may be daemons threads still running when this routine is 62 | // called. If so, cleaning memory out from under then is a good 63 | // way to make them crash horribly. This probably doesn't matter 64 | // much since the app is supposed to be shutting down anyway, but 65 | // I'm disabling cleanup for now until I can think about it some 66 | // more. 67 | // 68 | // NOTE: Due to popular demand, this has been re-enabled. It still has 69 | // the problems mentioned above though, so I guess we'll see. 70 | 71 | instance.collectNoStack(); // not really a 'collect all' -- still scans 72 | // static data area, roots, and ranges. 73 | 74 | // thread_term(); 75 | 76 | ManualGC.finalize(instance); 77 | //ConservativeGC.finalize(instance); 78 | } 79 | 80 | void gc_enable() 81 | { 82 | instance.enable(); 83 | } 84 | 85 | void gc_disable() 86 | { 87 | instance.disable(); 88 | } 89 | 90 | void gc_collect() nothrow 91 | { 92 | instance.collect(); 93 | } 94 | 95 | void gc_minimize() nothrow 96 | { 97 | instance.minimize(); 98 | } 99 | 100 | uint gc_getAttr( void* p ) nothrow 101 | { 102 | return instance.getAttr(p); 103 | } 104 | 105 | uint gc_setAttr( void* p, uint a ) nothrow 106 | { 107 | return instance.setAttr(p, a); 108 | } 109 | 110 | uint gc_clrAttr( void* p, uint a ) nothrow 111 | { 112 | return instance.clrAttr(p, a); 113 | } 114 | 115 | void* gc_malloc( size_t sz, uint ba = 0, const TypeInfo ti = null ) nothrow 116 | { 117 | return instance.malloc(sz, ba, ti); 118 | } 119 | 120 | BlkInfo gc_qalloc( size_t sz, uint ba = 0, const TypeInfo ti = null ) nothrow 121 | { 122 | return instance.qalloc( sz, ba, ti ); 123 | } 124 | 125 | void* gc_calloc( size_t sz, uint ba = 0, const TypeInfo ti = null ) nothrow 126 | { 127 | return instance.calloc( sz, ba, ti ); 128 | } 129 | 130 | void* gc_realloc( void* p, size_t sz, uint ba = 0, const TypeInfo ti = null ) nothrow 131 | { 132 | return instance.realloc( p, sz, ba, ti ); 133 | } 134 | 135 | size_t gc_extend( void* p, size_t mx, size_t sz, const TypeInfo ti = null ) nothrow 136 | { 137 | return instance.extend( p, mx, sz,ti ); 138 | } 139 | 140 | size_t gc_reserve( size_t sz ) nothrow 141 | { 142 | return instance.reserve( sz ); 143 | } 144 | 145 | void gc_free( void* p ) nothrow @nogc 146 | { 147 | return instance.free( p ); 148 | } 149 | 150 | void* gc_addrOf( void* p ) nothrow @nogc 151 | { 152 | return instance.addrOf( p ); 153 | } 154 | 155 | size_t gc_sizeOf( void* p ) nothrow @nogc 156 | { 157 | return instance.sizeOf( p ); 158 | } 159 | 160 | BlkInfo gc_query( void* p ) nothrow 161 | { 162 | return instance.query( p ); 163 | } 164 | 165 | core.memory.GC.Stats gc_stats() nothrow 166 | { 167 | return instance.stats(); 168 | } 169 | 170 | void gc_addRoot( void* p ) nothrow 171 | { 172 | return instance.addRoot( p ); 173 | } 174 | 175 | void gc_addRange( void* p, size_t sz, const TypeInfo ti = null ) nothrow 176 | { 177 | return instance.addRange( p, sz, ti ); 178 | } 179 | 180 | void gc_removeRoot( void* p ) nothrow 181 | { 182 | return instance.removeRoot( p ); 183 | } 184 | 185 | void gc_removeRange( void* p ) nothrow 186 | { 187 | return instance.removeRange( p ); 188 | } 189 | 190 | void gc_runFinalizers( in void[] segment ) nothrow 191 | { 192 | return instance.runFinalizers( segment ); 193 | } 194 | 195 | bool gc_inFinalizer() nothrow 196 | { 197 | return instance.inFinalizer(); 198 | } 199 | 200 | GC gc_getProxy() nothrow 201 | { 202 | return instance; 203 | } 204 | 205 | // LDC: Don't export these functions by default for each binary linked statically against druntime. 206 | //export 207 | //{ 208 | void gc_setProxy( GC proxy ) 209 | { 210 | foreach(root; instance.rootIter) 211 | { 212 | proxy.addRoot(root); 213 | } 214 | 215 | foreach(range; instance.rangeIter) 216 | { 217 | proxy.addRange(range.pbot, range.ptop - range.pbot, range.ti); 218 | } 219 | 220 | proxiedGC = instance; // remember initial GC to later remove roots 221 | instance = proxy; 222 | } 223 | 224 | void gc_clrProxy() 225 | { 226 | foreach(root; proxiedGC.rootIter) 227 | { 228 | instance.removeRoot(root); 229 | } 230 | 231 | foreach(range; proxiedGC.rangeIter) 232 | { 233 | instance.removeRange(range); 234 | } 235 | 236 | instance = proxiedGC; 237 | proxiedGC = null; 238 | } 239 | //} 240 | } 241 | -------------------------------------------------------------------------------- /rt/mainloop.c: -------------------------------------------------------------------------------- 1 | void startup(); 2 | void mainLoop(); 3 | 4 | static int mustQuit; 5 | 6 | #ifdef __EMSCRIPTEN__ 7 | 8 | void emscripten_set_main_loop(void (*function)(), int fps, int simulate_infinite_loop); 9 | 10 | int main() 11 | { 12 | startup(); 13 | emscripten_set_main_loop(&mainLoop, 60, 1); 14 | return 0; 15 | } 16 | 17 | #else 18 | 19 | void SDL_Delay(int); 20 | 21 | int main() 22 | { 23 | startup(); 24 | 25 | while(!mustQuit) 26 | { 27 | mainLoop(); 28 | SDL_Delay(16); 29 | } 30 | return 0; 31 | } 32 | 33 | #endif 34 | 35 | void quit() 36 | { 37 | mustQuit = 1; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /rt/rt/config.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Configuration options for druntime 3 | * 4 | * Copyright: Copyright Digital Mars 2014. 5 | * License: Distributed under the 6 | * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0). 7 | * (See accompanying file LICENSE) 8 | * Authors: Rainer Schuetze 9 | * Source: $(DRUNTIMESRC src/rt/_config.d) 10 | */ 11 | 12 | module rt.config; 13 | 14 | alias rt_configCallBack = string delegate(string) @nogc nothrow; 15 | string rt_configOption(string opt, scope rt_configCallBack dg = null, bool reverse = false) @nogc nothrow { return null; } 16 | 17 | version(none): 18 | // The default way to configure the runtime is by passing command line arguments 19 | // starting with "--DRT-" and followed by the option name, e.g. "--DRT-gcopt" to 20 | // configure the GC. 21 | // Command line options starting with "--DRT-" are filtered out before calling main, 22 | // so the program will not see them. They are still available via rt_args(). 23 | // 24 | // Configuration via the command line can be disabled by declaring a variable for the 25 | // linker to pick up before using it's default from the runtime: 26 | // 27 | // extern(C) __gshared bool rt_cmdline_enabled = false; 28 | // 29 | // Likewise, declare a boolean rt_envvars_enabled to enable configuration via the 30 | // environment variable "DRT_" followed by the option name, e.g. "DRT_GCOPT": 31 | // 32 | // extern(C) __gshared bool rt_envvars_enabled = true; 33 | // 34 | // Setting default configuration properties in the executable can be done by specifying an 35 | // array of options named rt_options: 36 | // 37 | // extern(C) __gshared string[] rt_options = [ "gcopt=precise:1 profile:1"]; 38 | // 39 | // Evaluation order of options is rt_options, then environment variables, then command 40 | // line arguments, i.e. if command line arguments are not disabled, they can override 41 | // options specified through the environment or embedded in the executable. 42 | 43 | // put each variable in its own COMDAT by making them template instances 44 | template rt_envvars_enabled() 45 | { 46 | extern(C) pragma(mangle, "rt_envvars_enabled") __gshared bool rt_envvars_enabled = false; 47 | } 48 | template rt_cmdline_enabled() 49 | { 50 | extern(C) pragma(mangle, "rt_cmdline_enabled") __gshared bool rt_cmdline_enabled = true; 51 | } 52 | template rt_options() 53 | { 54 | extern(C) pragma(mangle, "rt_options") __gshared string[] rt_options = []; 55 | } 56 | 57 | import core.stdc.ctype : toupper; 58 | import core.stdc.stdlib : getenv; 59 | import core.stdc.string : strlen; 60 | 61 | extern extern(C) string[] rt_args() @nogc nothrow; 62 | 63 | alias rt_configCallBack = string delegate(string) @nogc nothrow; 64 | 65 | /** 66 | * get a druntime config option using standard configuration options 67 | * opt name of the option to retreive 68 | * dg if non-null, passes the option through this 69 | * delegate and only returns its return value if non-null 70 | * reverse reverse the default processing order cmdline/envvar/rt_options 71 | * to allow overwriting settings in the delegate with values 72 | * from higher priority 73 | * 74 | * returns the options' value if 75 | * - set on the command line as "--DRT-=value" (rt_cmdline_enabled enabled) 76 | * - the environment variable "DRT_" is set (rt_envvars_enabled enabled) 77 | * - rt_options[] contains an entry "=value" 78 | * - null otherwise 79 | */ 80 | string rt_configOption(string opt, scope rt_configCallBack dg = null, bool reverse = false) @nogc nothrow 81 | { 82 | if (!dg) 83 | dg = (string s) => s; 84 | 85 | string s = (reverse ? rt_linkOption(opt, dg) : rt_cmdlineOption(opt, dg)); 86 | if (s != null) 87 | return s; 88 | s = rt_envvarsOption(opt, dg); 89 | if (s != null) 90 | return s; 91 | s = (reverse ? rt_cmdlineOption(opt, dg) : rt_linkOption(opt, dg)); 92 | return s; 93 | } 94 | 95 | string rt_cmdlineOption(string opt, scope rt_configCallBack dg) @nogc nothrow 96 | { 97 | if(rt_cmdline_enabled!()) 98 | { 99 | foreach (a; rt_args) 100 | { 101 | if (a.length >= opt.length + 7 && a[0..6] == "--DRT-" && 102 | a[6 .. 6 + opt.length] == opt && a[6 + opt.length] == '=') 103 | { 104 | string s = dg(a[7 + opt.length .. $]); 105 | if (s != null) 106 | return s; 107 | } 108 | } 109 | } 110 | return null; 111 | } 112 | 113 | string rt_envvarsOption(string opt, scope rt_configCallBack dg) @nogc nothrow 114 | { 115 | if(rt_envvars_enabled!()) 116 | { 117 | if (opt.length >= 32) 118 | assert(0); 119 | 120 | char[40] var; 121 | var[0 .. 4] = "DRT_"; 122 | foreach (i, c; opt) 123 | var[4 + i] = cast(char) toupper(c); 124 | var[4 + opt.length] = 0; 125 | 126 | auto p = getenv(var.ptr); 127 | if (p) 128 | { 129 | string s = dg(cast(string) p[0 .. strlen(p)]); 130 | if (s != null) 131 | return s; 132 | } 133 | } 134 | return null; 135 | } 136 | 137 | string rt_linkOption(string opt, scope rt_configCallBack dg) @nogc nothrow 138 | { 139 | foreach (a; rt_options!()) 140 | { 141 | if(a.length > opt.length && a[0..opt.length] == opt && a[opt.length] == '=') 142 | { 143 | string s = dg(a[opt.length + 1 .. $]); 144 | if (s != null) 145 | return s; 146 | } 147 | } 148 | return null; 149 | } 150 | -------------------------------------------------------------------------------- /rt/rt/deh.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementation of exception handling support routines. 3 | * 4 | * Copyright: Copyright Digital Mars 1999 - 2013. 5 | * License: Distributed under the 6 | * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0). 7 | * (See accompanying file LICENSE) 8 | * Authors: Walter Bright 9 | * Source: $(DRUNTIMESRC src/rt/deh.d) 10 | */ 11 | 12 | module rt.deh; 13 | 14 | extern (C) 15 | { 16 | Throwable.TraceInfo _d_traceContext(void* ptr = null); 17 | void _d_createTrace(Object o, void* context) 18 | { 19 | auto t = cast(Throwable) o; 20 | 21 | if (t !is null && t.info is null && 22 | cast(byte*) t !is typeid(t).initializer.ptr) 23 | { 24 | t.info = _d_traceContext(context); 25 | } 26 | } 27 | } 28 | 29 | version (dscripten) 30 | {} 31 | else version (LDC) 32 | public import rt.deh_win64_posix; 33 | else version (Win32) 34 | public import rt.deh_win32; 35 | else version (Win64) 36 | public import rt.deh_win64_posix; 37 | else version (Posix) 38 | public import rt.deh_win64_posix; 39 | else 40 | static assert (0, "Unsupported architecture"); 41 | 42 | -------------------------------------------------------------------------------- /rt/rt/invariant_.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementation of invariant support routines. 3 | * 4 | * Copyright: Copyright Digital Mars 2007 - 2010. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2007 - 2010. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.invariant_; 15 | 16 | /** 17 | * 18 | */ 19 | pragma(mangle, "_D9invariant12_d_invariantFC6ObjectZv") 20 | void _d_invariant(Object o) 21 | { ClassInfo c; 22 | 23 | //printf("__d_invariant(%p)\n", o); 24 | 25 | // BUG: needs to be filename/line of caller, not library routine 26 | assert(o !is null); // just do null check, not invariant check 27 | 28 | c = typeid(o); 29 | do 30 | { 31 | if (c.classInvariant) 32 | { 33 | (*c.classInvariant)(o); 34 | } 35 | c = c.base; 36 | } while (c); 37 | } 38 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_Acdouble.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_Acdouble; 15 | 16 | private import rt.util.typeinfo; 17 | 18 | // cdouble[] 19 | 20 | class TypeInfo_Ar : TypeInfo_Array 21 | { 22 | alias F = cdouble; 23 | 24 | override bool opEquals(Object o) { return TypeInfo.opEquals(o); } 25 | 26 | override string toString() const { return (F[]).stringof; } 27 | 28 | override size_t getHash(in void* p) @trusted const 29 | { 30 | return Array!F.hashOf(*cast(F[]*)p); 31 | } 32 | 33 | override bool equals(in void* p1, in void* p2) const 34 | { 35 | return Array!F.equals(*cast(F[]*)p1, *cast(F[]*)p2); 36 | } 37 | 38 | override int compare(in void* p1, in void* p2) const 39 | { 40 | return Array!F.compare(*cast(F[]*)p1, *cast(F[]*)p2); 41 | } 42 | 43 | override @property inout(TypeInfo) next() inout 44 | { 45 | return cast(inout)typeid(F); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_Acfloat.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_Acfloat; 15 | 16 | private import rt.util.typeinfo; 17 | 18 | // cfloat[] 19 | 20 | class TypeInfo_Aq : TypeInfo_Array 21 | { 22 | alias F = cfloat; 23 | 24 | override bool opEquals(Object o) { return TypeInfo.opEquals(o); } 25 | 26 | override string toString() const { return (F[]).stringof; } 27 | 28 | override size_t getHash(in void* p) @trusted const 29 | { 30 | return Array!F.hashOf(*cast(F[]*)p); 31 | } 32 | 33 | override bool equals(in void* p1, in void* p2) const 34 | { 35 | return Array!F.equals(*cast(F[]*)p1, *cast(F[]*)p2); 36 | } 37 | 38 | override int compare(in void* p1, in void* p2) const 39 | { 40 | return Array!F.compare(*cast(F[]*)p1, *cast(F[]*)p2); 41 | } 42 | 43 | override @property inout(TypeInfo) next() inout 44 | { 45 | return cast(inout)typeid(F); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_Acreal.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_Acreal; 15 | 16 | private import rt.util.typeinfo; 17 | 18 | // creal[] 19 | 20 | class TypeInfo_Ac : TypeInfo_Array 21 | { 22 | alias F = creal; 23 | 24 | override bool opEquals(Object o) { return TypeInfo.opEquals(o); } 25 | 26 | override string toString() const { return (F[]).stringof; } 27 | 28 | override size_t getHash(in void* p) @trusted const 29 | { 30 | return Array!F.hashOf(*cast(F[]*)p); 31 | } 32 | 33 | override bool equals(in void* p1, in void* p2) const 34 | { 35 | return Array!F.equals(*cast(F[]*)p1, *cast(F[]*)p2); 36 | } 37 | 38 | override int compare(in void* p1, in void* p2) const 39 | { 40 | return Array!F.compare(*cast(F[]*)p1, *cast(F[]*)p2); 41 | } 42 | 43 | override @property inout(TypeInfo) next() inout 44 | { 45 | return cast(inout)typeid(F); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_Adouble.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_Adouble; 15 | 16 | private import rt.util.typeinfo; 17 | 18 | // double[] 19 | 20 | class TypeInfo_Ad : TypeInfo_Array 21 | { 22 | alias F = double; 23 | 24 | override bool opEquals(Object o) { return TypeInfo.opEquals(o); } 25 | 26 | override string toString() const { return (F[]).stringof; } 27 | 28 | override size_t getHash(in void* p) @trusted const 29 | { 30 | return Array!F.hashOf(*cast(F[]*)p); 31 | } 32 | 33 | override bool equals(in void* p1, in void* p2) const 34 | { 35 | return Array!F.equals(*cast(F[]*)p1, *cast(F[]*)p2); 36 | } 37 | 38 | override int compare(in void* p1, in void* p2) const 39 | { 40 | return Array!F.compare(*cast(F[]*)p1, *cast(F[]*)p2); 41 | } 42 | 43 | override @property inout(TypeInfo) next() inout 44 | { 45 | return cast(inout)typeid(F); 46 | } 47 | } 48 | 49 | // idouble[] 50 | 51 | class TypeInfo_Ap : TypeInfo_Ad 52 | { 53 | alias F = idouble; 54 | 55 | override string toString() const { return (F[]).stringof; } 56 | 57 | override @property inout(TypeInfo) next() inout 58 | { 59 | return cast(inout)typeid(F); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_Afloat.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_Afloat; 15 | 16 | private import rt.util.typeinfo; 17 | 18 | // float[] 19 | 20 | class TypeInfo_Af : TypeInfo_Array 21 | { 22 | alias F = float; 23 | 24 | override bool opEquals(Object o) { return TypeInfo.opEquals(o); } 25 | 26 | override string toString() const { return (F[]).stringof; } 27 | 28 | override size_t getHash(in void* p) @trusted const 29 | { 30 | return Array!F.hashOf(*cast(F[]*)p); 31 | } 32 | 33 | override bool equals(in void* p1, in void* p2) const 34 | { 35 | return Array!F.equals(*cast(F[]*)p1, *cast(F[]*)p2); 36 | } 37 | 38 | override int compare(in void* p1, in void* p2) const 39 | { 40 | return Array!F.compare(*cast(F[]*)p1, *cast(F[]*)p2); 41 | } 42 | 43 | override @property inout(TypeInfo) next() inout 44 | { 45 | return cast(inout)typeid(F); 46 | } 47 | } 48 | 49 | // ifloat[] 50 | 51 | class TypeInfo_Ao : TypeInfo_Af 52 | { 53 | alias F = ifloat; 54 | 55 | override string toString() const { return (F[]).stringof; } 56 | 57 | override @property inout(TypeInfo) next() inout 58 | { 59 | return cast(inout)typeid(F); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_Ag.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_Ag; 15 | 16 | private import core.stdc.string; 17 | private import rt.util.hash; 18 | private import core.internal.string; 19 | 20 | // byte[] 21 | 22 | class TypeInfo_Ag : TypeInfo_Array 23 | { 24 | override bool opEquals(Object o) { return TypeInfo.opEquals(o); } 25 | 26 | override string toString() const { return "byte[]"; } 27 | 28 | override size_t getHash(in void* p) @trusted const 29 | { 30 | const s = *cast(const void[]*)p; 31 | return rt.util.hash.hashOf(s, 0); 32 | } 33 | 34 | override bool equals(in void* p1, in void* p2) const 35 | { 36 | byte[] s1 = *cast(byte[]*)p1; 37 | byte[] s2 = *cast(byte[]*)p2; 38 | 39 | return s1.length == s2.length && 40 | memcmp(cast(byte *)s1, cast(byte *)s2, s1.length) == 0; 41 | } 42 | 43 | override int compare(in void* p1, in void* p2) const 44 | { 45 | byte[] s1 = *cast(byte[]*)p1; 46 | byte[] s2 = *cast(byte[]*)p2; 47 | size_t len = s1.length; 48 | 49 | if (s2.length < len) 50 | len = s2.length; 51 | for (size_t u = 0; u < len; u++) 52 | { 53 | int result = s1[u] - s2[u]; 54 | if (result) 55 | return result; 56 | } 57 | if (s1.length < s2.length) 58 | return -1; 59 | else if (s1.length > s2.length) 60 | return 1; 61 | return 0; 62 | } 63 | 64 | override @property inout(TypeInfo) next() inout 65 | { 66 | return cast(inout)typeid(byte); 67 | } 68 | } 69 | 70 | 71 | // ubyte[] 72 | 73 | class TypeInfo_Ah : TypeInfo_Ag 74 | { 75 | override string toString() const { return "ubyte[]"; } 76 | 77 | override int compare(in void* p1, in void* p2) const 78 | { 79 | char[] s1 = *cast(char[]*)p1; 80 | char[] s2 = *cast(char[]*)p2; 81 | 82 | return dstrcmp(s1, s2); 83 | } 84 | 85 | override @property inout(TypeInfo) next() inout 86 | { 87 | return cast(inout)typeid(ubyte); 88 | } 89 | } 90 | 91 | // void[] 92 | 93 | class TypeInfo_Av : TypeInfo_Ah 94 | { 95 | override string toString() const { return "void[]"; } 96 | 97 | override @property inout(TypeInfo) next() inout 98 | { 99 | return cast(inout)typeid(void); 100 | } 101 | } 102 | 103 | // bool[] 104 | 105 | class TypeInfo_Ab : TypeInfo_Ah 106 | { 107 | override string toString() const { return "bool[]"; } 108 | 109 | override @property inout(TypeInfo) next() inout 110 | { 111 | return cast(inout)typeid(bool); 112 | } 113 | } 114 | 115 | // char[] 116 | 117 | class TypeInfo_Aa : TypeInfo_Ah 118 | { 119 | override string toString() const { return "char[]"; } 120 | 121 | override size_t getHash(in void* p) @trusted const 122 | { 123 | char[] s = *cast(char[]*)p; 124 | size_t hash = 0; 125 | 126 | version (all) 127 | { 128 | foreach (char c; s) 129 | hash = hash * 11 + c; 130 | } 131 | else 132 | { 133 | size_t len = s.length; 134 | char *str = s; 135 | 136 | while (1) 137 | { 138 | switch (len) 139 | { 140 | case 0: 141 | return hash; 142 | 143 | case 1: 144 | hash *= 9; 145 | hash += *cast(ubyte *)str; 146 | return hash; 147 | 148 | case 2: 149 | hash *= 9; 150 | hash += *cast(ushort *)str; 151 | return hash; 152 | 153 | case 3: 154 | hash *= 9; 155 | hash += (*cast(ushort *)str << 8) + 156 | (cast(ubyte *)str)[2]; 157 | return hash; 158 | 159 | default: 160 | hash *= 9; 161 | hash += *cast(uint *)str; 162 | str += 4; 163 | len -= 4; 164 | break; 165 | } 166 | } 167 | } 168 | return hash; 169 | } 170 | 171 | override @property inout(TypeInfo) next() inout 172 | { 173 | return cast(inout)typeid(char); 174 | } 175 | } 176 | 177 | // string 178 | 179 | class TypeInfo_Aya : TypeInfo_Aa 180 | { 181 | override string toString() const { return "immutable(char)[]"; } 182 | 183 | override @property inout(TypeInfo) next() inout 184 | { 185 | return cast(inout)typeid(immutable(char)); 186 | } 187 | } 188 | 189 | // const(char)[] 190 | 191 | class TypeInfo_Axa : TypeInfo_Aa 192 | { 193 | override string toString() const { return "const(char)[]"; } 194 | 195 | override @property inout(TypeInfo) next() inout 196 | { 197 | return cast(inout)typeid(const(char)); 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_Aint.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_Aint; 15 | 16 | private import core.stdc.string; 17 | private import rt.util.hash; 18 | 19 | extern (C) void[] _adSort(void[] a, TypeInfo ti); 20 | 21 | // int[] 22 | 23 | class TypeInfo_Ai : TypeInfo_Array 24 | { 25 | override bool opEquals(Object o) { return TypeInfo.opEquals(o); } 26 | 27 | override string toString() const { return "int[]"; } 28 | 29 | override size_t getHash(in void* p) @trusted const 30 | { 31 | const s = *cast(const int[]*)p; 32 | return rt.util.hash.hashOf(s, 0); 33 | } 34 | 35 | override bool equals(in void* p1, in void* p2) const 36 | { 37 | int[] s1 = *cast(int[]*)p1; 38 | int[] s2 = *cast(int[]*)p2; 39 | 40 | return s1.length == s2.length && 41 | memcmp(cast(void *)s1, cast(void *)s2, s1.length * int.sizeof) == 0; 42 | } 43 | 44 | override int compare(in void* p1, in void* p2) const 45 | { 46 | int[] s1 = *cast(int[]*)p1; 47 | int[] s2 = *cast(int[]*)p2; 48 | size_t len = s1.length; 49 | 50 | if (s2.length < len) 51 | len = s2.length; 52 | for (size_t u = 0; u < len; u++) 53 | { 54 | if (s1[u] < s2[u]) 55 | return -1; 56 | else if (s1[u] > s2[u]) 57 | return 1; 58 | } 59 | if (s1.length < s2.length) 60 | return -1; 61 | else if (s1.length > s2.length) 62 | return 1; 63 | return 0; 64 | } 65 | 66 | override @property inout(TypeInfo) next() inout 67 | { 68 | return cast(inout)typeid(int); 69 | } 70 | } 71 | 72 | unittest 73 | { 74 | int[][] a = [[5,3,8,7], [2,5,3,8,7]]; 75 | _adSort(*cast(void[]*)&a, typeid(a[0])); 76 | assert(a == [[2,5,3,8,7], [5,3,8,7]]); 77 | 78 | a = [[5,3,8,7], [5,3,8]]; 79 | _adSort(*cast(void[]*)&a, typeid(a[0])); 80 | assert(a == [[5,3,8], [5,3,8,7]]); 81 | } 82 | 83 | unittest 84 | { 85 | // Issue 13073: original code uses int subtraction which is susceptible to 86 | // integer overflow, causing the following case to fail. 87 | int[] a = [int.max, int.max]; 88 | int[] b = [int.min, int.min]; 89 | assert(a > b); 90 | assert(b < a); 91 | } 92 | 93 | // uint[] 94 | 95 | class TypeInfo_Ak : TypeInfo_Ai 96 | { 97 | override string toString() const { return "uint[]"; } 98 | 99 | override int compare(in void* p1, in void* p2) const 100 | { 101 | uint[] s1 = *cast(uint[]*)p1; 102 | uint[] s2 = *cast(uint[]*)p2; 103 | size_t len = s1.length; 104 | 105 | if (s2.length < len) 106 | len = s2.length; 107 | for (size_t u = 0; u < len; u++) 108 | { 109 | if (s1[u] < s2[u]) 110 | return -1; 111 | else if (s1[u] > s2[u]) 112 | return 1; 113 | } 114 | if (s1.length < s2.length) 115 | return -1; 116 | else if (s1.length > s2.length) 117 | return 1; 118 | return 0; 119 | } 120 | 121 | override @property inout(TypeInfo) next() inout 122 | { 123 | return cast(inout)typeid(uint); 124 | } 125 | } 126 | 127 | unittest 128 | { 129 | // Original test case from issue 13073 130 | uint x = 0x22_DF_FF_FF; 131 | uint y = 0xA2_DF_FF_FF; 132 | assert(!(x < y && y < x)); 133 | uint[] a = [x]; 134 | uint[] b = [y]; 135 | assert(!(a < b && b < a)); // Original failing case 136 | uint[1] a1 = [x]; 137 | uint[1] b1 = [y]; 138 | assert(!(a1 < b1 && b1 < a1)); // Original failing case 139 | } 140 | 141 | // dchar[] 142 | 143 | class TypeInfo_Aw : TypeInfo_Ak 144 | { 145 | override string toString() const { return "dchar[]"; } 146 | 147 | override @property inout(TypeInfo) next() inout 148 | { 149 | return cast(inout)typeid(dchar); 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_Along.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_Along; 15 | 16 | private import core.stdc.string; 17 | private import rt.util.hash; 18 | 19 | // long[] 20 | 21 | class TypeInfo_Al : TypeInfo_Array 22 | { 23 | override bool opEquals(Object o) { return TypeInfo.opEquals(o); } 24 | 25 | override string toString() const { return "long[]"; } 26 | 27 | override size_t getHash(in void* p) @trusted const 28 | { 29 | const s = *cast(const long[]*)p; 30 | return rt.util.hash.hashOf(s, 0); 31 | } 32 | 33 | override bool equals(in void* p1, in void* p2) const 34 | { 35 | long[] s1 = *cast(long[]*)p1; 36 | long[] s2 = *cast(long[]*)p2; 37 | 38 | return s1.length == s2.length && 39 | memcmp(cast(void *)s1, cast(void *)s2, s1.length * long.sizeof) == 0; 40 | } 41 | 42 | override int compare(in void* p1, in void* p2) const 43 | { 44 | long[] s1 = *cast(long[]*)p1; 45 | long[] s2 = *cast(long[]*)p2; 46 | size_t len = s1.length; 47 | 48 | if (s2.length < len) 49 | len = s2.length; 50 | for (size_t u = 0; u < len; u++) 51 | { 52 | if (s1[u] < s2[u]) 53 | return -1; 54 | else if (s1[u] > s2[u]) 55 | return 1; 56 | } 57 | if (s1.length < s2.length) 58 | return -1; 59 | else if (s1.length > s2.length) 60 | return 1; 61 | return 0; 62 | } 63 | 64 | override @property inout(TypeInfo) next() inout 65 | { 66 | return cast(inout)typeid(long); 67 | } 68 | } 69 | 70 | 71 | // ulong[] 72 | 73 | class TypeInfo_Am : TypeInfo_Al 74 | { 75 | override string toString() const { return "ulong[]"; } 76 | 77 | override int compare(in void* p1, in void* p2) const 78 | { 79 | ulong[] s1 = *cast(ulong[]*)p1; 80 | ulong[] s2 = *cast(ulong[]*)p2; 81 | size_t len = s1.length; 82 | 83 | if (s2.length < len) 84 | len = s2.length; 85 | for (size_t u = 0; u < len; u++) 86 | { 87 | if (s1[u] < s2[u]) 88 | return -1; 89 | else if (s1[u] > s2[u]) 90 | return 1; 91 | } 92 | if (s1.length < s2.length) 93 | return -1; 94 | else if (s1.length > s2.length) 95 | return 1; 96 | return 0; 97 | } 98 | 99 | override @property inout(TypeInfo) next() inout 100 | { 101 | return cast(inout)typeid(ulong); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_Areal.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_Areal; 15 | 16 | private import rt.util.typeinfo; 17 | 18 | // real[] 19 | 20 | class TypeInfo_Ae : TypeInfo_Array 21 | { 22 | alias F = real; 23 | 24 | override bool opEquals(Object o) { return TypeInfo.opEquals(o); } 25 | 26 | override string toString() const { return (F[]).stringof; } 27 | 28 | override size_t getHash(in void* p) @trusted const 29 | { 30 | return Array!F.hashOf(*cast(F[]*)p); 31 | } 32 | 33 | override bool equals(in void* p1, in void* p2) const 34 | { 35 | return Array!F.equals(*cast(F[]*)p1, *cast(F[]*)p2); 36 | } 37 | 38 | override int compare(in void* p1, in void* p2) const 39 | { 40 | return Array!F.compare(*cast(F[]*)p1, *cast(F[]*)p2); 41 | } 42 | 43 | override @property inout(TypeInfo) next() inout 44 | { 45 | return cast(inout)typeid(F); 46 | } 47 | } 48 | 49 | // ireal[] 50 | 51 | class TypeInfo_Aj : TypeInfo_Ae 52 | { 53 | alias F = ireal; 54 | 55 | override string toString() const { return (F[]).stringof; } 56 | 57 | override @property inout(TypeInfo) next() inout 58 | { 59 | return cast(inout)typeid(F); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_Ashort.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_Ashort; 15 | 16 | private import core.stdc.string; 17 | private import rt.util.hash; 18 | 19 | // short[] 20 | 21 | class TypeInfo_As : TypeInfo_Array 22 | { 23 | override bool opEquals(Object o) { return TypeInfo.opEquals(o); } 24 | 25 | override string toString() const { return "short[]"; } 26 | 27 | override size_t getHash(in void* p) @trusted const 28 | { 29 | const s = *cast(const short[]*)p; 30 | return rt.util.hash.hashOf(s, 0); 31 | } 32 | 33 | override bool equals(in void* p1, in void* p2) const 34 | { 35 | short[] s1 = *cast(short[]*)p1; 36 | short[] s2 = *cast(short[]*)p2; 37 | 38 | return s1.length == s2.length && 39 | memcmp(cast(void *)s1, cast(void *)s2, s1.length * short.sizeof) == 0; 40 | } 41 | 42 | override int compare(in void* p1, in void* p2) const 43 | { 44 | short[] s1 = *cast(short[]*)p1; 45 | short[] s2 = *cast(short[]*)p2; 46 | size_t len = s1.length; 47 | 48 | if (s2.length < len) 49 | len = s2.length; 50 | for (size_t u = 0; u < len; u++) 51 | { 52 | int result = s1[u] - s2[u]; 53 | if (result) 54 | return result; 55 | } 56 | if (s1.length < s2.length) 57 | return -1; 58 | else if (s1.length > s2.length) 59 | return 1; 60 | return 0; 61 | } 62 | 63 | override @property inout(TypeInfo) next() inout 64 | { 65 | return cast(inout)typeid(short); 66 | } 67 | } 68 | 69 | 70 | // ushort[] 71 | 72 | class TypeInfo_At : TypeInfo_As 73 | { 74 | override string toString() const { return "ushort[]"; } 75 | 76 | override int compare(in void* p1, in void* p2) const 77 | { 78 | ushort[] s1 = *cast(ushort[]*)p1; 79 | ushort[] s2 = *cast(ushort[]*)p2; 80 | size_t len = s1.length; 81 | 82 | if (s2.length < len) 83 | len = s2.length; 84 | for (size_t u = 0; u < len; u++) 85 | { 86 | int result = s1[u] - s2[u]; 87 | if (result) 88 | return result; 89 | } 90 | if (s1.length < s2.length) 91 | return -1; 92 | else if (s1.length > s2.length) 93 | return 1; 94 | return 0; 95 | } 96 | 97 | override @property inout(TypeInfo) next() inout 98 | { 99 | return cast(inout)typeid(ushort); 100 | } 101 | } 102 | 103 | // wchar[] 104 | 105 | class TypeInfo_Au : TypeInfo_At 106 | { 107 | override string toString() const { return "wchar[]"; } 108 | 109 | override @property inout(TypeInfo) next() inout 110 | { 111 | return cast(inout)typeid(wchar); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_C.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_C; 15 | 16 | // Object 17 | 18 | class TypeInfo_C : TypeInfo 19 | { 20 | @trusted: 21 | const: 22 | //pure: 23 | //nothrow: 24 | 25 | override size_t getHash(in void* p) 26 | { 27 | Object o = *cast(Object*)p; 28 | return o ? o.toHash() : 0; 29 | } 30 | 31 | override bool equals(in void* p1, in void* p2) 32 | { 33 | Object o1 = *cast(Object*)p1; 34 | Object o2 = *cast(Object*)p2; 35 | 36 | return o1 == o2; 37 | } 38 | 39 | override int compare(in void* p1, in void* p2) 40 | { 41 | Object o1 = *cast(Object*)p1; 42 | Object o2 = *cast(Object*)p2; 43 | int c = 0; 44 | 45 | // Regard null references as always being "less than" 46 | if (!(o1 is o2)) 47 | { 48 | if (o1) 49 | { 50 | if (!o2) 51 | c = 1; 52 | else 53 | c = o1.opCmp(o2); 54 | } 55 | else 56 | c = -1; 57 | } 58 | return c; 59 | } 60 | 61 | override @property size_t tsize() nothrow pure 62 | { 63 | return Object.sizeof; 64 | } 65 | 66 | override const(void)[] initializer() const @trusted 67 | { 68 | return (cast(void *)null)[0 .. Object.sizeof]; 69 | } 70 | 71 | override @property uint flags() nothrow pure 72 | { 73 | return 1; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_byte.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_byte; 15 | 16 | // byte 17 | 18 | class TypeInfo_g : TypeInfo 19 | { 20 | @trusted: 21 | const: 22 | pure: 23 | nothrow: 24 | 25 | override string toString() const pure nothrow @safe { return "byte"; } 26 | 27 | override size_t getHash(in void* p) 28 | { 29 | return *cast(byte *)p; 30 | } 31 | 32 | override bool equals(in void* p1, in void* p2) 33 | { 34 | return *cast(byte *)p1 == *cast(byte *)p2; 35 | } 36 | 37 | override int compare(in void* p1, in void* p2) 38 | { 39 | return *cast(byte *)p1 - *cast(byte *)p2; 40 | } 41 | 42 | override @property size_t tsize() nothrow pure 43 | { 44 | return byte.sizeof; 45 | } 46 | 47 | override const(void)[] initializer() @trusted 48 | { 49 | return (cast(void *)null)[0 .. byte.sizeof]; 50 | } 51 | 52 | override void swap(void *p1, void *p2) 53 | { 54 | byte t; 55 | 56 | t = *cast(byte *)p1; 57 | *cast(byte *)p1 = *cast(byte *)p2; 58 | *cast(byte *)p2 = t; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_cdouble.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_cdouble; 15 | 16 | private import rt.util.typeinfo; 17 | 18 | // cdouble 19 | 20 | class TypeInfo_r : TypeInfo 21 | { 22 | pure: 23 | nothrow: 24 | @safe: 25 | 26 | alias F = cdouble; 27 | 28 | override string toString() const { return F.stringof; } 29 | 30 | override size_t getHash(in void* p) const @trusted 31 | { 32 | return Floating!F.hashOf(*cast(F*)p); 33 | } 34 | 35 | override bool equals(in void* p1, in void* p2) const @trusted 36 | { 37 | return Floating!F.equals(*cast(F*)p1, *cast(F*)p2); 38 | } 39 | 40 | override int compare(in void* p1, in void* p2) const @trusted 41 | { 42 | return Floating!F.compare(*cast(F*)p1, *cast(F*)p2); 43 | } 44 | 45 | override @property size_t tsize() const 46 | { 47 | return F.sizeof; 48 | } 49 | 50 | override void swap(void *p1, void *p2) const @trusted 51 | { 52 | F t = *cast(F*)p1; 53 | *cast(F*)p1 = *cast(F*)p2; 54 | *cast(F*)p2 = t; 55 | } 56 | 57 | override const(void)[] initializer() const @trusted 58 | { 59 | static immutable F r; 60 | return (&r)[0 .. 1]; 61 | } 62 | 63 | override @property size_t talign() const 64 | { 65 | return F.alignof; 66 | } 67 | 68 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) 69 | { 70 | arg1 = typeid(double); 71 | arg2 = typeid(double); 72 | return 0; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_cent.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2015. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2015. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_cent; 15 | 16 | private import rt.util.hash; 17 | 18 | static if(is(cent)): 19 | 20 | // cent 21 | 22 | class TypeInfo_zi : TypeInfo 23 | { 24 | @trusted: 25 | const: 26 | pure: 27 | nothrow: 28 | 29 | override string toString() const pure nothrow @safe { return "cent"; } 30 | 31 | override size_t getHash(in void* p) 32 | { 33 | return rt.util.hash.hashOf(p[0 .. cent.sizeof], 0); 34 | } 35 | 36 | override bool equals(in void* p1, in void* p2) 37 | { 38 | return *cast(cent *)p1 == *cast(cent *)p2; 39 | } 40 | 41 | override int compare(in void* p1, in void* p2) 42 | { 43 | if (*cast(cent *)p1 < *cast(cent *)p2) 44 | return -1; 45 | else if (*cast(cent *)p1 > *cast(cent *)p2) 46 | return 1; 47 | return 0; 48 | } 49 | 50 | override @property size_t tsize() nothrow pure 51 | { 52 | return cent.sizeof; 53 | } 54 | 55 | override const(void)[] initializer() const @trusted 56 | { 57 | return (cast(void *)null)[0 .. cent.sizeof]; 58 | } 59 | 60 | override void swap(void *p1, void *p2) 61 | { 62 | cent t; 63 | 64 | t = *cast(cent *)p1; 65 | *cast(cent *)p1 = *cast(cent *)p2; 66 | *cast(cent *)p2 = t; 67 | } 68 | 69 | override @property size_t talign() nothrow pure 70 | { 71 | return cent.alignof; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_cfloat.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_cfloat; 15 | 16 | private import rt.util.typeinfo; 17 | 18 | // cfloat 19 | 20 | class TypeInfo_q : TypeInfo 21 | { 22 | pure: 23 | nothrow: 24 | @safe: 25 | 26 | alias F = cfloat; 27 | 28 | override string toString() const { return F.stringof; } 29 | 30 | override size_t getHash(in void* p) const @trusted 31 | { 32 | return Floating!F.hashOf(*cast(F*)p); 33 | } 34 | 35 | override bool equals(in void* p1, in void* p2) const @trusted 36 | { 37 | return Floating!F.equals(*cast(F*)p1, *cast(F*)p2); 38 | } 39 | 40 | override int compare(in void* p1, in void* p2) const @trusted 41 | { 42 | return Floating!F.compare(*cast(F*)p1, *cast(F*)p2); 43 | } 44 | 45 | override @property size_t tsize() const 46 | { 47 | return F.sizeof; 48 | } 49 | 50 | override void swap(void *p1, void *p2) const @trusted 51 | { 52 | F t = *cast(F*)p1; 53 | *cast(F*)p1 = *cast(F*)p2; 54 | *cast(F*)p2 = t; 55 | } 56 | 57 | override const(void)[] initializer() const @trusted 58 | { 59 | static immutable F r; 60 | return (&r)[0 .. 1]; 61 | } 62 | 63 | override @property size_t talign() const 64 | { 65 | return F.alignof; 66 | } 67 | 68 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) 69 | { 70 | arg1 = typeid(double); 71 | return 0; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_char.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_char; 15 | 16 | // char 17 | 18 | class TypeInfo_a : TypeInfo 19 | { 20 | @trusted: 21 | const: 22 | pure: 23 | nothrow: 24 | 25 | override string toString() const pure nothrow @safe { return "char"; } 26 | 27 | override size_t getHash(in void* p) 28 | { 29 | return *cast(char *)p; 30 | } 31 | 32 | override bool equals(in void* p1, in void* p2) 33 | { 34 | return *cast(char *)p1 == *cast(char *)p2; 35 | } 36 | 37 | override int compare(in void* p1, in void* p2) 38 | { 39 | return *cast(char *)p1 - *cast(char *)p2; 40 | } 41 | 42 | override @property size_t tsize() nothrow pure 43 | { 44 | return char.sizeof; 45 | } 46 | 47 | override void swap(void *p1, void *p2) 48 | { 49 | char t; 50 | 51 | t = *cast(char *)p1; 52 | *cast(char *)p1 = *cast(char *)p2; 53 | *cast(char *)p2 = t; 54 | } 55 | 56 | override const(void)[] initializer() const @trusted 57 | { 58 | static immutable char c; 59 | 60 | return (&c)[0 .. 1]; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_creal.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_creal; 15 | 16 | private import rt.util.typeinfo; 17 | 18 | // creal 19 | 20 | class TypeInfo_c : TypeInfo 21 | { 22 | pure: 23 | nothrow: 24 | @safe: 25 | 26 | alias F = creal; 27 | 28 | override string toString() const { return F.stringof; } 29 | 30 | override size_t getHash(in void* p) const @trusted 31 | { 32 | return Floating!F.hashOf(*cast(F*)p); 33 | } 34 | 35 | override bool equals(in void* p1, in void* p2) const @trusted 36 | { 37 | return Floating!F.equals(*cast(F*)p1, *cast(F*)p2); 38 | } 39 | 40 | override int compare(in void* p1, in void* p2) const @trusted 41 | { 42 | return Floating!F.compare(*cast(F*)p1, *cast(F*)p2); 43 | } 44 | 45 | override @property size_t tsize() const 46 | { 47 | return F.sizeof; 48 | } 49 | 50 | override void swap(void *p1, void *p2) const @trusted 51 | { 52 | F t = *cast(F*)p1; 53 | *cast(F*)p1 = *cast(F*)p2; 54 | *cast(F*)p2 = t; 55 | } 56 | 57 | override const(void)[] initializer() const @trusted 58 | { 59 | static immutable F r; 60 | return (&r)[0 .. 1]; 61 | } 62 | 63 | override @property size_t talign() const 64 | { 65 | return F.alignof; 66 | } 67 | 68 | version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2) 69 | { 70 | arg1 = typeid(real); 71 | arg2 = typeid(real); 72 | return 0; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_dchar.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_dchar; 15 | 16 | // dchar 17 | 18 | class TypeInfo_w : TypeInfo 19 | { 20 | @trusted: 21 | const: 22 | pure: 23 | nothrow: 24 | 25 | override string toString() const pure nothrow @safe { return "dchar"; } 26 | 27 | override size_t getHash(in void* p) 28 | { 29 | return *cast(dchar *)p; 30 | } 31 | 32 | override bool equals(in void* p1, in void* p2) 33 | { 34 | return *cast(dchar *)p1 == *cast(dchar *)p2; 35 | } 36 | 37 | override int compare(in void* p1, in void* p2) 38 | { 39 | return *cast(dchar *)p1 - *cast(dchar *)p2; 40 | } 41 | 42 | override @property size_t tsize() nothrow pure 43 | { 44 | return dchar.sizeof; 45 | } 46 | 47 | override void swap(void *p1, void *p2) 48 | { 49 | dchar t; 50 | 51 | t = *cast(dchar *)p1; 52 | *cast(dchar *)p1 = *cast(dchar *)p2; 53 | *cast(dchar *)p2 = t; 54 | } 55 | 56 | override const(void)[] initializer() const @trusted 57 | { 58 | static immutable dchar c; 59 | 60 | return (&c)[0 .. 1]; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_delegate.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_delegate; 15 | 16 | private import rt.util.hash; 17 | 18 | // delegate 19 | 20 | alias void delegate(int) dg; 21 | 22 | class TypeInfo_D : TypeInfo 23 | { 24 | @trusted: 25 | const: 26 | pure: 27 | nothrow: 28 | 29 | override size_t getHash(in void* p) 30 | { 31 | return rt.util.hash.hashOf(p[0 .. dg.sizeof], 0); 32 | } 33 | 34 | override bool equals(in void* p1, in void* p2) 35 | { 36 | return *cast(dg *)p1 == *cast(dg *)p2; 37 | } 38 | 39 | override @property size_t tsize() nothrow pure 40 | { 41 | return dg.sizeof; 42 | } 43 | 44 | override void swap(void *p1, void *p2) 45 | { 46 | dg t; 47 | 48 | t = *cast(dg *)p1; 49 | *cast(dg *)p1 = *cast(dg *)p2; 50 | *cast(dg *)p2 = t; 51 | } 52 | 53 | override const(void)[] initializer() const @trusted 54 | { 55 | static immutable dg d; 56 | 57 | return (cast(void *)null)[0 .. dg.sizeof]; 58 | } 59 | 60 | override @property uint flags() nothrow pure 61 | { 62 | return 1; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_double.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_double; 15 | 16 | private import rt.util.typeinfo; 17 | 18 | // double 19 | 20 | class TypeInfo_d : TypeInfo 21 | { 22 | pure: 23 | nothrow: 24 | @safe: 25 | 26 | alias F = double; 27 | 28 | override string toString() const { return F.stringof; } 29 | 30 | override size_t getHash(in void* p) const @trusted 31 | { 32 | return Floating!F.hashOf(*cast(F*)p); 33 | } 34 | 35 | override bool equals(in void* p1, in void* p2) const @trusted 36 | { 37 | return Floating!F.equals(*cast(F*)p1, *cast(F*)p2); 38 | } 39 | 40 | override int compare(in void* p1, in void* p2) const @trusted 41 | { 42 | return Floating!F.compare(*cast(F*)p1, *cast(F*)p2); 43 | } 44 | 45 | override @property size_t tsize() const 46 | { 47 | return F.sizeof; 48 | } 49 | 50 | override void swap(void *p1, void *p2) const @trusted 51 | { 52 | F t = *cast(F*)p1; 53 | *cast(F*)p1 = *cast(F*)p2; 54 | *cast(F*)p2 = t; 55 | } 56 | 57 | override const(void)[] initializer() const @trusted 58 | { 59 | static immutable F r; 60 | return (&r)[0 .. 1]; 61 | } 62 | 63 | override @property size_t talign() const 64 | { 65 | return F.alignof; 66 | } 67 | 68 | version (Windows) 69 | { 70 | } 71 | else version (X86_64) 72 | { 73 | // 2 means arg to function is passed in XMM registers 74 | override @property uint flags() const { return 2; } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_float.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_float; 15 | 16 | private import rt.util.typeinfo; 17 | 18 | // float 19 | 20 | class TypeInfo_f : TypeInfo 21 | { 22 | pure: 23 | nothrow: 24 | @safe: 25 | 26 | alias F = float; 27 | 28 | override string toString() const { return F.stringof; } 29 | 30 | override size_t getHash(in void* p) const @trusted 31 | { 32 | return Floating!F.hashOf(*cast(F*)p); 33 | } 34 | 35 | override bool equals(in void* p1, in void* p2) const @trusted 36 | { 37 | return Floating!F.equals(*cast(F*)p1, *cast(F*)p2); 38 | } 39 | 40 | override int compare(in void* p1, in void* p2) const @trusted 41 | { 42 | return Floating!F.compare(*cast(F*)p1, *cast(F*)p2); 43 | } 44 | 45 | override @property size_t tsize() const 46 | { 47 | return F.sizeof; 48 | } 49 | 50 | override void swap(void *p1, void *p2) const @trusted 51 | { 52 | F t = *cast(F*)p1; 53 | *cast(F*)p1 = *cast(F*)p2; 54 | *cast(F*)p2 = t; 55 | } 56 | 57 | override const(void)[] initializer() const @trusted 58 | { 59 | static immutable F r; 60 | return (&r)[0 .. 1]; 61 | } 62 | 63 | version (Windows) 64 | { 65 | } 66 | else version (X86_64) 67 | { 68 | // 2 means arg to function is passed in XMM registers 69 | override @property uint flags() const { return 2; } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_idouble.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_idouble; 15 | 16 | private import rt.typeinfo.ti_double; 17 | 18 | // idouble 19 | 20 | class TypeInfo_p : TypeInfo_d 21 | { 22 | pure: 23 | nothrow: 24 | @safe: 25 | 26 | override string toString() const { return idouble.stringof; } 27 | } 28 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_ifloat.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_ifloat; 15 | 16 | private import rt.typeinfo.ti_float; 17 | 18 | // ifloat 19 | 20 | class TypeInfo_o : TypeInfo_f 21 | { 22 | pure: 23 | nothrow: 24 | @safe: 25 | 26 | override string toString() const { return ifloat.stringof; } 27 | } 28 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_int.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_int; 15 | 16 | // int 17 | 18 | class TypeInfo_i : TypeInfo 19 | { 20 | @trusted: 21 | const: 22 | pure: 23 | nothrow: 24 | 25 | override string toString() const pure nothrow @safe { return "int"; } 26 | 27 | override size_t getHash(in void* p) 28 | { 29 | return *cast(uint *)p; 30 | } 31 | 32 | override bool equals(in void* p1, in void* p2) 33 | { 34 | return *cast(uint *)p1 == *cast(uint *)p2; 35 | } 36 | 37 | override int compare(in void* p1, in void* p2) 38 | { 39 | if (*cast(int*) p1 < *cast(int*) p2) 40 | return -1; 41 | else if (*cast(int*) p1 > *cast(int*) p2) 42 | return 1; 43 | return 0; 44 | } 45 | 46 | override @property size_t tsize() nothrow pure 47 | { 48 | return int.sizeof; 49 | } 50 | 51 | override const(void)[] initializer() const @trusted 52 | { 53 | return (cast(void *)null)[0 .. int.sizeof]; 54 | } 55 | 56 | override void swap(void *p1, void *p2) 57 | { 58 | int t; 59 | 60 | t = *cast(int *)p1; 61 | *cast(int *)p1 = *cast(int *)p2; 62 | *cast(int *)p2 = t; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_ireal.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_ireal; 15 | 16 | private import rt.typeinfo.ti_real; 17 | 18 | // ireal 19 | 20 | class TypeInfo_j : TypeInfo_e 21 | { 22 | pure: 23 | nothrow: 24 | @safe: 25 | 26 | override string toString() const { return ireal.stringof; } 27 | } 28 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_long.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_long; 15 | 16 | private import rt.util.hash; 17 | 18 | // long 19 | 20 | class TypeInfo_l : TypeInfo 21 | { 22 | @trusted: 23 | const: 24 | pure: 25 | nothrow: 26 | 27 | override string toString() const pure nothrow @safe { return "long"; } 28 | 29 | override size_t getHash(in void* p) 30 | { 31 | return rt.util.hash.hashOf(p[0 .. long.sizeof], 0); 32 | } 33 | 34 | override bool equals(in void* p1, in void* p2) 35 | { 36 | return *cast(long *)p1 == *cast(long *)p2; 37 | } 38 | 39 | override int compare(in void* p1, in void* p2) 40 | { 41 | if (*cast(long *)p1 < *cast(long *)p2) 42 | return -1; 43 | else if (*cast(long *)p1 > *cast(long *)p2) 44 | return 1; 45 | return 0; 46 | } 47 | 48 | override @property size_t tsize() nothrow pure 49 | { 50 | return long.sizeof; 51 | } 52 | 53 | override const(void)[] initializer() const @trusted 54 | { 55 | return (cast(void *)null)[0 .. long.sizeof]; 56 | } 57 | 58 | override void swap(void *p1, void *p2) 59 | { 60 | long t; 61 | 62 | t = *cast(long *)p1; 63 | *cast(long *)p1 = *cast(long *)p2; 64 | *cast(long *)p2 = t; 65 | } 66 | 67 | override @property size_t talign() nothrow pure 68 | { 69 | return long.alignof; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_n.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2016. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Kenji Hara 7 | */ 8 | 9 | /* Copyright Digital Mars 2016. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_n; 15 | 16 | // typeof(null) 17 | 18 | class TypeInfo_n : TypeInfo 19 | { 20 | override string toString() const @safe { return "typeof(null)"; } 21 | 22 | override size_t getHash(in void* p) const 23 | { 24 | return 0; 25 | } 26 | 27 | override bool equals(in void* p1, in void* p2) const @trusted 28 | { 29 | //return *cast(typeof(null)*)p1 is *cast(typeof(null)*)p2; 30 | return true; 31 | } 32 | 33 | override int compare(in void* p1, in void* p2) const @trusted 34 | { 35 | //if (*cast(int*) p1 < *cast(int*) p2) 36 | // return -1; 37 | //else if (*cast(int*) p1 > *cast(int*) p2) 38 | // return 1; 39 | return 0; 40 | } 41 | 42 | override @property size_t tsize() const 43 | { 44 | return typeof(null).sizeof; 45 | } 46 | 47 | override const(void)[] initializer() const @trusted 48 | { 49 | return (cast(void*)null)[0 .. typeof(null).sizeof]; 50 | } 51 | 52 | override void swap(void *p1, void *p2) const @trusted 53 | { 54 | //auto t = *cast(typeof(null)*)p1; 55 | //*cast(typeof(null)*)p1 = *cast(typeof(null)*)p2; 56 | //*cast(typeof(null)*)p2 = t; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_ptr.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_ptr; 15 | 16 | // internal typeinfo for any pointer type 17 | // please keep in sync with TypeInfo_Pointer 18 | 19 | class TypeInfo_P : TypeInfo 20 | { 21 | @trusted: 22 | const: 23 | pure: 24 | nothrow: 25 | 26 | override size_t getHash(in void* p) 27 | { 28 | return cast(size_t)*cast(void**)p; 29 | } 30 | 31 | override bool equals(in void* p1, in void* p2) 32 | { 33 | return *cast(void**)p1 == *cast(void**)p2; 34 | } 35 | 36 | override int compare(in void* p1, in void* p2) 37 | { 38 | if (*cast(void**)p1 < *cast(void**)p2) 39 | return -1; 40 | else if (*cast(void**)p1 > *cast(void**)p2) 41 | return 1; 42 | else 43 | return 0; 44 | } 45 | 46 | override @property size_t tsize() nothrow pure 47 | { 48 | return (void*).sizeof; 49 | } 50 | 51 | override const(void)[] initializer() const @trusted 52 | { 53 | return (cast(void *)null)[0 .. (void*).sizeof]; 54 | } 55 | 56 | override void swap(void *p1, void *p2) 57 | { 58 | void* tmp = *cast(void**)p1; 59 | *cast(void**)p1 = *cast(void**)p2; 60 | *cast(void**)p2 = tmp; 61 | } 62 | 63 | override @property uint flags() nothrow pure const { return 1; } 64 | } 65 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_real.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_real; 15 | 16 | private import rt.util.typeinfo; 17 | 18 | // real 19 | 20 | class TypeInfo_e : TypeInfo 21 | { 22 | pure: 23 | nothrow: 24 | @safe: 25 | 26 | alias F = real; 27 | 28 | override string toString() const { return F.stringof; } 29 | 30 | override size_t getHash(in void* p) const @trusted 31 | { 32 | return Floating!F.hashOf(*cast(F*)p); 33 | } 34 | 35 | override bool equals(in void* p1, in void* p2) const @trusted 36 | { 37 | return Floating!F.equals(*cast(F*)p1, *cast(F*)p2); 38 | } 39 | 40 | override int compare(in void* p1, in void* p2) const @trusted 41 | { 42 | return Floating!F.compare(*cast(F*)p1, *cast(F*)p2); 43 | } 44 | 45 | override @property size_t tsize() const 46 | { 47 | return F.sizeof; 48 | } 49 | 50 | override void swap(void *p1, void *p2) const @trusted 51 | { 52 | F t = *cast(F*)p1; 53 | *cast(F*)p1 = *cast(F*)p2; 54 | *cast(F*)p2 = t; 55 | } 56 | 57 | override const(void)[] initializer() const @trusted 58 | { 59 | static immutable F r; 60 | return (&r)[0 .. 1]; 61 | } 62 | 63 | override @property size_t talign() const 64 | { 65 | return F.alignof; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_short.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_short; 15 | 16 | // short 17 | 18 | class TypeInfo_s : TypeInfo 19 | { 20 | @trusted: 21 | const: 22 | pure: 23 | nothrow: 24 | 25 | override string toString() const pure nothrow @safe { return "short"; } 26 | 27 | override size_t getHash(in void* p) 28 | { 29 | return *cast(short *)p; 30 | } 31 | 32 | override bool equals(in void* p1, in void* p2) 33 | { 34 | return *cast(short *)p1 == *cast(short *)p2; 35 | } 36 | 37 | override int compare(in void* p1, in void* p2) 38 | { 39 | return *cast(short *)p1 - *cast(short *)p2; 40 | } 41 | 42 | override @property size_t tsize() nothrow pure 43 | { 44 | return short.sizeof; 45 | } 46 | 47 | override const(void)[] initializer() const @trusted 48 | { 49 | return (cast(void *)null)[0 .. short.sizeof]; 50 | } 51 | 52 | override void swap(void *p1, void *p2) 53 | { 54 | short t; 55 | 56 | t = *cast(short *)p1; 57 | *cast(short *)p1 = *cast(short *)p2; 58 | *cast(short *)p2 = t; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_ubyte.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_ubyte; 15 | 16 | // ubyte 17 | 18 | class TypeInfo_h : TypeInfo 19 | { 20 | @trusted: 21 | const: 22 | pure: 23 | nothrow: 24 | 25 | override string toString() const pure nothrow @safe { return "ubyte"; } 26 | 27 | override size_t getHash(in void* p) 28 | { 29 | return *cast(ubyte *)p; 30 | } 31 | 32 | override bool equals(in void* p1, in void* p2) 33 | { 34 | return *cast(ubyte *)p1 == *cast(ubyte *)p2; 35 | } 36 | 37 | override int compare(in void* p1, in void* p2) 38 | { 39 | return *cast(ubyte *)p1 - *cast(ubyte *)p2; 40 | } 41 | 42 | override @property size_t tsize() nothrow pure 43 | { 44 | return ubyte.sizeof; 45 | } 46 | 47 | override const(void)[] initializer() const @trusted 48 | { 49 | return (cast(void *)null)[0 .. ubyte.sizeof]; 50 | } 51 | 52 | override void swap(void *p1, void *p2) 53 | { 54 | ubyte t; 55 | 56 | t = *cast(ubyte *)p1; 57 | *cast(ubyte *)p1 = *cast(ubyte *)p2; 58 | *cast(ubyte *)p2 = t; 59 | } 60 | } 61 | 62 | class TypeInfo_b : TypeInfo_h 63 | { 64 | @trusted: 65 | const: 66 | pure: 67 | nothrow: 68 | 69 | override string toString() const pure nothrow @safe { return "bool"; } 70 | } 71 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_ucent.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2015. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2015. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_ucent; 15 | 16 | private import rt.util.hash; 17 | 18 | static if (is(ucent)): 19 | 20 | // ucent 21 | 22 | class TypeInfo_zk : TypeInfo 23 | { 24 | @trusted: 25 | const: 26 | pure: 27 | nothrow: 28 | 29 | override string toString() const pure nothrow @safe { return "ucent"; } 30 | 31 | override size_t getHash(in void* p) 32 | { 33 | return rt.util.hash.hashOf(p[0 .. ucent.sizeof], 0); 34 | } 35 | 36 | override bool equals(in void* p1, in void* p2) 37 | { 38 | return *cast(ucent *)p1 == *cast(ucent *)p2; 39 | } 40 | 41 | override int compare(in void* p1, in void* p2) 42 | { 43 | if (*cast(ucent *)p1 < *cast(ucent *)p2) 44 | return -1; 45 | else if (*cast(ucent *)p1 > *cast(ucent *)p2) 46 | return 1; 47 | return 0; 48 | } 49 | 50 | override @property size_t tsize() nothrow pure 51 | { 52 | return ucent.sizeof; 53 | } 54 | 55 | override const(void)[] initializer() const @trusted 56 | { 57 | return (cast(void *)null)[0 .. ucent.sizeof]; 58 | } 59 | 60 | override void swap(void *p1, void *p2) 61 | { 62 | ucent t; 63 | 64 | t = *cast(ucent *)p1; 65 | *cast(ucent *)p1 = *cast(ucent *)p2; 66 | *cast(ucent *)p2 = t; 67 | } 68 | 69 | override @property size_t talign() nothrow pure 70 | { 71 | return ucent.alignof; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_uint.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_uint; 15 | 16 | // uint 17 | 18 | class TypeInfo_k : TypeInfo 19 | { 20 | @trusted: 21 | const: 22 | pure: 23 | nothrow: 24 | 25 | override string toString() const pure nothrow @safe { return "uint"; } 26 | 27 | override size_t getHash(in void* p) 28 | { 29 | return *cast(uint *)p; 30 | } 31 | 32 | override bool equals(in void* p1, in void* p2) 33 | { 34 | return *cast(uint *)p1 == *cast(uint *)p2; 35 | } 36 | 37 | override int compare(in void* p1, in void* p2) 38 | { 39 | if (*cast(uint*) p1 < *cast(uint*) p2) 40 | return -1; 41 | else if (*cast(uint*) p1 > *cast(uint*) p2) 42 | return 1; 43 | return 0; 44 | } 45 | 46 | override @property size_t tsize() nothrow pure 47 | { 48 | return uint.sizeof; 49 | } 50 | 51 | override const(void)[] initializer() const @trusted 52 | { 53 | return (cast(void *)null)[0 .. uint.sizeof]; 54 | } 55 | 56 | override void swap(void *p1, void *p2) 57 | { 58 | int t; 59 | 60 | t = *cast(uint *)p1; 61 | *cast(uint *)p1 = *cast(uint *)p2; 62 | *cast(uint *)p2 = t; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_ulong.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_ulong; 15 | 16 | private import rt.util.hash; 17 | 18 | // ulong 19 | 20 | class TypeInfo_m : TypeInfo 21 | { 22 | @trusted: 23 | const: 24 | pure: 25 | nothrow: 26 | 27 | override string toString() const pure nothrow @safe { return "ulong"; } 28 | 29 | override size_t getHash(in void* p) 30 | { 31 | return rt.util.hash.hashOf(p[0 .. ulong.sizeof], 0); 32 | } 33 | 34 | override bool equals(in void* p1, in void* p2) 35 | { 36 | return *cast(ulong *)p1 == *cast(ulong *)p2; 37 | } 38 | 39 | override int compare(in void* p1, in void* p2) 40 | { 41 | if (*cast(ulong *)p1 < *cast(ulong *)p2) 42 | return -1; 43 | else if (*cast(ulong *)p1 > *cast(ulong *)p2) 44 | return 1; 45 | return 0; 46 | } 47 | 48 | override @property size_t tsize() nothrow pure 49 | { 50 | return ulong.sizeof; 51 | } 52 | 53 | override const(void)[] initializer() const @trusted 54 | { 55 | return (cast(void *)null)[0 .. ulong.sizeof]; 56 | } 57 | 58 | override void swap(void *p1, void *p2) 59 | { 60 | ulong t; 61 | 62 | t = *cast(ulong *)p1; 63 | *cast(ulong *)p1 = *cast(ulong *)p2; 64 | *cast(ulong *)p2 = t; 65 | } 66 | 67 | override @property size_t talign() nothrow pure 68 | { 69 | return ulong.alignof; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_ushort.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_ushort; 15 | 16 | // ushort 17 | 18 | class TypeInfo_t : TypeInfo 19 | { 20 | @trusted: 21 | const: 22 | pure: 23 | nothrow: 24 | 25 | override string toString() const pure nothrow @safe { return "ushort"; } 26 | 27 | override size_t getHash(in void* p) 28 | { 29 | return *cast(ushort *)p; 30 | } 31 | 32 | override bool equals(in void* p1, in void* p2) 33 | { 34 | return *cast(ushort *)p1 == *cast(ushort *)p2; 35 | } 36 | 37 | override int compare(in void* p1, in void* p2) 38 | { 39 | return *cast(ushort *)p1 - *cast(ushort *)p2; 40 | } 41 | 42 | override @property size_t tsize() nothrow pure 43 | { 44 | return ushort.sizeof; 45 | } 46 | 47 | override const(void)[] initializer() const @trusted 48 | { 49 | return (cast(void *)null)[0 .. ushort.sizeof]; 50 | } 51 | 52 | override void swap(void *p1, void *p2) 53 | { 54 | ushort t; 55 | 56 | t = *cast(ushort *)p1; 57 | *cast(ushort *)p1 = *cast(ushort *)p2; 58 | *cast(ushort *)p2 = t; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_void.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_void; 15 | 16 | // void 17 | 18 | class TypeInfo_v : TypeInfo 19 | { 20 | @trusted: 21 | const: 22 | pure: 23 | nothrow: 24 | 25 | override string toString() const pure nothrow @safe { return "void"; } 26 | 27 | override size_t getHash(in void* p) 28 | { 29 | assert(0); 30 | } 31 | 32 | override bool equals(in void* p1, in void* p2) 33 | { 34 | return *cast(byte *)p1 == *cast(byte *)p2; 35 | } 36 | 37 | override int compare(in void* p1, in void* p2) 38 | { 39 | return *cast(byte *)p1 - *cast(byte *)p2; 40 | } 41 | 42 | override @property size_t tsize() nothrow pure 43 | { 44 | return void.sizeof; 45 | } 46 | 47 | override const(void)[] initializer() const @trusted 48 | { 49 | return (cast(void *)null)[0 .. void.sizeof]; 50 | } 51 | 52 | override void swap(void *p1, void *p2) 53 | { 54 | byte t; 55 | 56 | t = *cast(byte *)p1; 57 | *cast(byte *)p1 = *cast(byte *)p2; 58 | *cast(byte *)p2 = t; 59 | } 60 | 61 | override @property uint flags() nothrow pure 62 | { 63 | return 1; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /rt/rt/typeinfo/ti_wchar.d: -------------------------------------------------------------------------------- 1 | /** 2 | * TypeInfo support code. 3 | * 4 | * Copyright: Copyright Digital Mars 2004 - 2009. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Walter Bright 7 | */ 8 | 9 | /* Copyright Digital Mars 2004 - 2009. 10 | * Distributed under the Boost Software License, Version 1.0. 11 | * (See accompanying file LICENSE or copy at 12 | * http://www.boost.org/LICENSE_1_0.txt) 13 | */ 14 | module rt.typeinfo.ti_wchar; 15 | 16 | // wchar 17 | 18 | class TypeInfo_u : TypeInfo 19 | { 20 | @trusted: 21 | const: 22 | pure: 23 | nothrow: 24 | 25 | override string toString() { return "wchar"; } 26 | 27 | override size_t getHash(in void* p) 28 | { 29 | return *cast(wchar *)p; 30 | } 31 | 32 | override bool equals(in void* p1, in void* p2) 33 | { 34 | return *cast(wchar *)p1 == *cast(wchar *)p2; 35 | } 36 | 37 | override int compare(in void* p1, in void* p2) 38 | { 39 | return *cast(wchar *)p1 - *cast(wchar *)p2; 40 | } 41 | 42 | override @property size_t tsize() 43 | { 44 | return wchar.sizeof; 45 | } 46 | 47 | override void swap(void *p1, void *p2) 48 | { 49 | wchar t; 50 | 51 | t = *cast(wchar *)p1; 52 | *cast(wchar *)p1 = *cast(wchar *)p2; 53 | *cast(wchar *)p2 = t; 54 | } 55 | 56 | override const(void)[] initializer() const @trusted 57 | { 58 | static immutable wchar c; 59 | 60 | return (&c)[0 .. 1]; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /rt/rt/util/container/array.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Array container for internal usage. 3 | * 4 | * Copyright: Copyright Martin Nowak 2013. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Martin Nowak 7 | */ 8 | module rt.util.container.array; 9 | 10 | static import common = rt.util.container.common; 11 | 12 | import core.exception : onOutOfMemoryErrorNoGC; 13 | 14 | struct Array(T) 15 | { 16 | nothrow: 17 | @disable this(this); 18 | 19 | ~this() 20 | { 21 | reset(); 22 | } 23 | 24 | void reset() 25 | { 26 | length = 0; 27 | } 28 | 29 | @property size_t length() const 30 | { 31 | return _length; 32 | } 33 | 34 | @property void length(size_t nlength) 35 | { 36 | import core.checkedint : mulu; 37 | 38 | bool overflow = false; 39 | size_t reqsize = mulu(T.sizeof, nlength, overflow); 40 | if (!overflow) 41 | { 42 | if (nlength < _length) 43 | foreach (ref val; _ptr[nlength .. _length]) common.destroy(val); 44 | _ptr = cast(T*)common.xrealloc(_ptr, reqsize); 45 | if (nlength > _length) 46 | foreach (ref val; _ptr[_length .. nlength]) common.initialize(val); 47 | _length = nlength; 48 | } 49 | else 50 | onOutOfMemoryErrorNoGC(); 51 | 52 | } 53 | 54 | @property bool empty() const 55 | { 56 | return !length; 57 | } 58 | 59 | @property ref inout(T) front() inout 60 | in { assert(!empty); } 61 | do 62 | { 63 | return _ptr[0]; 64 | } 65 | 66 | @property ref inout(T) back() inout 67 | in { assert(!empty); } 68 | do 69 | { 70 | return _ptr[_length - 1]; 71 | } 72 | 73 | ref inout(T) opIndex(size_t idx) inout 74 | in { assert(idx < length); } 75 | do 76 | { 77 | return _ptr[idx]; 78 | } 79 | 80 | inout(T)[] opSlice() inout 81 | { 82 | return _ptr[0 .. _length]; 83 | } 84 | 85 | inout(T)[] opSlice(size_t a, size_t b) inout 86 | in { assert(a < b && b <= length); } 87 | do 88 | { 89 | return _ptr[a .. b]; 90 | } 91 | 92 | alias length opDollar; 93 | 94 | void insertBack()(auto ref T val) 95 | { 96 | import core.checkedint : addu; 97 | 98 | bool overflow = false; 99 | size_t newlength = addu(length, 1, overflow); 100 | if (!overflow) 101 | { 102 | length = newlength; 103 | back = val; 104 | } 105 | else 106 | onOutOfMemoryErrorNoGC(); 107 | } 108 | 109 | void popBack() 110 | { 111 | length = length - 1; 112 | } 113 | 114 | void remove(size_t idx) 115 | in { assert(idx < length); } 116 | do 117 | { 118 | foreach (i; idx .. length - 1) 119 | _ptr[i] = _ptr[i+1]; 120 | popBack(); 121 | } 122 | 123 | void swap(ref Array other) 124 | { 125 | auto ptr = _ptr; 126 | _ptr = other._ptr; 127 | other._ptr = ptr; 128 | immutable len = _length; 129 | _length = other._length; 130 | other._length = len; 131 | } 132 | 133 | invariant 134 | { 135 | assert(!_ptr == !_length); 136 | } 137 | 138 | private: 139 | T* _ptr; 140 | size_t _length; 141 | } 142 | 143 | unittest 144 | { 145 | Array!size_t ary; 146 | 147 | assert(ary[] == []); 148 | ary.insertBack(5); 149 | assert(ary[] == [5]); 150 | assert(ary[$-1] == 5); 151 | ary.popBack(); 152 | assert(ary[] == []); 153 | ary.insertBack(0); 154 | ary.insertBack(1); 155 | assert(ary[] == [0, 1]); 156 | assert(ary[0 .. 1] == [0]); 157 | assert(ary[1 .. 2] == [1]); 158 | assert(ary[$ - 2 .. $] == [0, 1]); 159 | size_t idx; 160 | foreach (val; ary) assert(idx++ == val); 161 | foreach_reverse (val; ary) assert(--idx == val); 162 | foreach (i, val; ary) assert(i == val); 163 | foreach_reverse (i, val; ary) assert(i == val); 164 | 165 | ary.insertBack(2); 166 | ary.remove(1); 167 | assert(ary[] == [0, 2]); 168 | 169 | assert(!ary.empty); 170 | ary.reset(); 171 | assert(ary.empty); 172 | ary.insertBack(0); 173 | assert(!ary.empty); 174 | destroy(ary); 175 | assert(ary.empty); 176 | 177 | // not copyable 178 | static assert(!__traits(compiles, { Array!size_t ary2 = ary; })); 179 | Array!size_t ary2; 180 | static assert(!__traits(compiles, ary = ary2)); 181 | static void foo(Array!size_t copy) {} 182 | static assert(!__traits(compiles, foo(ary))); 183 | 184 | ary2.insertBack(0); 185 | assert(ary.empty); 186 | assert(ary2[] == [0]); 187 | ary.swap(ary2); 188 | assert(ary[] == [0]); 189 | assert(ary2.empty); 190 | } 191 | 192 | unittest 193 | { 194 | alias RC = common.RC; 195 | Array!RC ary; 196 | 197 | size_t cnt; 198 | assert(cnt == 0); 199 | ary.insertBack(RC(&cnt)); 200 | assert(cnt == 1); 201 | ary.insertBack(RC(&cnt)); 202 | assert(cnt == 2); 203 | ary.back = ary.front; 204 | assert(cnt == 2); 205 | ary.popBack(); 206 | assert(cnt == 1); 207 | ary.popBack(); 208 | assert(cnt == 0); 209 | } 210 | 211 | unittest 212 | { 213 | import core.exception; 214 | try 215 | { 216 | // Overflow ary.length. 217 | auto ary = Array!size_t(cast(size_t*)0xdeadbeef, -1); 218 | ary.insertBack(0); 219 | } 220 | catch(OutOfMemoryError) 221 | { 222 | } 223 | try 224 | { 225 | // Overflow requested memory size for common.xrealloc(). 226 | auto ary = Array!size_t(cast(size_t*)0xdeadbeef, -2); 227 | ary.insertBack(0); 228 | } 229 | catch(OutOfMemoryError) 230 | { 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /rt/rt/util/container/common.d: -------------------------------------------------------------------------------- 1 | /** 2 | * Common code for writing containers. 3 | * 4 | * Copyright: Copyright Martin Nowak 2013. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Martin Nowak 7 | */ 8 | module rt.util.container.common; 9 | 10 | import core.stdc.stdlib : malloc, realloc; 11 | public import core.stdc.stdlib : free; 12 | import core.internal.traits : dtorIsNothrow; 13 | nothrow: 14 | 15 | void* xrealloc(void* ptr, size_t sz) nothrow @nogc 16 | { 17 | import core.exception; 18 | 19 | if (!sz) { .free(ptr); return null; } 20 | if (auto nptr = .realloc(ptr, sz)) return nptr; 21 | .free(ptr); onOutOfMemoryErrorNoGC(); 22 | assert(0); 23 | } 24 | 25 | void* xmalloc(size_t sz) nothrow @nogc 26 | { 27 | import core.exception; 28 | if (auto nptr = .malloc(sz)) 29 | return nptr; 30 | onOutOfMemoryErrorNoGC(); 31 | assert(0); 32 | } 33 | 34 | void destroy(T)(ref T t) if (is(T == struct) && dtorIsNothrow!T) 35 | { 36 | scope (failure) assert(0); // nothrow hack 37 | object.destroy(t); 38 | } 39 | 40 | void destroy(T)(ref T t) if (!is(T == struct)) 41 | { 42 | t = T.init; 43 | } 44 | 45 | void initialize(T)(ref T t) if (is(T == struct)) 46 | { 47 | import core.stdc.string; 48 | if(auto p = typeid(T).initializer().ptr) 49 | memcpy(&t, p, T.sizeof); 50 | else 51 | memset(&t, 0, T.sizeof); 52 | } 53 | 54 | void initialize(T)(ref T t) if (!is(T == struct)) 55 | { 56 | t = T.init; 57 | } 58 | 59 | version (unittest) struct RC 60 | { 61 | nothrow: 62 | this(size_t* cnt) { ++*(_cnt = cnt); } 63 | ~this() { if (_cnt) --*_cnt; } 64 | this(this) { if (_cnt) ++*_cnt; } 65 | size_t* _cnt; 66 | } 67 | -------------------------------------------------------------------------------- /rt/rt/util/container/hashtab.d: -------------------------------------------------------------------------------- 1 | /** 2 | * HashTab container for internal usage. 3 | * 4 | * Copyright: Copyright Martin Nowak 2013. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Martin Nowak 7 | */ 8 | module rt.util.container.hashtab; 9 | 10 | import rt.util.container.array; 11 | static import common = rt.util.container.common; 12 | 13 | struct HashTab(Key, Value) 14 | { 15 | static struct Node 16 | { 17 | Key _key; 18 | Value _value; 19 | Node* _next; 20 | } 21 | 22 | @disable this(this); 23 | 24 | ~this() 25 | { 26 | reset(); 27 | } 28 | 29 | void reset() 30 | { 31 | foreach (p; _buckets) 32 | { 33 | while (p !is null) 34 | { 35 | auto pn = p._next; 36 | common.destroy(*p); 37 | common.free(p); 38 | p = pn; 39 | } 40 | } 41 | _buckets.reset(); 42 | _length = 0; 43 | } 44 | 45 | @property size_t length() const 46 | { 47 | return _length; 48 | } 49 | 50 | @property bool empty() const 51 | { 52 | return !_length; 53 | } 54 | 55 | void remove(in Key key) 56 | in { assert(key in this); } 57 | do 58 | { 59 | ensureNotInOpApply(); 60 | 61 | immutable hash = hashOf(key) & mask; 62 | auto pp = &_buckets[hash]; 63 | while (*pp) 64 | { 65 | auto p = *pp; 66 | if (p._key == key) 67 | { 68 | *pp = p._next; 69 | common.destroy(*p); 70 | common.free(p); 71 | if (--_length < _buckets.length && _length >= 4) 72 | shrink(); 73 | return; 74 | } 75 | else 76 | { 77 | pp = &p._next; 78 | } 79 | } 80 | assert(0); 81 | } 82 | 83 | ref inout(Value) opIndex(Key key) inout 84 | { 85 | return *opIn_r(key); 86 | } 87 | 88 | void opIndexAssign(Value value, Key key) 89 | { 90 | *get(key) = value; 91 | } 92 | 93 | inout(Value)* opIn_r(in Key key) inout 94 | { 95 | if (_buckets.length) 96 | { 97 | immutable hash = hashOf(key) & mask; 98 | for (inout(Node)* p = _buckets[hash]; p !is null; p = p._next) 99 | { 100 | if (p._key == key) 101 | return &p._value; 102 | } 103 | } 104 | return null; 105 | } 106 | 107 | int opApply(scope int delegate(ref Key, ref Value) dg) 108 | { 109 | immutable save = _inOpApply; 110 | _inOpApply = true; 111 | scope (exit) _inOpApply = save; 112 | foreach (p; _buckets) 113 | { 114 | while (p !is null) 115 | { 116 | if (auto res = dg(p._key, p._value)) 117 | return res; 118 | p = p._next; 119 | } 120 | } 121 | return 0; 122 | } 123 | 124 | private: 125 | 126 | Value* get(Key key) 127 | { 128 | if (auto p = opIn_r(key)) 129 | return p; 130 | 131 | ensureNotInOpApply(); 132 | 133 | if (!_buckets.length) 134 | _buckets.length = 4; 135 | 136 | immutable hash = hashOf(key) & mask; 137 | auto p = cast(Node*)common.xmalloc(Node.sizeof); 138 | common.initialize(*p); 139 | p._key = key; 140 | p._next = _buckets[hash]; 141 | _buckets[hash] = p; 142 | if (++_length >= 2 * _buckets.length) 143 | grow(); 144 | return &p._value; 145 | } 146 | 147 | static hash_t hashOf(in ref Key key) @trusted 148 | { 149 | import rt.util.hash : hashOf; 150 | static if (is(Key U : U[])) 151 | return hashOf(key, 0); 152 | else 153 | return hashOf((&key)[0 .. 1], 0); 154 | } 155 | 156 | @property hash_t mask() const 157 | { 158 | return _buckets.length - 1; 159 | } 160 | 161 | void grow() 162 | in 163 | { 164 | assert(_buckets.length); 165 | } 166 | do 167 | { 168 | immutable ocnt = _buckets.length; 169 | immutable nmask = 2 * ocnt - 1; 170 | _buckets.length = 2 * ocnt; 171 | for (size_t i = 0; i < ocnt; ++i) 172 | { 173 | auto pp = &_buckets[i]; 174 | while (*pp) 175 | { 176 | auto p = *pp; 177 | 178 | immutable nidx = hashOf(p._key) & nmask; 179 | if (nidx != i) 180 | { 181 | *pp = p._next; 182 | p._next = _buckets[nidx]; 183 | _buckets[nidx] = p; 184 | } 185 | else 186 | { 187 | pp = &p._next; 188 | } 189 | } 190 | } 191 | } 192 | 193 | void shrink() 194 | in 195 | { 196 | assert(_buckets.length >= 2); 197 | } 198 | do 199 | { 200 | immutable ocnt = _buckets.length; 201 | immutable ncnt = ocnt >> 1; 202 | immutable nmask = ncnt - 1; 203 | 204 | for (size_t i = ncnt; i < ocnt; ++i) 205 | { 206 | if (auto tail = _buckets[i]) 207 | { 208 | immutable nidx = i & nmask; 209 | auto pp = &_buckets[nidx]; 210 | while (*pp) 211 | pp = &(*pp)._next; 212 | *pp = tail; 213 | _buckets[i] = null; 214 | } 215 | } 216 | _buckets.length = ncnt; 217 | } 218 | 219 | void ensureNotInOpApply() 220 | { 221 | if (_inOpApply) 222 | assert(0, "Invalid HashTab manipulation during opApply iteration."); 223 | } 224 | 225 | Array!(Node*) _buckets; 226 | size_t _length; 227 | bool _inOpApply; 228 | } 229 | 230 | unittest 231 | { 232 | HashTab!(int, int) tab; 233 | 234 | foreach(i; 0 .. 100) 235 | tab[i] = 100 - i; 236 | 237 | foreach(i; 0 .. 100) 238 | assert(tab[i] == 100 - i); 239 | 240 | foreach (k, v; tab) 241 | assert(v == 100 - k); 242 | 243 | foreach(i; 0 .. 50) 244 | tab.remove(2 * i); 245 | 246 | assert(tab.length == 50); 247 | 248 | foreach(i; 0 .. 50) 249 | assert(tab[2 * i + 1] == 100 - 2 * i - 1); 250 | 251 | assert(tab.length == 50); 252 | 253 | tab.reset(); 254 | assert(tab.empty); 255 | tab[0] = 0; 256 | assert(!tab.empty); 257 | destroy(tab); 258 | assert(tab.empty); 259 | 260 | // not copyable 261 | static assert(!__traits(compiles, { HashTab!(int, int) tab2 = tab; })); 262 | HashTab!(int, int) tab2; 263 | static assert(!__traits(compiles, tab = tab2)); 264 | static void foo(HashTab!(int, int) copy) {} 265 | static assert(!__traits(compiles, foo(tab))); 266 | } 267 | 268 | unittest 269 | { 270 | HashTab!(string, size_t) tab; 271 | 272 | tab["foo"] = 0; 273 | assert(tab["foo"] == 0); 274 | ++tab["foo"]; 275 | assert(tab["foo"] == 1); 276 | tab["foo"]++; 277 | assert(tab["foo"] == 2); 278 | 279 | auto s = "fo"; 280 | s ~= "o"; 281 | assert(tab[s] == 2); 282 | assert(tab.length == 1); 283 | tab[s] -= 2; 284 | assert(tab[s] == 0); 285 | tab["foo"] = 12; 286 | assert(tab[s] == 12); 287 | 288 | tab.remove("foo"); 289 | assert(tab.empty); 290 | } 291 | 292 | unittest 293 | { 294 | alias RC = common.RC; 295 | HashTab!(size_t, RC) tab; 296 | 297 | size_t cnt; 298 | assert(cnt == 0); 299 | tab[0] = RC(&cnt); 300 | assert(cnt == 1); 301 | tab[1] = tab[0]; 302 | assert(cnt == 2); 303 | tab.remove(0); 304 | assert(cnt == 1); 305 | tab.remove(1); 306 | assert(cnt == 0); 307 | } 308 | 309 | unittest 310 | { 311 | import core.exception; 312 | 313 | HashTab!(uint, uint) tab; 314 | foreach (i; 0 .. 5) 315 | tab[i] = i; 316 | bool thrown; 317 | foreach (k, v; tab) 318 | { 319 | try 320 | { 321 | if (k == 3) tab.remove(k); 322 | } 323 | catch (AssertError e) 324 | { 325 | thrown = true; 326 | } 327 | } 328 | assert(thrown); 329 | assert(tab[3] == 3); 330 | } 331 | -------------------------------------------------------------------------------- /rt/rt/util/hash.d: -------------------------------------------------------------------------------- 1 | /** 2 | * The default hash implementation. 3 | * 4 | * Copyright: Copyright Sean Kelly 2009 - 2016. 5 | * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 | * Authors: Sean Kelly 7 | * Source: $(DRUNTIMESRC src/rt/util/_hash.d) 8 | */ 9 | module rt.util.hash; 10 | 11 | 12 | version( X86 ) 13 | version = AnyX86; 14 | version( X86_64 ) 15 | version = AnyX86; 16 | version( AnyX86 ) 17 | version = HasUnalignedOps; 18 | 19 | 20 | @trusted pure nothrow @nogc 21 | size_t hashOf( const(void)[] buf, size_t seed ) 22 | { 23 | /* 24 | * This is Paul Hsieh's SuperFastHash algorithm, described here: 25 | * http://www.azillionmonkeys.com/qed/hash.html 26 | * It is protected by the following open source license: 27 | * http://www.azillionmonkeys.com/qed/weblicense.html 28 | */ 29 | static uint get16bits( const (ubyte)* x ) pure nothrow @nogc 30 | { 31 | // CTFE doesn't support casting ubyte* -> ushort*, so revert to 32 | // per-byte access when in CTFE. 33 | version( HasUnalignedOps ) 34 | { 35 | if (!__ctfe) 36 | return *cast(ushort*) x; 37 | } 38 | 39 | return ((cast(uint) x[1]) << 8) + (cast(uint) x[0]); 40 | } 41 | 42 | // NOTE: SuperFastHash normally starts with a zero hash value. The seed 43 | // value was incorporated to allow chaining. 44 | auto data = cast(const(ubyte)*) buf.ptr; 45 | auto len = buf.length; 46 | auto hash = seed; 47 | 48 | if( len == 0 || data is null ) 49 | return 0; 50 | 51 | int rem = len & 3; 52 | len >>= 2; 53 | 54 | for( ; len > 0; len-- ) 55 | { 56 | hash += get16bits( data ); 57 | auto tmp = (get16bits( data + 2 ) << 11) ^ hash; 58 | hash = (hash << 16) ^ tmp; 59 | data += 2 * ushort.sizeof; 60 | hash += hash >> 11; 61 | } 62 | 63 | switch( rem ) 64 | { 65 | case 3: hash += get16bits( data ); 66 | hash ^= hash << 16; 67 | hash ^= data[ushort.sizeof] << 18; 68 | hash += hash >> 11; 69 | break; 70 | case 2: hash += get16bits( data ); 71 | hash ^= hash << 11; 72 | hash += hash >> 17; 73 | break; 74 | case 1: hash += *data; 75 | hash ^= hash << 10; 76 | hash += hash >> 1; 77 | break; 78 | default: 79 | break; 80 | } 81 | 82 | /* Force "avalanching" of final 127 bits */ 83 | hash ^= hash << 3; 84 | hash += hash >> 5; 85 | hash ^= hash << 4; 86 | hash += hash >> 17; 87 | hash ^= hash << 25; 88 | hash += hash >> 6; 89 | 90 | return hash; 91 | } 92 | 93 | unittest 94 | { 95 | enum test_str = "Sample string"; 96 | size_t hashval = hashOf(test_str, 5); 97 | 98 | //import core.stdc.stdio; 99 | //printf("hashval = %lld\n", cast(long)hashval); 100 | 101 | if (hashval.sizeof == 4) 102 | assert(hashval == 528740845); 103 | else if (hashval.sizeof == 8) 104 | assert(hashval == 8106800467257150594L); 105 | else 106 | assert(0); 107 | } 108 | -------------------------------------------------------------------------------- /rt/rt/util/typeinfo.d: -------------------------------------------------------------------------------- 1 | /** 2 | * This module contains utilities for TypeInfo implementation. 3 | * 4 | * Copyright: Copyright Kenji Hara 2014-. 5 | * License: Boost License 1.0. 6 | * Authors: Kenji Hara 7 | */ 8 | module rt.util.typeinfo; 9 | 10 | private enum isX87Real(T) = (T.mant_dig == 64 && T.max_exp == 16384); 11 | 12 | template Floating(T) 13 | if (is(T == float) || is(T == double) || is(T == real)) 14 | { 15 | pure nothrow @safe: 16 | 17 | bool equals(T f1, T f2) 18 | { 19 | return f1 == f2; 20 | } 21 | 22 | int compare(T d1, T d2) 23 | { 24 | if (d1 != d1 || d2 != d2) // if either are NaN 25 | { 26 | if (d1 != d1) 27 | { 28 | if (d2 != d2) 29 | return 0; 30 | return -1; 31 | } 32 | return 1; 33 | } 34 | return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1); 35 | } 36 | 37 | size_t hashOf(T value) @trusted 38 | { 39 | if (value == 0) // +0.0 and -0.0 40 | value = 0; 41 | 42 | static if (is(T == float)) // special case? 43 | return *cast(uint*)&value; 44 | else 45 | { 46 | import rt.util.hash; 47 | static if (isX87Real!T) // Only consider the non-padding bytes. 48 | return rt.util.hash.hashOf((cast(void*) &value)[0 .. 10], 0); 49 | else 50 | return rt.util.hash.hashOf((&value)[0 .. 1], 0); 51 | } 52 | } 53 | } 54 | template Floating(T) 55 | if (is(T == cfloat) || is(T == cdouble) || is(T == creal)) 56 | { 57 | pure nothrow @safe: 58 | 59 | bool equals(T f1, T f2) 60 | { 61 | return f1 == f2; 62 | } 63 | 64 | int compare(T f1, T f2) 65 | { 66 | int result; 67 | 68 | if (f1.re < f2.re) 69 | result = -1; 70 | else if (f1.re > f2.re) 71 | result = 1; 72 | else if (f1.im < f2.im) 73 | result = -1; 74 | else if (f1.im > f2.im) 75 | result = 1; 76 | else 77 | result = 0; 78 | return result; 79 | } 80 | 81 | size_t hashOf(T value) @trusted 82 | { 83 | if (value == 0 + 0i) 84 | value = 0 + 0i; 85 | import rt.util.hash; 86 | static if (isX87Real!(typeof(T.init.re))) // Only consider the non-padding bytes. 87 | { 88 | real* ptr = cast(real*) &value; 89 | return rt.util.hash.hashOf((cast(void*) &ptr[0])[0 .. 10], 90 | rt.util.hash.hashOf((cast(void*) &ptr[1])[0 .. 10], 0)); 91 | } 92 | else 93 | return rt.util.hash.hashOf((&value)[0 .. 1], 0); 94 | } 95 | } 96 | 97 | template Array(T) 98 | if (is(T == float) || is(T == double) || is(T == real) || 99 | is(T == cfloat) || is(T == cdouble) || is(T == creal)) 100 | { 101 | pure nothrow @safe: 102 | 103 | bool equals(T[] s1, T[] s2) 104 | { 105 | size_t len = s1.length; 106 | if (len != s2.length) 107 | return false; 108 | for (size_t u = 0; u < len; u++) 109 | { 110 | if (!Floating!T.equals(s1[u], s2[u])) 111 | return false; 112 | } 113 | return true; 114 | } 115 | 116 | int compare(T[] s1, T[] s2) 117 | { 118 | size_t len = s1.length; 119 | if (s2.length < len) 120 | len = s2.length; 121 | for (size_t u = 0; u < len; u++) 122 | { 123 | if (int c = Floating!T.compare(s1[u], s2[u])) 124 | return c; 125 | } 126 | if (s1.length < s2.length) 127 | return -1; 128 | else if (s1.length > s2.length) 129 | return 1; 130 | return 0; 131 | } 132 | 133 | size_t hashOf(T[] value) 134 | { 135 | size_t h = 0; 136 | foreach (e; value) 137 | h += Floating!T.hashOf(e); 138 | return h; 139 | } 140 | } 141 | 142 | version(unittest) 143 | { 144 | alias TypeTuple(T...) = T; 145 | } 146 | unittest 147 | { 148 | // Bugzilla 13052 149 | 150 | static struct SX(F) { F f; } 151 | TypeInfo ti; 152 | 153 | // real types 154 | foreach (F; TypeTuple!(float, double, real)) 155 | (){ // workaround #2396 156 | alias S = SX!F; 157 | F f1 = +0.0, 158 | f2 = -0.0; 159 | 160 | assert(f1 == f2); 161 | assert(f1 !is f2); 162 | ti = typeid(F); 163 | assert(ti.getHash(&f1) == ti.getHash(&f2)); 164 | 165 | F[] a1 = [f1, f1, f1]; 166 | F[] a2 = [f2, f2, f2]; 167 | assert(a1 == a2); 168 | assert(a1 !is a2); 169 | ti = typeid(F[]); 170 | assert(ti.getHash(&a1) == ti.getHash(&a2)); 171 | 172 | F[][] aa1 = [a1, a1, a1]; 173 | F[][] aa2 = [a2, a2, a2]; 174 | assert(aa1 == aa2); 175 | assert(aa1 !is aa2); 176 | ti = typeid(F[][]); 177 | assert(ti.getHash(&aa1) == ti.getHash(&aa2)); 178 | 179 | S s1 = {f1}, 180 | s2 = {f2}; 181 | assert(s1 == s2); 182 | assert(s1 !is s2); 183 | ti = typeid(S); 184 | assert(ti.getHash(&s1) == ti.getHash(&s2)); 185 | 186 | S[] da1 = [S(f1), S(f1), S(f1)], 187 | da2 = [S(f2), S(f2), S(f2)]; 188 | assert(da1 == da2); 189 | assert(da1 !is da2); 190 | ti = typeid(S[]); 191 | assert(ti.getHash(&da1) == ti.getHash(&da2)); 192 | 193 | S[3] sa1 = {f1}, 194 | sa2 = {f2}; 195 | assert(sa1 == sa2); 196 | assert(sa1[] !is sa2[]); 197 | ti = typeid(S[3]); 198 | assert(ti.getHash(&sa1) == ti.getHash(&sa2)); 199 | }(); 200 | 201 | // imaginary types 202 | foreach (F; TypeTuple!(ifloat, idouble, ireal)) 203 | (){ // workaround #2396 204 | alias S = SX!F; 205 | F f1 = +0.0i, 206 | f2 = -0.0i; 207 | 208 | assert(f1 == f2); 209 | assert(f1 !is f2); 210 | ti = typeid(F); 211 | assert(ti.getHash(&f1) == ti.getHash(&f2)); 212 | 213 | F[] a1 = [f1, f1, f1]; 214 | F[] a2 = [f2, f2, f2]; 215 | assert(a1 == a2); 216 | assert(a1 !is a2); 217 | ti = typeid(F[]); 218 | assert(ti.getHash(&a1) == ti.getHash(&a2)); 219 | 220 | F[][] aa1 = [a1, a1, a1]; 221 | F[][] aa2 = [a2, a2, a2]; 222 | assert(aa1 == aa2); 223 | assert(aa1 !is aa2); 224 | ti = typeid(F[][]); 225 | assert(ti.getHash(&aa1) == ti.getHash(&aa2)); 226 | 227 | S s1 = {f1}, 228 | s2 = {f2}; 229 | assert(s1 == s2); 230 | assert(s1 !is s2); 231 | ti = typeid(S); 232 | assert(ti.getHash(&s1) == ti.getHash(&s2)); 233 | 234 | S[] da1 = [S(f1), S(f1), S(f1)], 235 | da2 = [S(f2), S(f2), S(f2)]; 236 | assert(da1 == da2); 237 | assert(da1 !is da2); 238 | ti = typeid(S[]); 239 | assert(ti.getHash(&da1) == ti.getHash(&da2)); 240 | 241 | S[3] sa1 = {f1}, 242 | sa2 = {f2}; 243 | assert(sa1 == sa2); 244 | assert(sa1[] !is sa2[]); 245 | ti = typeid(S[3]); 246 | assert(ti.getHash(&sa1) == ti.getHash(&sa2)); 247 | }(); 248 | 249 | // complex types 250 | foreach (F; TypeTuple!(cfloat, cdouble, creal)) 251 | (){ // workaround #2396 252 | alias S = SX!F; 253 | F[4] f = [+0.0 + 0.0i, 254 | +0.0 - 0.0i, 255 | -0.0 + 0.0i, 256 | -0.0 - 0.0i]; 257 | 258 | foreach (i, f1; f) foreach (j, f2; f) if (i != j) 259 | { 260 | assert(f1 == 0 + 0i); 261 | 262 | assert(f1 == f2); 263 | assert(f1 !is f2); 264 | ti = typeid(F); 265 | assert(ti.getHash(&f1) == ti.getHash(&f2)); 266 | 267 | F[] a1 = [f1, f1, f1]; 268 | F[] a2 = [f2, f2, f2]; 269 | assert(a1 == a2); 270 | assert(a1 !is a2); 271 | ti = typeid(F[]); 272 | assert(ti.getHash(&a1) == ti.getHash(&a2)); 273 | 274 | F[][] aa1 = [a1, a1, a1]; 275 | F[][] aa2 = [a2, a2, a2]; 276 | assert(aa1 == aa2); 277 | assert(aa1 !is aa2); 278 | ti = typeid(F[][]); 279 | assert(ti.getHash(&aa1) == ti.getHash(&aa2)); 280 | 281 | S s1 = {f1}, 282 | s2 = {f2}; 283 | assert(s1 == s2); 284 | assert(s1 !is s2); 285 | ti = typeid(S); 286 | assert(ti.getHash(&s1) == ti.getHash(&s2)); 287 | 288 | S[] da1 = [S(f1), S(f1), S(f1)], 289 | da2 = [S(f2), S(f2), S(f2)]; 290 | assert(da1 == da2); 291 | assert(da1 !is da2); 292 | ti = typeid(S[]); 293 | assert(ti.getHash(&da1) == ti.getHash(&da2)); 294 | 295 | S[3] sa1 = {f1}, 296 | sa2 = {f2}; 297 | assert(sa1 == sa2); 298 | assert(sa1[] !is sa2[]); 299 | ti = typeid(S[3]); 300 | assert(ti.getHash(&sa1) == ti.getHash(&sa2)); 301 | } 302 | }(); 303 | } 304 | -------------------------------------------------------------------------------- /rt/runtime.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /////////////////////////////////////////////////////////////////////////////// 5 | 6 | void not_implemented(const char* file, int line) 7 | { 8 | printf("Not implemented: %s(%d)\n", file, line); 9 | exit(123); 10 | } 11 | 12 | #define NOT_IMPLEMENTED not_implemented(__FILE__, __LINE__) 13 | 14 | /////////////////////////////////////////////////////////////////////////////// 15 | // make link work. will most probably crash if actually used during runtime. 16 | // can't get rid of those, seems to be refered-to by compiler-inserted code 17 | int _D10TypeInfo_v6__initZ; 18 | int _D10TypeInfo_m6__initZ; 19 | int _D11TypeInfo_Ai6__initZ; 20 | void _d_throw_exception() { NOT_IMPLEMENTED; } 21 | /////////////////////////////////////////////////////////////////////////////// 22 | 23 | -------------------------------------------------------------------------------- /rt/std/experimental/allocator/mallocator.d: -------------------------------------------------------------------------------- 1 | // Written in the D programming language. 2 | /** 3 | The C heap allocator. 4 | 5 | Source: $(PHOBOSSRC std/experimental/allocator/_mallocator.d) 6 | */ 7 | module std.experimental.allocator.mallocator; 8 | import std.experimental.allocator.common; 9 | 10 | /** 11 | The C heap allocator. 12 | */ 13 | struct Mallocator 14 | { 15 | @system unittest { testAllocator!(() => Mallocator.instance); } 16 | 17 | /** 18 | The alignment is a static constant equal to $(D platformAlignment), which 19 | ensures proper alignment for any D data type. 20 | */ 21 | enum uint alignment = platformAlignment; 22 | 23 | /** 24 | Standard allocator methods per the semantics defined above. The 25 | $(D deallocate) and $(D reallocate) methods are $(D @system) because they 26 | may move memory around, leaving dangling pointers in user code. Somewhat 27 | paradoxically, $(D malloc) is $(D @safe) but that's only useful to safe 28 | programs that can afford to leak memory allocated. 29 | */ 30 | @trusted @nogc nothrow 31 | void[] allocate(size_t bytes) shared 32 | { 33 | import core.stdc.stdlib : malloc; 34 | if (!bytes) return null; 35 | auto p = malloc(bytes); 36 | return p ? p[0 .. bytes] : null; 37 | } 38 | 39 | /// Ditto 40 | @system @nogc nothrow 41 | bool deallocate(void[] b) shared 42 | { 43 | import core.stdc.stdlib : free; 44 | free(b.ptr); 45 | return true; 46 | } 47 | 48 | /// Ditto 49 | @system @nogc nothrow 50 | bool reallocate(ref void[] b, size_t s) shared 51 | { 52 | import core.stdc.stdlib : realloc; 53 | if (!s) 54 | { 55 | // fuzzy area in the C standard, see http://goo.gl/ZpWeSE 56 | // so just deallocate and nullify the pointer 57 | deallocate(b); 58 | b = null; 59 | return true; 60 | } 61 | auto p = cast(ubyte*) realloc(b.ptr, s); 62 | if (!p) return false; 63 | b = p[0 .. s]; 64 | return true; 65 | } 66 | 67 | /** 68 | Returns the global instance of this allocator type. The C heap allocator is 69 | thread-safe, therefore all of its methods and `it` itself are 70 | $(D shared). 71 | */ 72 | static shared Mallocator instance; 73 | } 74 | 75 | /// 76 | @nogc @system nothrow unittest 77 | { 78 | auto buffer = Mallocator.instance.allocate(1024 * 1024 * 4); 79 | scope(exit) Mallocator.instance.deallocate(buffer); 80 | //... 81 | } 82 | 83 | @nogc @system nothrow unittest 84 | { 85 | @nogc nothrow 86 | static void test(A)() 87 | { 88 | int* p = null; 89 | p = cast(int*) A.instance.allocate(int.sizeof); 90 | scope(exit) () nothrow @nogc { A.instance.deallocate(p[0 .. int.sizeof]); }(); 91 | *p = 42; 92 | assert(*p == 42); 93 | } 94 | test!Mallocator(); 95 | } 96 | 97 | @nogc @system nothrow unittest 98 | { 99 | static void test(A)() 100 | { 101 | import std.experimental.allocator : make; 102 | Object p = null; 103 | p = A.instance.make!Object(); 104 | assert(p !is null); 105 | } 106 | 107 | test!Mallocator(); 108 | } 109 | 110 | version (Windows) 111 | { 112 | // DMD Win 32 bit, DigitalMars C standard library misses the _aligned_xxx 113 | // functions family (snn.lib) 114 | version(CRuntime_DigitalMars) 115 | { 116 | // Helper to cast the infos written before the aligned pointer 117 | // this header keeps track of the size (required to realloc) and of 118 | // the base ptr (required to free). 119 | private struct AlignInfo 120 | { 121 | void* basePtr; 122 | size_t size; 123 | 124 | @nogc nothrow 125 | static AlignInfo* opCall(void* ptr) 126 | { 127 | return cast(AlignInfo*) (ptr - AlignInfo.sizeof); 128 | } 129 | } 130 | 131 | @nogc nothrow 132 | private void* _aligned_malloc(size_t size, size_t alignment) 133 | { 134 | import std.c.stdlib : malloc; 135 | size_t offset = alignment + size_t.sizeof * 2 - 1; 136 | 137 | // unaligned chunk 138 | void* basePtr = malloc(size + offset); 139 | if (!basePtr) return null; 140 | 141 | // get aligned location within the chunk 142 | void* alignedPtr = cast(void**)((cast(size_t)(basePtr) + offset) 143 | & ~(alignment - 1)); 144 | 145 | // write the header before the aligned pointer 146 | AlignInfo* head = AlignInfo(alignedPtr); 147 | head.basePtr = basePtr; 148 | head.size = size; 149 | 150 | return alignedPtr; 151 | } 152 | 153 | @nogc nothrow 154 | private void* _aligned_realloc(void* ptr, size_t size, size_t alignment) 155 | { 156 | import std.c.stdlib : free; 157 | import std.c.string : memcpy; 158 | 159 | if (!ptr) return _aligned_malloc(size, alignment); 160 | 161 | // gets the header from the exising pointer 162 | AlignInfo* head = AlignInfo(ptr); 163 | 164 | // gets a new aligned pointer 165 | void* alignedPtr = _aligned_malloc(size, alignment); 166 | if (!alignedPtr) 167 | { 168 | //to https://msdn.microsoft.com/en-us/library/ms235462.aspx 169 | //see Return value: in this case the original block is unchanged 170 | return null; 171 | } 172 | 173 | // copy exising data 174 | memcpy(alignedPtr, ptr, head.size); 175 | free(head.basePtr); 176 | 177 | return alignedPtr; 178 | } 179 | 180 | @nogc nothrow 181 | private void _aligned_free(void *ptr) 182 | { 183 | import std.c.stdlib : free; 184 | if (!ptr) return; 185 | AlignInfo* head = AlignInfo(ptr); 186 | free(head.basePtr); 187 | } 188 | 189 | } 190 | // DMD Win 64 bit, uses microsoft standard C library which implements them 191 | else 192 | { 193 | @nogc nothrow private extern(C) void* _aligned_malloc(size_t, size_t); 194 | @nogc nothrow private extern(C) void _aligned_free(void *memblock); 195 | @nogc nothrow private extern(C) void* _aligned_realloc(void *, size_t, size_t); 196 | } 197 | } 198 | 199 | /** 200 | Aligned allocator using OS-specific primitives, under a uniform API. 201 | */ 202 | version (dscripten) {} else 203 | struct AlignedMallocator 204 | { 205 | @system unittest { testAllocator!(() => typeof(this).instance); } 206 | 207 | /** 208 | The default alignment is $(D platformAlignment). 209 | */ 210 | enum uint alignment = platformAlignment; 211 | 212 | /** 213 | Forwards to $(D alignedAllocate(bytes, platformAlignment)). 214 | */ 215 | @trusted @nogc nothrow 216 | void[] allocate(size_t bytes) shared 217 | { 218 | if (!bytes) return null; 219 | return alignedAllocate(bytes, alignment); 220 | } 221 | 222 | /** 223 | Uses $(HTTP man7.org/linux/man-pages/man3/posix_memalign.3.html, 224 | $(D posix_memalign)) on Posix and 225 | $(HTTP msdn.microsoft.com/en-us/library/8z34s9c6(v=vs.80).aspx, 226 | $(D __aligned_malloc)) on Windows. 227 | */ 228 | version(Posix) 229 | @trusted @nogc nothrow 230 | void[] alignedAllocate(size_t bytes, uint a) shared 231 | { 232 | import core.stdc.errno : ENOMEM, EINVAL; 233 | import core.sys.posix.stdlib : posix_memalign; 234 | assert(a.isGoodDynamicAlignment); 235 | void* result; 236 | auto code = posix_memalign(&result, a, bytes); 237 | if (code == ENOMEM) 238 | return null; 239 | 240 | else if (code == EINVAL) 241 | { 242 | assert(0, "AlignedMallocator.alignment is not a power of two " 243 | ~"multiple of (void*).sizeof, according to posix_memalign!"); 244 | } 245 | else if (code != 0) 246 | assert(0, "posix_memalign returned an unknown code!"); 247 | 248 | else 249 | return result[0 .. bytes]; 250 | } 251 | else version(Windows) 252 | @trusted @nogc nothrow 253 | void[] alignedAllocate(size_t bytes, uint a) shared 254 | { 255 | auto result = _aligned_malloc(bytes, a); 256 | return result ? result[0 .. bytes] : null; 257 | } 258 | else static assert(0); 259 | 260 | /** 261 | Calls $(D free(b.ptr)) on Posix and 262 | $(HTTP msdn.microsoft.com/en-US/library/17b5h8td(v=vs.80).aspx, 263 | $(D __aligned_free(b.ptr))) on Windows. 264 | */ 265 | version (Posix) 266 | @system @nogc nothrow 267 | bool deallocate(void[] b) shared 268 | { 269 | import core.stdc.stdlib : free; 270 | free(b.ptr); 271 | return true; 272 | } 273 | else version (Windows) 274 | @system @nogc nothrow 275 | bool deallocate(void[] b) shared 276 | { 277 | _aligned_free(b.ptr); 278 | return true; 279 | } 280 | else static assert(0); 281 | 282 | /** 283 | Forwards to $(D alignedReallocate(b, newSize, platformAlignment)). 284 | Should be used with bocks obtained with `allocate` otherwise the custom 285 | alignment passed with `alignedAllocate` can be lost. 286 | */ 287 | @system @nogc nothrow 288 | bool reallocate(ref void[] b, size_t newSize) shared 289 | { 290 | return alignedReallocate(b, newSize, alignment); 291 | } 292 | 293 | /** 294 | On Posix there is no `realloc` for aligned memory, so `alignedReallocate` emulates 295 | the needed behavior by using `alignedAllocate` to get a new block. The existing 296 | block is copied to the new block and then freed. 297 | On Windows, calls $(HTTPS msdn.microsoft.com/en-us/library/y69db7sx.aspx, 298 | $(D __aligned_realloc(b.ptr, newSize, a))). 299 | */ 300 | version (Windows) 301 | @system @nogc nothrow 302 | bool alignedReallocate(ref void[] b, size_t s, uint a) shared 303 | { 304 | if (!s) 305 | { 306 | deallocate(b); 307 | b = null; 308 | return true; 309 | } 310 | auto p = cast(ubyte*) _aligned_realloc(b.ptr, s, a); 311 | if (!p) return false; 312 | b = p[0 .. s]; 313 | return true; 314 | } 315 | 316 | /// ditto 317 | version (Posix) 318 | @system @nogc nothrow 319 | bool alignedReallocate(ref void[] b, size_t s, uint a) shared 320 | { 321 | if (!s) 322 | { 323 | deallocate(b); 324 | b = null; 325 | return true; 326 | } 327 | auto p = alignedAllocate(s, a); 328 | if (!p.ptr) 329 | { 330 | return false; 331 | } 332 | import std.algorithm.comparison : min; 333 | const upTo = min(s, b.length); 334 | p[0 .. upTo] = b[0 .. upTo]; 335 | deallocate(b); 336 | b = p; 337 | return true; 338 | } 339 | 340 | /** 341 | Returns the global instance of this allocator type. The C heap allocator is 342 | thread-safe, therefore all of its methods and `instance` itself are 343 | $(D shared). 344 | */ 345 | static shared AlignedMallocator instance; 346 | } 347 | 348 | /// 349 | @nogc @system nothrow unittest 350 | { 351 | auto buffer = AlignedMallocator.instance.alignedAllocate(1024 * 1024 * 4, 352 | 128); 353 | scope(exit) AlignedMallocator.instance.deallocate(buffer); 354 | //... 355 | } 356 | 357 | version(unittest) version(CRuntime_DigitalMars) 358 | @nogc nothrow 359 | size_t addr(ref void* ptr) { return cast(size_t) ptr; } 360 | 361 | version(Posix) 362 | @nogc @system nothrow unittest 363 | { 364 | // 16398 : test the "pseudo" alignedReallocate for Posix 365 | void[] s = AlignedMallocator.instance.alignedAllocate(16, 32); 366 | (cast(ubyte[]) s)[] = ubyte(1); 367 | AlignedMallocator.instance.alignedReallocate(s, 32, 32); 368 | ubyte[16] o; 369 | o[] = 1; 370 | assert((cast(ubyte[]) s)[0 .. 16] == o); 371 | AlignedMallocator.instance.alignedReallocate(s, 4, 32); 372 | assert((cast(ubyte[]) s)[0 .. 3] == o[0 .. 3]); 373 | AlignedMallocator.instance.alignedReallocate(s, 128, 32); 374 | assert((cast(ubyte[]) s)[0 .. 3] == o[0 .. 3]); 375 | AlignedMallocator.instance.deallocate(s); 376 | 377 | void[] c; 378 | AlignedMallocator.instance.alignedReallocate(c, 32, 32); 379 | assert(c.ptr); 380 | 381 | assert(!AlignedMallocator.instance.alignedReallocate(c, size_t.max, 4096)); 382 | AlignedMallocator.instance.deallocate(c); 383 | } 384 | 385 | version(CRuntime_DigitalMars) 386 | @nogc @system nothrow unittest 387 | { 388 | void* m; 389 | 390 | m = _aligned_malloc(16, 0x10); 391 | if (m) 392 | { 393 | assert((m.addr & 0xF) == 0); 394 | _aligned_free(m); 395 | } 396 | 397 | m = _aligned_malloc(16, 0x100); 398 | if (m) 399 | { 400 | assert((m.addr & 0xFF) == 0); 401 | _aligned_free(m); 402 | } 403 | 404 | m = _aligned_malloc(16, 0x1000); 405 | if (m) 406 | { 407 | assert((m.addr & 0xFFF) == 0); 408 | _aligned_free(m); 409 | } 410 | 411 | m = _aligned_malloc(16, 0x10); 412 | if (m) 413 | { 414 | assert((cast(size_t) m & 0xF) == 0); 415 | m = _aligned_realloc(m, 32, 0x10000); 416 | if (m) assert((m.addr & 0xFFFF) == 0); 417 | _aligned_free(m); 418 | } 419 | 420 | m = _aligned_malloc(8, 0x10); 421 | if (m) 422 | { 423 | *cast(ulong*) m = 0X01234567_89ABCDEF; 424 | m = _aligned_realloc(m, 0x800, 0x1000); 425 | if (m) assert(*cast(ulong*) m == 0X01234567_89ABCDEF); 426 | _aligned_free(m); 427 | } 428 | } 429 | -------------------------------------------------------------------------------- /rt/std/system.d: -------------------------------------------------------------------------------- 1 | // Written in the D programming language. 2 | 3 | /** 4 | * Information about the target operating system, environment, and CPU. 5 | * 6 | * Copyright: Copyright Digital Mars 2000 - 2011 7 | * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 8 | * Authors: $(HTTP digitalmars.com, Walter Bright) and Jonathan M Davis 9 | * Source: $(PHOBOSSRC std/_system.d) 10 | */ 11 | module std.system; 12 | 13 | immutable 14 | { 15 | /++ 16 | Operating system. 17 | 18 | Note: 19 | This is for cases where you need a value representing the OS at 20 | runtime. If you're doing something which should compile differently 21 | on different OSes, then please use $(D version(Windows)), 22 | $(D version(linux)), etc. 23 | 24 | See_Also: 25 | $(DDSUBLINK spec/version,PredefinedVersions, Predefined Versions) 26 | +/ 27 | enum OS 28 | { 29 | win32 = 1, /// Microsoft 32 bit Windows systems 30 | win64, /// Microsoft 64 bit Windows systems 31 | linux, /// All Linux Systems 32 | osx, /// Mac OS X 33 | freeBSD, /// FreeBSD 34 | netBSD, /// NetBSD 35 | solaris, /// Solaris 36 | android, /// Android 37 | otherPosix /// Other Posix Systems 38 | } 39 | 40 | /// The OS that the program was compiled for. 41 | version(Win32) OS os = OS.win32; 42 | else version(Win64) OS os = OS.win64; 43 | else version(Android) OS os = OS.android; 44 | else version(linux) OS os = OS.linux; 45 | else version(OSX) OS os = OS.osx; 46 | else version(FreeBSD) OS os = OS.freeBSD; 47 | else version(NetBSD) OS os = OS.netBSD; 48 | else version(Posix) OS os = OS.otherPosix; 49 | else version(dscripten) OS os = OS.otherPosix; 50 | else static assert(0, "Unknown OS."); 51 | 52 | /++ 53 | Byte order endianness. 54 | 55 | Note: 56 | This is intended for cases where you need to deal with endianness at 57 | runtime. If you're doing something which should compile differently 58 | depending on whether you're compiling on a big endian or little 59 | endian machine, then please use $(D version(BigEndian)) and 60 | $(D version(LittleEndian)). 61 | 62 | See_Also: 63 | $(DDSUBLINK spec/version,PredefinedVersions, Predefined Versions) 64 | +/ 65 | enum Endian 66 | { 67 | bigEndian, /// Big endian byte order 68 | littleEndian /// Little endian byte order 69 | } 70 | 71 | /// The endianness that the program was compiled for. 72 | version(LittleEndian) Endian endian = Endian.littleEndian; 73 | else Endian endian = Endian.bigEndian; 74 | } 75 | 76 | -------------------------------------------------------------------------------- /rt/stdx/allocator/mallocator.d: -------------------------------------------------------------------------------- 1 | /// 2 | module stdx.allocator.mallocator; 3 | import stdx.allocator.common; 4 | 5 | /** 6 | The C heap allocator. 7 | */ 8 | struct Mallocator 9 | { 10 | @system unittest { testAllocator!(() => Mallocator.instance); } 11 | 12 | /** 13 | The alignment is a static constant equal to $(D platformAlignment), which 14 | ensures proper alignment for any D data type. 15 | */ 16 | enum uint alignment = platformAlignment; 17 | 18 | /** 19 | Standard allocator methods per the semantics defined above. The 20 | $(D deallocate) and $(D reallocate) methods are $(D @system) because they 21 | may move memory around, leaving dangling pointers in user code. Somewhat 22 | paradoxically, $(D malloc) is $(D @safe) but that's only useful to safe 23 | programs that can afford to leak memory allocated. 24 | */ 25 | @trusted @nogc nothrow 26 | void[] allocate(size_t bytes) shared 27 | { 28 | import core.stdc.stdlib : malloc; 29 | if (!bytes) return null; 30 | auto p = malloc(bytes); 31 | return p ? p[0 .. bytes] : null; 32 | } 33 | 34 | /// Ditto 35 | @system @nogc nothrow 36 | bool deallocate(void[] b) shared 37 | { 38 | import core.stdc.stdlib : free; 39 | free(b.ptr); 40 | return true; 41 | } 42 | 43 | /// Ditto 44 | @system @nogc nothrow 45 | bool reallocate(ref void[] b, size_t s) shared 46 | { 47 | import core.stdc.stdlib : realloc; 48 | if (!s) 49 | { 50 | // fuzzy area in the C standard, see http://goo.gl/ZpWeSE 51 | // so just deallocate and nullify the pointer 52 | deallocate(b); 53 | b = null; 54 | return true; 55 | } 56 | auto p = cast(ubyte*) realloc(b.ptr, s); 57 | if (!p) return false; 58 | b = p[0 .. s]; 59 | return true; 60 | } 61 | 62 | /** 63 | Returns the global instance of this allocator type. The C heap allocator is 64 | thread-safe, therefore all of its methods and `it` itself are 65 | $(D shared). 66 | */ 67 | static shared Mallocator instance; 68 | } 69 | 70 | /// 71 | @nogc nothrow 72 | @system unittest 73 | { 74 | auto buffer = Mallocator.instance.allocate(1024 * 1024 * 4); 75 | scope(exit) Mallocator.instance.deallocate(buffer); 76 | //... 77 | } 78 | 79 | @nogc nothrow 80 | @system unittest 81 | { 82 | @nogc nothrow 83 | static void test(A)() 84 | { 85 | int* p = null; 86 | p = cast(int*) A.instance.allocate(int.sizeof); 87 | scope(exit) A.instance.deallocate(p[0 .. int.sizeof]); 88 | *p = 42; 89 | assert(*p == 42); 90 | } 91 | test!Mallocator(); 92 | } 93 | 94 | @nogc nothrow 95 | @system unittest 96 | { 97 | static void test(A)() 98 | { 99 | import stdx.allocator : make; 100 | Object p = null; 101 | p = A.instance.make!Object(); 102 | assert(p !is null); 103 | } 104 | 105 | test!Mallocator(); 106 | } 107 | 108 | version (Posix) 109 | @nogc nothrow 110 | private extern(C) int posix_memalign(void**, size_t, size_t); 111 | 112 | version (Windows) 113 | { 114 | // DMD Win 32 bit, DigitalMars C standard library misses the _aligned_xxx 115 | // functions family (snn.lib) 116 | version(CRuntime_DigitalMars) 117 | { 118 | // Helper to cast the infos written before the aligned pointer 119 | // this header keeps track of the size (required to realloc) and of 120 | // the base ptr (required to free). 121 | private struct AlignInfo 122 | { 123 | void* basePtr; 124 | size_t size; 125 | 126 | @nogc nothrow 127 | static AlignInfo* opCall(void* ptr) 128 | { 129 | return cast(AlignInfo*) (ptr - AlignInfo.sizeof); 130 | } 131 | } 132 | 133 | @nogc nothrow 134 | private void* _aligned_malloc(size_t size, size_t alignment) 135 | { 136 | import std.c.stdlib : malloc; 137 | size_t offset = alignment + size_t.sizeof * 2 - 1; 138 | 139 | // unaligned chunk 140 | void* basePtr = malloc(size + offset); 141 | if (!basePtr) return null; 142 | 143 | // get aligned location within the chunk 144 | void* alignedPtr = cast(void**)((cast(size_t)(basePtr) + offset) 145 | & ~(alignment - 1)); 146 | 147 | // write the header before the aligned pointer 148 | AlignInfo* head = AlignInfo(alignedPtr); 149 | head.basePtr = basePtr; 150 | head.size = size; 151 | 152 | return alignedPtr; 153 | } 154 | 155 | @nogc nothrow 156 | private void* _aligned_realloc(void* ptr, size_t size, size_t alignment) 157 | { 158 | import std.c.stdlib : free; 159 | import std.c.string : memcpy; 160 | 161 | if (!ptr) return _aligned_malloc(size, alignment); 162 | 163 | // gets the header from the exising pointer 164 | AlignInfo* head = AlignInfo(ptr); 165 | 166 | // gets a new aligned pointer 167 | void* alignedPtr = _aligned_malloc(size, alignment); 168 | if (!alignedPtr) 169 | { 170 | //to https://msdn.microsoft.com/en-us/library/ms235462.aspx 171 | //see Return value: in this case the original block is unchanged 172 | return null; 173 | } 174 | 175 | // copy exising data 176 | memcpy(alignedPtr, ptr, head.size); 177 | free(head.basePtr); 178 | 179 | return alignedPtr; 180 | } 181 | 182 | @nogc nothrow 183 | private void _aligned_free(void *ptr) 184 | { 185 | import std.c.stdlib : free; 186 | if (!ptr) return; 187 | AlignInfo* head = AlignInfo(ptr); 188 | free(head.basePtr); 189 | } 190 | 191 | } 192 | // DMD Win 64 bit, uses microsoft standard C library which implements them 193 | else 194 | { 195 | @nogc nothrow private extern(C) void* _aligned_malloc(size_t, size_t); 196 | @nogc nothrow private extern(C) void _aligned_free(void *memblock); 197 | @nogc nothrow private extern(C) void* _aligned_realloc(void *, size_t, size_t); 198 | } 199 | } 200 | 201 | /** 202 | Aligned allocator using OS-specific primitives, under a uniform API. 203 | */ 204 | version (dscripten) {} else 205 | struct AlignedMallocator 206 | { 207 | @system unittest { testAllocator!(() => typeof(this).instance); } 208 | 209 | /** 210 | The default alignment is $(D platformAlignment). 211 | */ 212 | enum uint alignment = platformAlignment; 213 | 214 | /** 215 | Forwards to $(D alignedAllocate(bytes, platformAlignment)). 216 | */ 217 | @trusted @nogc nothrow 218 | void[] allocate(size_t bytes) shared 219 | { 220 | if (!bytes) return null; 221 | return alignedAllocate(bytes, alignment); 222 | } 223 | 224 | /** 225 | Uses $(HTTP man7.org/linux/man-pages/man3/posix_memalign.3.html, 226 | $(D posix_memalign)) on Posix and 227 | $(HTTP msdn.microsoft.com/en-us/library/8z34s9c6(v=vs.80).aspx, 228 | $(D __aligned_malloc)) on Windows. 229 | */ 230 | version(Posix) 231 | @trusted @nogc nothrow 232 | void[] alignedAllocate(size_t bytes, uint a) shared 233 | { 234 | import core.stdc.errno : ENOMEM, EINVAL; 235 | assert(a.isGoodDynamicAlignment); 236 | void* result; 237 | auto code = posix_memalign(&result, a, bytes); 238 | if (code == ENOMEM) 239 | return null; 240 | 241 | else if (code == EINVAL) 242 | { 243 | assert(0, "AlignedMallocator.alignment is not a power of two " 244 | ~"multiple of (void*).sizeof, according to posix_memalign!"); 245 | } 246 | else if (code != 0) 247 | assert(0, "posix_memalign returned an unknown code!"); 248 | 249 | else 250 | return result[0 .. bytes]; 251 | } 252 | else version(Windows) 253 | @trusted @nogc nothrow 254 | void[] alignedAllocate(size_t bytes, uint a) shared 255 | { 256 | auto result = _aligned_malloc(bytes, a); 257 | return result ? result[0 .. bytes] : null; 258 | } 259 | else static assert(0); 260 | 261 | /** 262 | Calls $(D free(b.ptr)) on Posix and 263 | $(HTTP msdn.microsoft.com/en-US/library/17b5h8td(v=vs.80).aspx, 264 | $(D __aligned_free(b.ptr))) on Windows. 265 | */ 266 | version (Posix) 267 | @system @nogc nothrow 268 | bool deallocate(void[] b) shared 269 | { 270 | import core.stdc.stdlib : free; 271 | free(b.ptr); 272 | return true; 273 | } 274 | else version (Windows) 275 | @system @nogc nothrow 276 | bool deallocate(void[] b) shared 277 | { 278 | _aligned_free(b.ptr); 279 | return true; 280 | } 281 | else static assert(0); 282 | 283 | /** 284 | On Posix, forwards to $(D realloc). On Windows, forwards to 285 | $(D alignedReallocate(b, newSize, platformAlignment)). 286 | */ 287 | version (Posix) 288 | @system @nogc nothrow 289 | bool reallocate(ref void[] b, size_t newSize) shared 290 | { 291 | return Mallocator.instance.reallocate(b, newSize); 292 | } 293 | version (Windows) 294 | @system @nogc nothrow 295 | bool reallocate(ref void[] b, size_t newSize) shared 296 | { 297 | return alignedReallocate(b, newSize, alignment); 298 | } 299 | 300 | /** 301 | On Posix, uses $(D alignedAllocate) and copies data around because there is 302 | no realloc for aligned memory. On Windows, calls 303 | $(HTTP msdn.microsoft.com/en-US/library/y69db7sx(v=vs.80).aspx, 304 | $(D __aligned_realloc(b.ptr, newSize, a))). 305 | */ 306 | version (Windows) 307 | @system @nogc nothrow 308 | bool alignedReallocate(ref void[] b, size_t s, uint a) shared 309 | { 310 | if (!s) 311 | { 312 | deallocate(b); 313 | b = null; 314 | return true; 315 | } 316 | auto p = cast(ubyte*) _aligned_realloc(b.ptr, s, a); 317 | if (!p) return false; 318 | b = p[0 .. s]; 319 | return true; 320 | } 321 | 322 | /** 323 | Returns the global instance of this allocator type. The C heap allocator is 324 | thread-safe, therefore all of its methods and `instance` itself are 325 | $(D shared). 326 | */ 327 | static shared AlignedMallocator instance; 328 | } 329 | 330 | /// 331 | @nogc nothrow 332 | @system unittest 333 | { 334 | auto buffer = AlignedMallocator.instance.alignedAllocate(1024 * 1024 * 4, 335 | 128); 336 | scope(exit) AlignedMallocator.instance.deallocate(buffer); 337 | //... 338 | } 339 | 340 | version(unittest) version(CRuntime_DigitalMars) 341 | @nogc nothrow 342 | size_t addr(ref void* ptr) { return cast(size_t) ptr; } 343 | 344 | version(CRuntime_DigitalMars) 345 | @nogc nothrow 346 | @system unittest 347 | { 348 | void* m; 349 | 350 | m = _aligned_malloc(16, 0x10); 351 | if (m) 352 | { 353 | assert((m.addr & 0xF) == 0); 354 | _aligned_free(m); 355 | } 356 | 357 | m = _aligned_malloc(16, 0x100); 358 | if (m) 359 | { 360 | assert((m.addr & 0xFF) == 0); 361 | _aligned_free(m); 362 | } 363 | 364 | m = _aligned_malloc(16, 0x1000); 365 | if (m) 366 | { 367 | assert((m.addr & 0xFFF) == 0); 368 | _aligned_free(m); 369 | } 370 | 371 | m = _aligned_malloc(16, 0x10); 372 | if (m) 373 | { 374 | assert((cast(size_t) m & 0xF) == 0); 375 | m = _aligned_realloc(m, 32, 0x10000); 376 | if (m) assert((m.addr & 0xFFFF) == 0); 377 | _aligned_free(m); 378 | } 379 | 380 | m = _aligned_malloc(8, 0x10); 381 | if (m) 382 | { 383 | *cast(ulong*) m = 0X01234567_89ABCDEF; 384 | m = _aligned_realloc(m, 0x800, 0x1000); 385 | if (m) assert(*cast(ulong*) m == 0X01234567_89ABCDEF); 386 | _aligned_free(m); 387 | } 388 | } 389 | -------------------------------------------------------------------------------- /test/.gitignore: -------------------------------------------------------------------------------- 1 | /t*/*.js 2 | /t*/*.wasm 3 | /t*/output.txt 4 | -------------------------------------------------------------------------------- /test/run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | shopt -s lastpipe 4 | 5 | for dir in ./t????-* 6 | do 7 | ( 8 | cd "$dir" 9 | ./run-test.sh 10 | ) 11 | done 12 | 13 | printf 'All tests OK!\n' 1>&2 14 | -------------------------------------------------------------------------------- /test/t0001-basic/output.exp: -------------------------------------------------------------------------------- 1 | Hello, world! 2 | -------------------------------------------------------------------------------- /test/t0001-basic/run-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source ../test-lib.sh 3 | RunTest 4 | -------------------------------------------------------------------------------- /test/t0001-basic/test.d: -------------------------------------------------------------------------------- 1 | import core.stdc.stdio; 2 | 3 | import dscripten.standard; // TODO: should be unnecessary 4 | 5 | extern(C) 6 | int main() 7 | { 8 | printf("Hello, world!\n"); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /test/t0002-c/output.exp: -------------------------------------------------------------------------------- 1 | The result is 42! 2 | -------------------------------------------------------------------------------- /test/t0002-c/run-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source ../test-lib.sh 3 | extra_args+=(--extra-file=test.c) 4 | RunTest 5 | -------------------------------------------------------------------------------- /test/t0002-c/test.c: -------------------------------------------------------------------------------- 1 | int test_add(int a, int b) 2 | { 3 | return a + b; 4 | } 5 | -------------------------------------------------------------------------------- /test/t0002-c/test.d: -------------------------------------------------------------------------------- 1 | import core.stdc.stdio; 2 | 3 | import dscripten.standard; // TODO: should be unnecessary 4 | 5 | extern(C) int test_add(int, int); 6 | 7 | extern(C) 8 | int main() 9 | { 10 | int ret = test_add(17, 25); 11 | printf("The result is %d!\n", ret); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /test/t0003-c-types/output.exp: -------------------------------------------------------------------------------- 1 | ok 2 | ok 3 | ok 4 | ok 5 | -------------------------------------------------------------------------------- /test/t0003-c-types/run-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source ../test-lib.sh 3 | extra_args+=(--extra-file=test.c) 4 | RunTest 5 | -------------------------------------------------------------------------------- /test/t0003-c-types/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int sizeOfInt() { return sizeof(int); } 4 | int sizeOfLong() { return sizeof(long); } 5 | int sizeOfSizet() { return sizeof(size_t); } 6 | int sizeOfWchar() { return sizeof(wchar_t); } 7 | -------------------------------------------------------------------------------- /test/t0003-c-types/test.d: -------------------------------------------------------------------------------- 1 | import core.stdc.config; 2 | import core.stdc.stddef; 3 | import core.stdc.stdio; 4 | 5 | import dscripten.standard; // TODO: should be unnecessary 6 | 7 | extern(C) int sizeOfInt(); 8 | extern(C) int sizeOfLong(); 9 | extern(C) int sizeOfSizet(); 10 | extern(C) int sizeOfWchar(); 11 | 12 | extern(C) 13 | int main() 14 | { 15 | printf("%s\n", sizeOfInt() == int.sizeof ? "ok".ptr : "mismatch".ptr); 16 | printf("%s\n", sizeOfLong() == c_long.sizeof ? "ok".ptr : "mismatch".ptr); 17 | printf("%s\n", sizeOfSizet() == size_t.sizeof ? "ok".ptr : "mismatch".ptr); 18 | printf("%s\n", sizeOfWchar() == wchar_t.sizeof ? "ok".ptr : "mismatch".ptr); 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /test/t0004-c-includes/output.exp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberShadow/dscripten-tools/e2ce05318810d0aac4a9bf291552b78dab92dbe3/test/t0004-c-includes/output.exp -------------------------------------------------------------------------------- /test/t0004-c-includes/run-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source ../test-lib.sh 3 | extra_args+=(--extra-file=test.c) 4 | RunTest 5 | -------------------------------------------------------------------------------- /test/t0004-c-includes/test.c: -------------------------------------------------------------------------------- 1 | // Ensure the include path is set up correctly. 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /test/t0004-c-includes/test.d: -------------------------------------------------------------------------------- 1 | import dscripten.standard; // TODO: should be unnecessary 2 | 3 | extern(C) 4 | int main() 5 | { 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /test/t0100-phobos/output.exp: -------------------------------------------------------------------------------- 1 | 1.414214 2 | 2 + 2 = 4 3 | On the heap! 4 | -------------------------------------------------------------------------------- /test/t0100-phobos/run-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source ../test-lib.sh 3 | RunTest 4 | -------------------------------------------------------------------------------- /test/t0100-phobos/test.d: -------------------------------------------------------------------------------- 1 | // Some limited Phobos tests 2 | 3 | import std.array; 4 | import std.format; 5 | import std.math; 6 | 7 | import core.stdc.stdio; 8 | 9 | import dscripten.standard; // TODO: should be unnecessary 10 | import dscripten.memory; 11 | 12 | void puts(in char[] s) 13 | { 14 | printf("%.*s\n", s.length, s.ptr); 15 | } 16 | 17 | extern(C) 18 | int main() 19 | { 20 | printf("%f\n", sqrt(2.0)); 21 | gc_init(); 22 | Appender!string app; 23 | formattedWrite(app, "%d + %d = %d", 2, 2, 4); 24 | puts(app.data); 25 | puts(format("On the %s!", "heap")); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /test/t0101-d-main/output.exp: -------------------------------------------------------------------------------- 1 | Hello, world! 2 | -------------------------------------------------------------------------------- /test/t0101-d-main/run-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source ../test-lib.sh 3 | RunTest 4 | -------------------------------------------------------------------------------- /test/t0101-d-main/test.d: -------------------------------------------------------------------------------- 1 | import dscripten.standard; // TODO: should be unnecessary 2 | import dscripten.memory; 3 | import rt.dmain2; 4 | 5 | import core.stdc.stdio; 6 | 7 | // This is a D (not extern(C)) main! 8 | void main() 9 | { 10 | printf("Hello, world!\n"); 11 | } 12 | -------------------------------------------------------------------------------- /test/t0102-writeln/output.exp: -------------------------------------------------------------------------------- 1 | Hello, world! 2 | -------------------------------------------------------------------------------- /test/t0102-writeln/run-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source ../test-lib.sh 3 | RunTest 4 | -------------------------------------------------------------------------------- /test/t0102-writeln/test.d: -------------------------------------------------------------------------------- 1 | import dscripten.standard; // TODO: should be unnecessary 2 | 3 | import std.stdio; 4 | 5 | extern(C) 6 | void main() 7 | { 8 | writeln("Hello, world!"); 9 | } 10 | -------------------------------------------------------------------------------- /test/t0200-wasm/output.exp: -------------------------------------------------------------------------------- 1 | Hello, world! 2 | -------------------------------------------------------------------------------- /test/t0200-wasm/run-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source ../test-lib.sh 3 | 4 | if [[ -n ${TRAVIS+x} ]] 5 | then 6 | # Travis' GCC seems to crash / run out of resources while 7 | # attempting to build Binaryen. 8 | # https://travis-ci.org/CyberShadow/dscripten-tools/builds/377109592 9 | SkipTest 10 | fi 11 | 12 | extra_args+=(--wasm) 13 | RunTest 14 | -------------------------------------------------------------------------------- /test/t0200-wasm/test.d: -------------------------------------------------------------------------------- 1 | import core.stdc.stdio; 2 | 3 | import dscripten.standard; // TODO: should be unnecessary 4 | 5 | extern(C) 6 | int main() 7 | { 8 | printf("Hello, world!\n"); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /test/test-lib.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | shopt -s lastpipe 4 | 5 | printf '%s:\n' "$(basename "$PWD")" 1>&2 6 | 7 | extra_args=() 8 | 9 | function BuildTools() { 10 | ( 11 | cd ../.. 12 | for prog in {dmd,rdmd}-dscripten 13 | do 14 | rdmd --build-only -g $prog 15 | done 16 | ) 17 | } 18 | 19 | function RunTest() { 20 | # Ensure tools are built 21 | BuildTools 22 | 23 | local args=( 24 | ../../rdmd-dscripten 25 | --compiler=../../dmd-dscripten 26 | --build-only 27 | ) 28 | 29 | if [[ ${#extra_args[@]} -gt 0 ]] 30 | then 31 | args+=("${extra_args[@]}") 32 | fi 33 | 34 | "${args[@]}" test.d 35 | 36 | node test.js > output.txt 37 | diff -u output.exp output.txt 38 | 39 | printf ' >>> OK\n' 1>&2 40 | } 41 | 42 | function SkipTest() { 43 | printf ' >>> Skipped!\n' 1>&2 44 | exit 0 45 | } 46 | --------------------------------------------------------------------------------