Compare commits

...

11 Commits

Author SHA1 Message Date
Ginger Bill 6e1864d21c Remove all binaries 2017-03-03 11:13:05 +00:00
Ginger Bill fb2d611dcd Update llvm binaries to latest version; Update utf8proc; 2017-03-03 11:09:37 +00:00
Ginger Bill 9e8c9be1ea Allow pointers to append; Fix strconv stuff; new_slice allows for capacity 2017-03-02 19:24:34 +00:00
Ginger Bill 9bc37f4400 fmt.odin uses ^[]byte rather than custom Buffer type 2017-02-26 15:34:02 +00:00
Ginger Bill f29e303ce7 Slices now have a capacity. 2017-02-26 15:14:08 +00:00
Ginger Bill 3c9143957c Ellipsis is now just ..; Remove half-closed range operator and treat all of them as half-closed; slice expression uses ..; 2017-02-26 14:19:03 +00:00
Ginger Bill 18b3c0b2fc Fix fmt integer width printing 2017-02-26 09:42:24 +00:00
Ginger Bill c59f6b7d0b ++ -- statements; add strconv.odin (and replace some of the fmt procs); Fix ~ on 64 bit constants; Fix integer casts from smaller to larger size 2017-02-26 00:44:26 +00:00
Ginger Bill 67ed8a9a4a Fix Tuple type info bug
Caused by not having type safe tagged unions :P (Silly C)
2017-02-24 22:56:34 +00:00
Ginger Bill 4cc4d604bc Add core/strings.odin 2017-02-24 21:11:05 +00:00
Ginger Bill eec709c545 Fix fmt.odin printing enums 2017-02-24 20:55:35 +00:00
35 changed files with 1713 additions and 1483 deletions
+1
View File
@@ -255,3 +255,4 @@ paket-files/
!misc/llvm-bim/lli.exe
!misc/llvm-bim/opt.exe
builds
bin
-200
View File
@@ -1,200 +0,0 @@
This file is a list of the people responsible for ensuring that patches for a
particular part of LLVM are reviewed, either by themself or by someone else.
They are also the gatekeepers for their part of LLVM, with the final word on
what goes in or not.
The list is sorted by surname and formatted to allow easy grepping and
beautification by scripts. The fields are: name (N), email (E), web-address
(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
(S). Each entry should contain at least the (N), (E) and (D) fields.
N: Joe Abbey
E: jabbey@arxan.com
D: LLVM Bitcode (lib/Bitcode/* include/llvm/Bitcode/*)
N: Owen Anderson
E: resistor@mac.com
D: SelectionDAG (lib/CodeGen/SelectionDAG/*)
N: Rafael Avila de Espindola
E: rafael.espindola@gmail.com
D: Gold plugin (tools/gold/*)
N: Justin Bogner
E: mail@justinbogner.com
D: InstrProfiling and related parts of ProfileData
N: Chandler Carruth
E: chandlerc@gmail.com
E: chandlerc@google.com
D: Config, ADT, Support, inlining & related passes, SROA/mem2reg & related passes, CMake, library layering
N: Evan Cheng
E: evan.cheng@apple.com
D: parts of code generator not covered by someone else
N: Eric Christopher
E: echristo@gmail.com
D: Debug Information, autotools/configure/make build, inline assembly
N: Greg Clayton
E: gclayton@apple.com
D: LLDB
N: Marshall Clow
E: mclow.lists@gmail.com
D: libc++
N: Peter Collingbourne
E: peter@pcc.me.uk
D: llgo
N: Quentin Colombet
E: qcolombet@apple.com
D: Register allocators
N: Duncan P. N. Exon Smith
E: dexonsmith@apple.com
D: Branch weights and BlockFrequencyInfo
N: Hal Finkel
E: hfinkel@anl.gov
D: BBVectorize, the loop reroller, alias analysis and the PowerPC target
N: Dan Gohman
E: sunfish@mozilla.com
D: WebAssembly Backend (lib/Target/WebAssembly/*)
N: Renato Golin
E: renato.golin@linaro.org
D: ARM Linux support
N: Venkatraman Govindaraju
E: venkatra@cs.wisc.edu
D: Sparc Backend (lib/Target/Sparc/*)
N: Tobias Grosser
E: tobias@grosser.es
D: Polly
N: James Grosbach
E: grosbach@apple.com
D: MC layer
N: Justin Holewinski
E: jholewinski@nvidia.com
D: NVPTX Target (lib/Target/NVPTX/*)
N: Lang Hames
E: lhames@gmail.com
D: MCJIT, RuntimeDyld and JIT event listeners
N: Galina Kistanova
E: gkistanova@gmail.com
D: LLVM Buildbot
N: Anton Korobeynikov
E: anton@korobeynikov.info
D: Exception handling, Windows codegen, ARM EABI
N: Benjamin Kramer
E: benny.kra@gmail.com
D: DWARF Parser
N: Sergei Larin
E: slarin@codeaurora.org
D: VLIW Instruction Scheduling, Packetization
N: Chris Lattner
E: sabre@nondot.org
W: http://nondot.org/~sabre/
D: Everything not covered by someone else
N: David Majnemer
E: david.majnemer@gmail.com
D: IR Constant Folder, InstCombine
N: Dylan McKay
E: dylanmckay34@gmail.com
D: AVR Backend
N: Tim Northover
E: t.p.northover@gmail.com
D: AArch64 backend, misc ARM backend
N: Diego Novillo
E: dnovillo@google.com
D: SampleProfile and related parts of ProfileData
N: Jakob Olesen
E: stoklund@2pi.dk
D: TableGen
N: Richard Osborne
E: richard@xmos.com
D: XCore Backend
N: Krzysztof Parzyszek
E: kparzysz@codeaurora.org
D: Hexagon Backend
N: Paul Robinson
E: paul_robinson@playstation.sony.com
D: Sony PlayStation®4 support
N: Chad Rosier
E: mcrosier@codeaurora.org
D: Fast-Isel
N: Nadav Rotem
E: nrotem@apple.com
D: X86 Backend, Loop Vectorizer
N: Daniel Sanders
E: daniel.sanders@imgtec.com
D: MIPS Backend (lib/Target/Mips/*)
N: Duncan Sands
E: baldrick@free.fr
D: DragonEgg
N: Kostya Serebryany
E: kcc@google.com
D: AddressSanitizer, ThreadSanitizer (LLVM parts)
N: Michael Spencer
E: bigcheesegs@gmail.com
D: Windows parts of Support, Object, ar, nm, objdump, ranlib, size
N: Alexei Starovoitov
E: alexei.starovoitov@gmail.com
D: BPF backend
N: Tom Stellard
E: thomas.stellard@amd.com
E: mesa-dev@lists.freedesktop.org
D: Release manager for the 3.5 and 3.6 branches, R600 Backend, libclc
N: Evgeniy Stepanov
E: eugenis@google.com
D: MemorySanitizer (LLVM part)
N: Andrew Trick
E: atrick@apple.com
D: IndVar Simplify, Loop Strength Reduction, Instruction Scheduling
N: Ulrich Weigand
E: uweigand@de.ibm.com
D: SystemZ Backend
N: Bill Wendling
E: isanbard@gmail.com
D: libLTO, IR Linker
N: Peter Zotov
E: whitequark@whitequark.org
D: OCaml bindings
N: Andrey Churbanov
E: andrey.churbanov@intel.com
D: OpenMP runtime library
-467
View File
@@ -1,467 +0,0 @@
This file is a partial list of people who have contributed to the LLVM
project. If you have contributed a patch or made some other contribution to
LLVM, please submit a patch to this file to add yourself, and it will be
done!
The list is sorted by surname and formatted to allow easy grepping and
beautification by scripts. The fields are: name (N), email (E), web-address
(W), PGP key ID and fingerprint (P), description (D), snail-mail address
(S), and (I) IRC handle.
N: Vikram Adve
E: vadve@cs.uiuc.edu
W: http://www.cs.uiuc.edu/~vadve/
D: The Sparc64 backend, provider of much wisdom, and motivator for LLVM
N: Owen Anderson
E: resistor@mac.com
D: LCSSA pass and related LoopUnswitch work
D: GVNPRE pass, DataLayout refactoring, random improvements
N: Henrik Bach
D: MingW Win32 API portability layer
N: Aaron Ballman
E: aaron@aaronballman.com
D: __declspec attributes, Windows support, general bug fixing
N: Nate Begeman
E: natebegeman@mac.com
D: PowerPC backend developer
D: Target-independent code generator and analysis improvements
N: Daniel Berlin
E: dberlin@dberlin.org
D: ET-Forest implementation.
D: Sparse bitmap
N: David Blaikie
E: dblaikie@gmail.com
D: General bug fixing/fit & finish, mostly in Clang
N: Neil Booth
E: neil@daikokuya.co.uk
D: APFloat implementation.
N: Misha Brukman
E: brukman+llvm@uiuc.edu
W: http://misha.brukman.net
D: Portions of X86 and Sparc JIT compilers, PowerPC backend
D: Incremental bitcode loader
N: Cameron Buschardt
E: buschard@uiuc.edu
D: The `mem2reg' pass - promotes values stored in memory to registers
N: Brendon Cahoon
E: bcahoon@codeaurora.org
D: Loop unrolling with run-time trip counts.
N: Chandler Carruth
E: chandlerc@gmail.com
E: chandlerc@google.com
D: Hashing algorithms and interfaces
D: Inline cost analysis
D: Machine block placement pass
D: SROA
N: Casey Carter
E: ccarter@uiuc.edu
D: Fixes to the Reassociation pass, various improvement patches
N: Evan Cheng
E: evan.cheng@apple.com
D: ARM and X86 backends
D: Instruction scheduler improvements
D: Register allocator improvements
D: Loop optimizer improvements
D: Target-independent code generator improvements
N: Dan Villiom Podlaski Christiansen
E: danchr@gmail.com
E: danchr@cs.au.dk
W: http://villiom.dk
D: LLVM Makefile improvements
D: Clang diagnostic & driver tweaks
S: Aarhus, Denmark
N: Jeff Cohen
E: jeffc@jolt-lang.org
W: http://jolt-lang.org
D: Native Win32 API portability layer
N: John T. Criswell
E: criswell@uiuc.edu
D: Original Autoconf support, documentation improvements, bug fixes
N: Anshuman Dasgupta
E: adasgupt@codeaurora.org
D: Deterministic finite automaton based infrastructure for VLIW packetization
N: Stefanus Du Toit
E: stefanus.du.toit@intel.com
D: Bug fixes and minor improvements
N: Rafael Avila de Espindola
E: rafael.espindola@gmail.com
D: The ARM backend
N: Dave Estes
E: cestes@codeaurora.org
D: AArch64 machine description for Cortex-A53
N: Alkis Evlogimenos
E: alkis@evlogimenos.com
D: Linear scan register allocator, many codegen improvements, Java frontend
N: Hal Finkel
E: hfinkel@anl.gov
D: Basic-block autovectorization, PowerPC backend improvements
N: Eric Fiselier
E: eric@efcs.ca
D: LIT patches and documentation.
N: Ryan Flynn
E: pizza@parseerror.com
D: Miscellaneous bug fixes
N: Brian Gaeke
E: gaeke@uiuc.edu
W: http://www.students.uiuc.edu/~gaeke/
D: Portions of X86 static and JIT compilers; initial SparcV8 backend
D: Dynamic trace optimizer
D: FreeBSD/X86 compatibility fixes, the llvm-nm tool
N: Nicolas Geoffray
E: nicolas.geoffray@lip6.fr
W: http://www-src.lip6.fr/homepages/Nicolas.Geoffray/
D: PPC backend fixes for Linux
N: Louis Gerbarg
E: lgg@apple.com
D: Portions of the PowerPC backend
N: Saem Ghani
E: saemghani@gmail.com
D: Callgraph class cleanups
N: Mikhail Glushenkov
E: foldr@codedgers.com
D: Author of llvmc2
N: Dan Gohman
E: sunfish@mozilla.com
D: Miscellaneous bug fixes
D: WebAssembly Backend
N: David Goodwin
E: david@goodwinz.net
D: Thumb-2 code generator
N: David Greene
E: greened@obbligato.org
D: Miscellaneous bug fixes
D: Register allocation refactoring
N: Gabor Greif
E: ggreif@gmail.com
D: Improvements for space efficiency
N: James Grosbach
E: grosbach@apple.com
I: grosbach
D: SjLj exception handling support
D: General fixes and improvements for the ARM back-end
D: MCJIT
D: ARM integrated assembler and assembly parser
D: Led effort for the backend formerly known as ARM64
N: Lang Hames
E: lhames@gmail.com
D: PBQP-based register allocator
N: Gordon Henriksen
E: gordonhenriksen@mac.com
D: Pluggable GC support
D: C interface
D: Ocaml bindings
N: Raul Fernandes Herbster
E: raul@dsc.ufcg.edu.br
D: JIT support for ARM
N: Paolo Invernizzi
E: arathorn@fastwebnet.it
D: Visual C++ compatibility fixes
N: Patrick Jenkins
E: patjenk@wam.umd.edu
D: Nightly Tester
N: Dale Johannesen
E: dalej@apple.com
D: ARM constant islands improvements
D: Tail merging improvements
D: Rewrite X87 back end
D: Use APFloat for floating point constants widely throughout compiler
D: Implement X87 long double
N: Brad Jones
E: kungfoomaster@nondot.org
D: Support for packed types
N: Rod Kay
E: rkay@auroraux.org
D: Author of LLVM Ada bindings
N: Eric Kidd
W: http://randomhacks.net/
D: llvm-config script
N: Anton Korobeynikov
E: asl@math.spbu.ru
D: Mingw32 fixes, cross-compiling support, stdcall/fastcall calling conv.
D: x86/linux PIC codegen, aliases, regparm/visibility attributes
D: Switch lowering refactoring
N: Sumant Kowshik
E: kowshik@uiuc.edu
D: Author of the original C backend
N: Benjamin Kramer
E: benny.kra@gmail.com
D: Miscellaneous bug fixes
N: Sundeep Kushwaha
E: sundeepk@codeaurora.org
D: Implemented DFA-based target independent VLIW packetizer
N: Christopher Lamb
E: christopher.lamb@gmail.com
D: aligned load/store support, parts of noalias and restrict support
D: vreg subreg infrastructure, X86 codegen improvements based on subregs
D: address spaces
N: Jim Laskey
E: jlaskey@apple.com
D: Improvements to the PPC backend, instruction scheduling
D: Debug and Dwarf implementation
D: Auto upgrade mangler
D: llvm-gcc4 svn wrangler
N: Chris Lattner
E: sabre@nondot.org
W: http://nondot.org/~sabre/
D: Primary architect of LLVM
N: Tanya Lattner (Tanya Brethour)
E: tonic@nondot.org
W: http://nondot.org/~tonic/
D: The initial llvm-ar tool, converted regression testsuite to dejagnu
D: Modulo scheduling in the SparcV9 backend
D: Release manager (1.7+)
N: Sylvestre Ledru
E: sylvestre@debian.org
W: http://sylvestre.ledru.info/
W: http://llvm.org/apt/
D: Debian and Ubuntu packaging
D: Continuous integration with jenkins
N: Andrew Lenharth
E: alenhar2@cs.uiuc.edu
W: http://www.lenharth.org/~andrewl/
D: Alpha backend
D: Sampling based profiling
N: Nick Lewycky
E: nicholas@mxc.ca
D: PredicateSimplifier pass
N: Tony Linthicum, et. al.
E: tlinth@codeaurora.org
D: Backend for Qualcomm's Hexagon VLIW processor.
N: Bruno Cardoso Lopes
E: bruno.cardoso@gmail.com
I: bruno
W: http://brunocardoso.cc
D: Mips backend
D: Random ARM integrated assembler and assembly parser improvements
D: General X86 AVX1 support
N: Duraid Madina
E: duraid@octopus.com.au
W: http://kinoko.c.u-tokyo.ac.jp/~duraid/
D: IA64 backend, BigBlock register allocator
N: John McCall
E: rjmccall@apple.com
D: Clang semantic analysis and IR generation
N: Michael McCracken
E: michael.mccracken@gmail.com
D: Line number support for llvmgcc
N: Vladimir Merzliakov
E: wanderer@rsu.ru
D: Test suite fixes for FreeBSD
N: Scott Michel
E: scottm@aero.org
D: Added STI Cell SPU backend.
N: Kai Nacke
E: kai@redstar.de
D: Support for implicit TLS model used with MS VC runtime
D: Dumping of Win64 EH structures
N: Takumi Nakamura
E: geek4civic@gmail.com
E: chapuni@hf.rim.or.jp
D: Cygwin and MinGW support.
D: Win32 tweaks.
S: Yokohama, Japan
N: Edward O'Callaghan
E: eocallaghan@auroraux.org
W: http://www.auroraux.org
D: Add Clang support with various other improvements to utils/NewNightlyTest.pl
D: Fix and maintain Solaris & AuroraUX support for llvm, various build warnings
D: and error clean ups.
N: Morten Ofstad
E: morten@hue.no
D: Visual C++ compatibility fixes
N: Jakob Stoklund Olesen
E: stoklund@2pi.dk
D: Machine code verifier
D: Blackfin backend
D: Fast register allocator
D: Greedy register allocator
N: Richard Osborne
E: richard@xmos.com
D: XCore backend
N: Devang Patel
E: dpatel@apple.com
D: LTO tool, PassManager rewrite, Loop Pass Manager, Loop Rotate
D: GCC PCH Integration (llvm-gcc), llvm-gcc improvements
D: Optimizer improvements, Loop Index Split
N: Ana Pazos
E: apazos@codeaurora.org
D: Fixes and improvements to the AArch64 backend
N: Wesley Peck
E: peckw@wesleypeck.com
W: http://wesleypeck.com/
D: MicroBlaze backend
N: Francois Pichet
E: pichet2000@gmail.com
D: MSVC support
N: Vladimir Prus
W: http://vladimir_prus.blogspot.com
E: ghost@cs.msu.su
D: Made inst_iterator behave like a proper iterator, LowerConstantExprs pass
N: Kalle Raiskila
E: kalle.rasikila@nokia.com
D: Some bugfixes to CellSPU
N: Xerxes Ranby
E: xerxes@zafena.se
D: Cmake dependency chain and various bug fixes
N: Alex Rosenberg
E: alexr@leftfield.org
I: arosenberg
D: ARM calling conventions rewrite, hard float support
N: Chad Rosier
E: mcrosier@codeaurora.org
I: mcrosier
D: AArch64 fast instruction selection pass
D: Fixes and improvements to the ARM fast-isel pass
D: Fixes and improvements to the AArch64 backend
N: Nadav Rotem
E: nrotem@apple.com
D: X86 code generation improvements, Loop Vectorizer.
N: Roman Samoilov
E: roman@codedgers.com
D: MSIL backend
N: Duncan Sands
E: baldrick@free.fr
I: baldrick
D: Ada support in llvm-gcc
D: Dragonegg plugin
D: Exception handling improvements
D: Type legalizer rewrite
N: Ruchira Sasanka
E: sasanka@uiuc.edu
D: Graph coloring register allocator for the Sparc64 backend
N: Arnold Schwaighofer
E: arnold.schwaighofer@gmail.com
D: Tail call optimization for the x86 backend
N: Shantonu Sen
E: ssen@apple.com
D: Miscellaneous bug fixes
N: Anand Shukla
E: ashukla@cs.uiuc.edu
D: The `paths' pass
N: Michael J. Spencer
E: bigcheesegs@gmail.com
D: Shepherding Windows COFF support into MC.
D: Lots of Windows stuff.
N: Reid Spencer
E: rspencer@reidspencer.com
W: http://reidspencer.com/
D: Lots of stuff, see: http://wiki.llvm.org/index.php/User:Reid
N: Alp Toker
E: alp@nuanti.com
W: http://atoker.com/
D: C++ frontend next generation standards implementation
N: Craig Topper
E: craig.topper@gmail.com
D: X86 codegen and disassembler improvements. AVX2 support.
N: Edwin Torok
E: edwintorok@gmail.com
D: Miscellaneous bug fixes
N: Adam Treat
E: manyoso@yahoo.com
D: C++ bugs filed, and C++ front-end bug fixes.
N: Lauro Ramos Venancio
E: lauro.venancio@indt.org.br
D: ARM backend improvements
D: Thread Local Storage implementation
N: Bill Wendling
I: wendling
E: isanbard@gmail.com
D: Release manager, IR Linker, LTO
D: Bunches of stuff
N: Bob Wilson
E: bob.wilson@acm.org
D: Advanced SIMD (NEON) support in the ARM backend.
-70
View File
@@ -1,70 +0,0 @@
==============================================================================
LLVM Release License
==============================================================================
University of Illinois/NCSA
Open Source License
Copyright (c) 2003-2015 University of Illinois at Urbana-Champaign.
All rights reserved.
Developed by:
LLVM Team
University of Illinois at Urbana-Champaign
http://llvm.org
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal with
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimers.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimers in the
documentation and/or other materials provided with the distribution.
* Neither the names of the LLVM Team, University of Illinois at
Urbana-Champaign, nor the names of its contributors may be used to
endorse or promote products derived from this Software without specific
prior written permission.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
SOFTWARE.
==============================================================================
Copyrights and Licenses for Third Party Software Distributed with LLVM:
==============================================================================
The LLVM software contains code written by third parties. Such software will
have its own individual LICENSE.TXT file in the directory in which it appears.
This file will describe the copyrights, license, and restrictions which apply
to that code.
The disclaimer of warranty in the University of Illinois Open Source License
applies to all code in the LLVM Distribution, and nothing in any of the
other licenses gives permission to use the names of the LLVM Team or the
University of Illinois to endorse or promote products derived from this
Software.
The following pieces of software have additional or alternate copyrights,
licenses, and/or restrictions:
Program Directory
------- ---------
Autoconf llvm/autoconf
llvm/projects/ModuleMaker/autoconf
Google Test llvm/utils/unittest/googletest
OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex}
pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT}
ARM contributions llvm/lib/Target/ARM/LICENSE.TXT
md5 contributions llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+1
View File
@@ -45,6 +45,7 @@ del *.ilk > NUL 2> NUL
cl %compiler_settings% "src\main.c" ^
/link %linker_settings% -OUT:%exe_name% ^
&& odin run code/demo.odin
rem && odin build code/Jaze/src/main.odin
rem && odin build_dll code/example.odin ^
rem odin run code/demo.odin
+19
View File
@@ -5,8 +5,23 @@
#import "mem.odin";
#import "opengl.odin";
#import "os.odin";
#import "strconv.odin";
#import "sync.odin";
main :: proc() {
// buf: [64]byte;
// // len := strconv.generic_ftoa(buf[..], 123.5431, 'f', 4, 64);
// x := 624.123;
// s := strconv.format_float(buf[..], x, 'f', 6, 64);
// fmt.println(s);
// fmt.printf("%3d\n", 102);
s := new_slice(int, 0, 10);
append(s, 1, 2, 6, 3, 6, 5, 5, 5, 5, 1, 2);
fmt.println(s);
when false {
/*
Version 0.1.1
@@ -57,6 +72,9 @@ main :: proc() {
To come very Soon:
* Linux and OS X builds (unofficial ones do exist already)
*/
{
}
{
Fruit :: enum {
@@ -145,4 +163,5 @@ main :: proc() {
// align_of([vector 7]i32) != align_of([7]i32) // this may be the case
}
}
}
+30 -11
View File
@@ -316,24 +316,24 @@ __bounds_check_error :: proc(file: string, line, column: int, index, count: int)
if 0 <= index && index < count {
return;
}
fmt.fprintf(os.stderr, "%s(%d:%d) Index %d is out of bounds range 0..<%d\n",
fmt.fprintf(os.stderr, "%s(%d:%d) Index %d is out of bounds range 0..%d\n",
file, line, column, index, count);
__debug_trap();
}
__slice_expr_error :: proc(file: string, line, column: int, low, high: int) {
if 0 <= low && low <= high {
__slice_expr_error :: proc(file: string, line, column: int, low, high, max: int) {
if 0 <= low && low <= high && high <= max {
return;
}
fmt.fprintf(os.stderr, "%s(%d:%d) Invalid slice indices: [%d:%d]\n",
file, line, column, low, high);
fmt.fprintf(os.stderr, "%s(%d:%d) Invalid slice indices: [%d..%d..%d]\n",
file, line, column, low, high, max);
__debug_trap();
}
__substring_expr_error :: proc(file: string, line, column: int, low, high: int) {
if 0 <= low && low <= high {
return;
}
fmt.fprintf(os.stderr, "%s(%d:%d) Invalid substring indices: [%d:%d]\n",
fmt.fprintf(os.stderr, "%s(%d:%d) Invalid substring indices: [%d..%d]\n",
file, line, column, low, high);
__debug_trap();
}
@@ -361,8 +361,9 @@ Raw_String :: struct #ordered {
};
Raw_Slice :: struct #ordered {
data: rawptr,
count: int,
data: rawptr,
count: int,
capacity: int,
};
Raw_Dynamic_Array :: struct #ordered {
@@ -447,10 +448,28 @@ __dynamic_array_append_nothing :: proc(array_: rawptr, elem_size, elem_align: in
data := cast(^byte)array.data;
assert(data != nil);
mem.zero(data + (elem_size*array.count), elem_size);
array.count += 1;
array.count++;
return array.count;
}
__slice_append :: proc(slice_: rawptr, elem_size, elem_align: int,
items: rawptr, item_count: int) -> int {
slice := cast(^Raw_Slice)slice_;
if item_count <= 0 || items == nil {
return slice.count;
}
item_count = min(slice.capacity-slice.count, item_count);
if item_count > 0 {
data := cast(^byte)slice.data;
assert(data != nil);
mem.copy(data + (elem_size*slice.count), items, elem_size * item_count);
slice.count += item_count;
}
return slice.count;
}
// Map stuff
@@ -506,7 +525,7 @@ __dynamic_map_rehash :: proc(using header: __Map_Header, new_count: int) {
nm.hashes[i] = -1;
}
for i := 0; i < nm.entries.count; i += 1 {
for i := 0; i < nm.entries.count; i++ {
entry_header := __dynamic_map_get_entry(new_header, i);
data := cast(^byte)entry_header;
@@ -645,7 +664,7 @@ __dynamic_map_erase :: proc(using h: __Map_Header, fr: __Map_Find_Result) {
}
if fr.entry_index == m.entries.count-1 {
m.entries.count -= 1;
m.entries.count--;
}
mem.copy(__dynamic_map_get_entry(h, fr.entry_index), __dynamic_map_get_entry(h, m.entries.count-1), entry_size);
last := __dynamic_map_find(h, __dynamic_map_get_entry(h, fr.entry_index).key);
+2 -2
View File
@@ -37,7 +37,7 @@ spin_lock :: proc(a: ^i32, time_out: int) -> bool { // NOTE(bill) time_out = -1
old_value := compare_exchange(a, 1, 0);
counter := 0;
for old_value != 0 && (time_out < 0 || counter < time_out) {
counter += 1;
counter++;
yield_thread();
old_value = compare_exchange(a, 1, 0);
mfence();
@@ -81,7 +81,7 @@ spin_lock :: proc(a: ^i64, time_out: int) -> bool { // NOTE(bill) time_out = -1
old_value := compare_exchange(a, 1, 0);
counter := 0;
for old_value != 0 && (time_out < 0 || counter < time_out) {
counter += 1;
counter++;
yield_thread();
old_value = compare_exchange(a, 1, 0);
mfence();
+257
View File
@@ -0,0 +1,257 @@
// #import "fmt.odin";
// Multiple precision decimal numbers
// NOTE: This is only for floating point printing and nothing else
Decimal :: struct {
digits: [384]byte, // big-endian digits
count: int,
decimal_point: int,
neg, trunc: bool,
}
decimal_to_string :: proc(buf: []byte, a: ^Decimal) -> string {
digit_zero :: proc(buf: []byte) -> int {
for _, i in buf {
buf[i] = '0';
}
return buf.count;
}
n := 10 + a.count + abs(a.decimal_point);
// TODO(bill): make this work with a buffer that's not big enough
assert(buf.count >= n);
buf = buf[..n];
if a.count == 0 {
buf[0] = '0';
return cast(string)buf[0..1];
}
w := 0;
if a.decimal_point <= 0 {
buf[w] = '0'; w++;
buf[w] = '.'; w++;
w += digit_zero(buf[w .. w-a.decimal_point]);
w += copy(buf[w..], a.digits[0..a.count]);
} else if a.decimal_point < a.count {
w += copy(buf[w..], a.digits[0..a.decimal_point]);
buf[w] = '.'; w++;
w += copy(buf[w..], a.digits[a.decimal_point .. a.count]);
} else {
w += copy(buf[w..], a.digits[0..a.count]);
w += digit_zero(buf[w .. w+a.decimal_point-a.count]);
}
return cast(string)buf[0..w];
}
// trim trailing zeros
trim :: proc(a: ^Decimal) {
for a.count > 0 && a.digits[a.count-1] == '0' {
a.count--;
}
if a.count == 0 {
a.decimal_point = 0;
}
}
assign :: proc(a: ^Decimal, i: u64) {
buf: [32]byte;
n := 0;
for i > 0 {
j := i/10;
i -= 10*j;
buf[n] = cast(byte)('0'+i);
n++;
i = j;
}
a.count = 0;
for n--; n >= 0; n-- {
a.digits[a.count] = buf[n];
a.count++;
}
a.decimal_point = a.count;
trim(a);
}
uint_size :: 8*size_of(uint);
max_shift :: uint_size-4;
shift_right :: proc(a: ^Decimal, k: uint) {
r := 0; // read index
w := 0; // write index
n: uint;
for ; n>>k == 0; r++ {
if r >= a.count {
if n == 0 {
// Just in case
a.count = 0;
return;
}
for n>>k == 0 {
n = n * 10;
r++;
}
break;
}
c := cast(uint)a.digits[r];
n = n*10 + c - '0';
}
a.decimal_point -= r-1;
mask: uint = (1<<k) - 1;
for ; r < a.count; r++ {
c := cast(uint)a.digits[r];
dig := n>>k;
n &= mask;
a.digits[w] = cast(byte)('0' + dig);
w++;
n = n*10 + c - '0';
}
for n > 0 {
dig := n>>k;
n &= mask;
if w < a.digits.count {
a.digits[w] = cast(byte)('0' + dig);
w++;
} else if dig > 0 {
a.trunc = true;
}
n *= 10;
}
a.count = w;
trim(a);
}
shift_left :: proc(a: ^Decimal, k: uint) {
delta := cast(int)(k/4);
r := a.count; // read index
w := a.count+delta; // write index
n: uint;
for r--; r >= 0; r-- {
n += (cast(uint)a.digits[r] - '0') << k;
quo := n/10;
rem := n - 10*quo;
w--;
if w < a.digits.count {
a.digits[w] = cast(byte)('0' + rem);
} else if rem != 0 {
a.trunc = true;
}
n = quo;
}
for n > 0 {
quo := n/10;
rem := n - 10*quo;
w--;
if w < a.digits.count {
a.digits[w] = cast(byte)('0' + rem);
} else if rem != 0 {
a.trunc = true;
}
n = quo;
}
a.count += delta;
a.count = min(a.count, a.digits.count);
a.decimal_point += delta;
trim(a);
}
shift :: proc(a: ^Decimal, k: int) {
match {
case a.count == 0:
// no need to update
case k > 0:
for k > max_shift {
shift_left(a, max_shift);
k -= max_shift;
}
shift_left(a, cast(uint)k);
case k < 0:
for k < -max_shift {
shift_right(a, max_shift);
k += max_shift;
}
shift_right(a, cast(uint)-k);
}
}
can_round_up :: proc(a: ^Decimal, nd: int) -> bool {
if nd < 0 || nd >= a.count { return false ; }
if a.digits[nd] == '5' && nd+1 == a.count {
if a.trunc {
return true;
}
return nd > 0 && (a.digits[nd-1]-'0')%2 != 0;
}
return a.digits[nd] >= '5';
}
round :: proc(a: ^Decimal, nd: int) {
if nd < 0 || nd >= a.count { return; }
if can_round_up(a, nd) {
round_up(a, nd);
} else {
round_down(a, nd);
}
}
round_up :: proc(a: ^Decimal, nd: int) {
if nd < 0 || nd >= a.count { return; }
for i := nd-1; i >= 0; i-- {
if c := a.digits[i]; c < '9' {
a.digits[i]++;
a.count = i+1;
return;
}
}
// Number is just 9s
a.digits[0] = '1';
a.count = 1;
a.decimal_point++;
}
round_down :: proc(a: ^Decimal, nd: int) {
if nd < 0 || nd >= a.count { return; }
a.count = nd;
trim(a);
}
// Extract integer part, rounded appropriately. There are no guarantees about overflow.
rounded_integer :: proc(a: ^Decimal) -> u64 {
if a.decimal_point > 20 {
return 0xffff_ffff_ffff_ffff;
}
i: int;
n: u64 = 0;
m := min(a.decimal_point, a.count);
for i = 0; i < m; i++ {
n = n*10 + cast(u64)(a.digits[i]-'0');
}
for ; i < a.decimal_point; i++ {
n *= 10;
}
if can_round_up(a, a.decimal_point) {
n++;
}
return n;
}
+308 -384
View File
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -66,7 +66,7 @@ murmur32 :: proc(data: []byte) -> u32 {
h1 = h1*5 + 0xe6546b64;
}
tail := data[nblocks*4:];
tail := data[nblocks*4 ..];
k1: u32;
match tail.count&3 {
@@ -146,7 +146,7 @@ murmur64 :: proc(data: []byte) -> u64 {
i := 0;
for len >= 8 {
k1, k2: u32;
k1 = data32[i]; i += 1;
k1 = data32[i]; i++;
k1 *= m;
k1 ~= k1>>r;
k1 *= m;
@@ -154,7 +154,7 @@ murmur64 :: proc(data: []byte) -> u64 {
h1 ~= k1;
len -= 4;
k2 = data32[i]; i += 1;
k2 = data32[i]; i++;
k2 *= m;
k2 ~= k2>>r;
k2 *= m;
@@ -165,7 +165,7 @@ murmur64 :: proc(data: []byte) -> u64 {
if len >= 4 {
k1: u32;
k1 = data32[i]; i += 1;
k1 = data32[i]; i++;
k1 *= m;
k1 ~= k1>>r;
k1 *= m;
@@ -174,7 +174,7 @@ murmur64 :: proc(data: []byte) -> u64 {
len -= 4;
}
data8 := slice_to_bytes(data32[i:])[:3];
data8 := slice_to_bytes(data32[i..])[..3];
match len {
case 3:
h2 ~= cast(u32)data8[2] << 16;
+4 -4
View File
@@ -151,8 +151,8 @@ mat4_identity :: proc() -> Mat4 {
}
mat4_transpose :: proc(m: Mat4) -> Mat4 {
for j in 0..<4 {
for i in 0..<4 {
for j in 0..4 {
for i in 0..4 {
m[i][j], m[j][i] = m[j][i], m[i][j];
}
}
@@ -161,8 +161,8 @@ mat4_transpose :: proc(m: Mat4) -> Mat4 {
mul :: proc(a, b: Mat4) -> Mat4 {
c: Mat4;
for j in 0..<4 {
for i in 0..<4 {
for j in 0..4 {
for i in 0..4 {
c[j][i] = a[0][i]*b[j][0] +
a[1][i]*b[j][1] +
a[2][i]*b[j][2] +
+5 -5
View File
@@ -32,7 +32,7 @@ copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr #link_name "_
compare :: proc(a, b: []byte) -> int #link_name "__mem_compare" {
n := min(a.count, b.count);
for i in 0..<n {
for i in 0..n {
match {
case a[i] < b[i]:
return -1;
@@ -79,7 +79,7 @@ allocation_header_fill :: proc(header: ^Allocation_Header, data: rawptr, size: i
header.size = size;
ptr := cast(^int)(header+1);
for i := 0; cast(rawptr)ptr < data; i += 1 {
for i := 0; cast(rawptr)ptr < data; i++ {
(ptr+i)^ = -1;
}
}
@@ -117,7 +117,7 @@ Arena_Temp_Memory :: struct {
init_arena_from_memory :: proc(using a: ^Arena, data: []byte) {
backing = Allocator{};
memory = data[:0];
memory = data[..0];
temp_count = 0;
}
@@ -183,7 +183,7 @@ begin_arena_temp_memory :: proc(a: ^Arena) -> Arena_Temp_Memory {
tmp: Arena_Temp_Memory;
tmp.arena = a;
tmp.original_count = a.memory.count;
a.temp_count += 1;
a.temp_count++;
return tmp;
}
@@ -191,7 +191,7 @@ end_arena_temp_memory :: proc(using tmp: Arena_Temp_Memory) {
assert(arena.memory.count >= original_count);
assert(arena.temp_count > 0);
arena.memory.count = original_count;
arena.temp_count -= 1;
arena.temp_count--;
}
+3 -3
View File
@@ -95,7 +95,7 @@ open :: proc(path: string, mode: int, perm: u32) -> (Handle, Errno) {
}
buf: [300]byte;
copy(buf[:], cast([]byte)path);
copy(buf[..], cast([]byte)path);
handle := cast(Handle)CreateFileA(^buf[0], access, share_mode, sa, create_mode, FILE_ATTRIBUTE_NORMAL, nil);
if handle != INVALID_HANDLE {
@@ -184,7 +184,7 @@ last_write_time_by_name :: proc(name: string) -> File_Time {
assert(buf.count > name.count);
copy(buf[:], cast([]byte)name);
copy(buf[..], cast([]byte)name);
if win32.GetFileAttributesExA(^buf[0], win32.GetFileExInfoStandard, ^data) != 0 {
last_write_time = data.last_write_time;
@@ -201,7 +201,7 @@ last_write_time_by_name :: proc(name: string) -> File_Time {
read_entire_file :: proc(name: string) -> ([]byte, bool) {
buf: [300]byte;
copy(buf[:], cast([]byte)name);
copy(buf[..], cast([]byte)name);
fd, err := open(name, O_RDONLY, 0);
if err != ERROR_NONE {
+336
View File
@@ -0,0 +1,336 @@
#import . "decimal.odin";
#import "math.odin";
Int_Flag :: enum {
PREFIX = 1<<0,
PLUS = 1<<1,
SPACE = 1<<2,
}
parse_bool :: proc(s: string) -> (result: bool, ok: bool) {
match s {
case "1", "t", "T", "true", "TRUE", "True":
return true, true;
case "0", "f", "F", "false", "FALSE", "False":
return false, true;
}
return false, false;
}
append_bool :: proc(buf: []byte, b: bool) -> string {
s := b ? "true" : "false";
append(buf, ..cast([]byte)s);
return cast(string)buf;
}
append_uint :: proc(buf: []byte, u: u64, base: int) -> string {
return append_bits(buf, u, base, false, digits, 0);
}
append_int :: proc(buf: []byte, i: i64, base: int) -> string {
return append_bits(buf, cast(u64)i, base, i < 0, digits, 0);
}
itoa :: proc(buf: []byte, i: int) -> string {
return append_int(buf, cast(i64)i, 10);
}
append_float :: proc(buf: []byte, f: f64, fmt: byte, prec, bit_size: int) -> string {
return cast(string)generic_ftoa(buf, f, fmt, prec, bit_size);
}
Decimal_Slice :: struct {
digits: []byte,
count: int,
decimal_point: int,
neg: bool,
}
Float_Info :: struct {
mantbits: uint,
expbits: uint,
bias: int,
}
f32_info := Float_Info{23, 8, -127};
f64_info := Float_Info{52, 11, -1023};
generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, prec, bit_size: int) -> []byte {
bits: u64;
flt: ^Float_Info;
match bit_size {
case 32:
bits = cast(u64)transmute(u32)cast(f32)val;
flt = ^f32_info;
case 64:
bits = transmute(u64)val;
flt = ^f64_info;
default:
panic("strconv: invalid bit_size");
}
neg := bits>>(flt.expbits+flt.mantbits) != 0;
exp := cast(int)(bits>>flt.mantbits) & (1<<flt.expbits - 1);
mant := bits & (cast(u64)1 << flt.mantbits - 1);
match exp {
case 1<<flt.expbits - 1:
s: string;
if mant != 0 {
s = "NaN";
} else if neg {
s = "-Inf";
} else {
s = "+Inf";
}
append(buf, ..cast([]byte)s);
return buf;
case 0: // denormalized
exp++;
default:
mant |= cast(u64)1 << flt.mantbits;
}
exp += flt.bias;
d_: Decimal;
d := ^d_;
assign(d, mant);
shift(d, exp - cast(int)flt.mantbits);
digs: Decimal_Slice;
shortest := prec < 0;
if shortest {
round_shortest(d, mant, exp, flt);
digs = Decimal_Slice{digits = d.digits[..], count = d.count, decimal_point = d.decimal_point};
match fmt {
case 'e', 'E': prec = digs.count-1;
case 'f', 'F': prec = max(digs.count-digs.decimal_point, 0);
case 'g', 'G': prec = digs.count;
}
} else {
match fmt {
case 'e', 'E': round(d, prec+1);
case 'f', 'F': round(d, d.decimal_point+prec);
case 'g', 'G':
if prec == 0 {
prec = 1;
}
round(d, prec);
}
digs = Decimal_Slice{digits = d.digits[..], count = d.count, decimal_point = d.decimal_point};
}
return format_digits(buf, shortest, neg, digs, prec, fmt);
}
format_digits :: proc(buf: []byte, shortest: bool, neg: bool, digs: Decimal_Slice, prec: int, fmt: byte) -> []byte {
match fmt {
case 'f', 'F':
add_bytes :: proc(dst: ^[]byte, w: ^int, bytes: ..byte) {
for b in bytes {
if dst.capacity <= w^ {
break;
}
dst.count++;
dst[w^] = b;
w^++;
}
}
dst := buf[..];
w := 0;
if neg {
add_bytes(^dst, ^w, '-');
} else {
add_bytes(^dst, ^w, '+');
}
// integer, padded with zeros when needed
if digs.decimal_point > 0 {
m := min(digs.count, digs.decimal_point);
add_bytes(^dst, ^w, ..digs.digits[..m]);
for ; m < digs.decimal_point; m++ {
add_bytes(^dst, ^w, '0');
}
} else {
add_bytes(^dst, ^w, '0');
}
// fractional part
if prec > 0 {
add_bytes(^dst, ^w, '.');
for i in 0..prec {
c: byte = '0';
if j := digs.decimal_point + i; 0 <= j && j < digs.count {
c = digs.digits[j];
}
add_bytes(^dst, ^w, c);
}
}
return buf[..w];
case 'e', 'E':
panic("strconv: e/E float printing is not yet supported");
return buf; // TODO
case 'g', 'G':
panic("strconv: g/G float printing is not yet supported");
return buf; // TODO
}
c: [2]byte;
c[0] = '%';
c[1] = fmt;
append(buf, ..c[..]);
return buf;
}
round_shortest :: proc(d: ^Decimal, mant: u64, exp: int, flt: ^Float_Info) {
if mant == 0 { // If mantissa is zero, the number is zero
d.count = 0;
return;
}
/*
10^(dp-nd) > 2^(exp-mantbits)
log2(10) * (dp-nd) > exp-mantbits
log(2) >~ 0.332
332*(dp-nd) >= 100*(exp-mantbits)
*/
minexp := flt.bias+1;
if exp > minexp && 332*(d.decimal_point-d.count) >= 100*(exp - cast(int)flt.mantbits) {
// Number is already its shortest
return;
}
upper_: Decimal; upper: = ^upper_;
assign(upper, 2*mant - 1);
shift(upper, exp - cast(int)flt.mantbits - 1);
mantlo: u64;
explo: int;
if mant > 1<<flt.mantbits || exp == minexp {
mantlo = mant-1;
explo = exp;
} else {
mantlo = 2*mant - 1;
explo = exp-1;
}
lower_: Decimal; lower: = ^lower_;
assign(lower, 2*mantlo + 1);
shift(lower, explo - cast(int)flt.mantbits - 1);
inclusive := mant%2 == 0;
for i in 0..d.count {
l: byte = '0'; // lower digit
if i < lower.count {
l = lower.digits[i];
}
m := d.digits[i]; // middle digit
u: byte = '0'; // upper digit
if i < upper.count {
u = upper.digits[i];
}
ok_round_down := l != m || inclusive && i+1 == lower.count;
ok_round_up := m != u && (inclusive || m+1 < u || i+1 < upper.count);
if (ok_round_down && ok_round_up) {
round(d, i+1);
return;
}
if (ok_round_down) {
round_down(d, i+1);
return;
}
if (ok_round_up) {
round_up(d, i+1);
return;
}
}
}
MAX_BASE :: 32;
immutable digits := "0123456789abcdefghijklmnopqrstuvwxyz";
append_bits :: proc(buf: []byte, u: u64, base: int, neg: bool, digits: string, flags: Int_Flag) -> string {
is_pow2 :: proc(x: i64) -> bool {
if (x <= 0) {
return false;
}
return x&(x-1) == 0;
}
if base < 2 || base > MAX_BASE {
panic("strconv: illegal base passed to append_bits");
}
a: [65]byte;
i := a.count;
if neg {
u = -u;
}
if is_pow2(cast(i64)base) {
b := cast(u64)base;
m := cast(uint)b - 1;
for u >= b {
i--;
a[i] = digits[cast(uint)u & m];
u >>= b;
}
i--;
a[i] = digits[cast(uint)u];
} else {
b := cast(u64)base;
for u >= b {
i--;
q := u / b;
a[i] = digits[cast(uint)(u-q*b)];
u = q;
}
i--;
a[i] = digits[cast(uint)u];
}
if flags&Int_Flag.PREFIX != 0 {
ok := true;
match base {
case 2: i--; a[i] = 'b';
case 8: i--; a[i] = 'o';
case 10: i--; a[i] = 'd';
case 16: i--; a[i] = 'x';
default: ok = false;
}
if ok {
i--;
a[i] = '0';
}
}
if neg {
i--; a[i] = '-';
} else if flags&Int_Flag.PLUS != 0 {
i--; a[i] = '+';
} else if flags&Int_Flag.SPACE != 0 {
i--; a[i] = ' ';
}
append(buf, ..a[i..]);
return cast(string)buf;
}
+15
View File
@@ -0,0 +1,15 @@
new_c_string :: proc(s: string) -> ^byte {
c := new_slice(byte, s.count+1);
copy(c, cast([]byte)s);
c[s.count] = 0;
return c.data;
}
to_odin_string :: proc(c: ^byte) -> string {
s: string;
s.data = c;
for (c+s.count)^ != 0 {
s.count++;
}
return s;
}
+31 -31
View File
@@ -2,14 +2,14 @@
#import "atomic.odin";
Semaphore :: struct {
handle: win32.HANDLE,
_handle: win32.HANDLE,
}
Mutex :: struct {
semaphore: Semaphore,
counter: i32,
owner: i32,
recursion: i32,
_semaphore: Semaphore,
_counter: i32,
_owner: i32,
_recursion: i32,
}
current_thread_id :: proc() -> i32 {
@@ -17,74 +17,74 @@ current_thread_id :: proc() -> i32 {
}
semaphore_init :: proc(s: ^Semaphore) {
s.handle = win32.CreateSemaphoreA(nil, 0, 1<<31-1, nil);
s._handle = win32.CreateSemaphoreA(nil, 0, 1<<31-1, nil);
}
semaphore_destroy :: proc(s: ^Semaphore) {
win32.CloseHandle(s.handle);
win32.CloseHandle(s._handle);
}
semaphore_post :: proc(s: ^Semaphore, count: int) {
win32.ReleaseSemaphore(s.handle, cast(i32)count, nil);
win32.ReleaseSemaphore(s._handle, cast(i32)count, nil);
}
semaphore_release :: proc(s: ^Semaphore) #inline { semaphore_post(s, 1); }
semaphore_wait :: proc(s: ^Semaphore) {
win32.WaitForSingleObject(s.handle, win32.INFINITE);
win32.WaitForSingleObject(s._handle, win32.INFINITE);
}
mutex_init :: proc(m: ^Mutex) {
atomic.store(^m.counter, 0);
atomic.store(^m.owner, current_thread_id());
semaphore_init(^m.semaphore);
m.recursion = 0;
atomic.store(^m._counter, 0);
atomic.store(^m._owner, current_thread_id());
semaphore_init(^m._semaphore);
m._recursion = 0;
}
mutex_destroy :: proc(m: ^Mutex) {
semaphore_destroy(^m.semaphore);
semaphore_destroy(^m._semaphore);
}
mutex_lock :: proc(m: ^Mutex) {
thread_id := current_thread_id();
if atomic.fetch_add(^m.counter, 1) > 0 {
if thread_id != atomic.load(^m.owner) {
semaphore_wait(^m.semaphore);
if atomic.fetch_add(^m._counter, 1) > 0 {
if thread_id != atomic.load(^m._owner) {
semaphore_wait(^m._semaphore);
}
}
atomic.store(^m.owner, thread_id);
m.recursion += 1;
atomic.store(^m._owner, thread_id);
m._recursion++;
}
mutex_try_lock :: proc(m: ^Mutex) -> bool {
thread_id := current_thread_id();
if atomic.load(^m.owner) == thread_id {
atomic.fetch_add(^m.counter, 1);
if atomic.load(^m._owner) == thread_id {
atomic.fetch_add(^m._counter, 1);
} else {
expected: i32 = 0;
if atomic.load(^m.counter) != 0 {
if atomic.load(^m._counter) != 0 {
return false;
}
if atomic.compare_exchange(^m.counter, expected, 1) == 0 {
if atomic.compare_exchange(^m._counter, expected, 1) == 0 {
return false;
}
atomic.store(^m.owner, thread_id);
atomic.store(^m._owner, thread_id);
}
m.recursion += 1;
m._recursion++;
return true;
}
mutex_unlock :: proc(m: ^Mutex) {
recursion: i32;
thread_id := current_thread_id();
assert(thread_id == atomic.load(^m.owner));
assert(thread_id == atomic.load(^m._owner));
m.recursion -= 1;
recursion = m.recursion;
m._recursion--;
recursion = m._recursion;
if recursion == 0 {
atomic.store(^m.owner, thread_id);
atomic.store(^m._owner, thread_id);
}
if atomic.fetch_add(^m.counter, -1) > 1 {
if atomic.fetch_add(^m._counter, -1) > 1 {
if recursion == 0 {
semaphore_release(^m.semaphore);
semaphore_release(^m._semaphore);
}
}
}
+75 -8
View File
@@ -40,14 +40,19 @@ WS_CAPTION :: 0x00C00000;
WS_VISIBLE :: 0x10000000;
WS_OVERLAPPEDWINDOW :: WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX;
WM_DESTROY :: 0x0002;
WM_SIZE :: 0x0005;
WM_CLOSE :: 0x0010;
WM_ACTIVATEAPP :: 0x001C;
WM_QUIT :: 0x0012;
WM_KEYDOWN :: 0x0100;
WM_KEYUP :: 0x0101;
WM_SIZING :: 0x0214;
WM_DESTROY :: 0x0002;
WM_SIZE :: 0x0005;
WM_CLOSE :: 0x0010;
WM_ACTIVATEAPP :: 0x001C;
WM_QUIT :: 0x0012;
WM_KEYDOWN :: 0x0100;
WM_KEYUP :: 0x0101;
WM_SIZING :: 0x0214;
WM_MOUSEWHEEL :: 0x020A;
WM_SYSKEYDOWN :: 0x0104;
WM_WINDOWPOSCHANGED :: 0x0047;
WM_SETCURSOR :: 0x0020;
WM_CHAR :: 0x0102;
PM_REMOVE :: 1;
@@ -300,6 +305,68 @@ ReadBarrier :: proc() #foreign kernel32;
HMONITOR :: HANDLE;
GWL_STYLE :: -16;
HWND_TOP :: cast(HWND)cast(uint)0;
MONITOR_DEFAULTTONULL :: 0x00000000;
MONITOR_DEFAULTTOPRIMARY :: 0x00000001;
MONITOR_DEFAULTTONEAREST :: 0x00000002;
SWP_FRAMECHANGED :: 0x0020;
SWP_NOOWNERZORDER :: 0x0200;
SWP_NOZORDER :: 0x0004;
SWP_NOSIZE :: 0x0001;
SWP_NOMOVE :: 0x0002;
MONITORINFO :: struct #ordered {
size: u32,
monitor: RECT,
work: RECT,
flags: u32,
}
WINDOWPLACEMENT :: struct #ordered {
length: u32,
flags: u32,
show_cmd: u32,
min_pos: POINT,
max_pos: POINT,
normal_pos: RECT,
}
GetMonitorInfoA :: proc(monitor: HMONITOR, mi: ^MONITORINFO) -> BOOL #foreign user32;
MonitorFromWindow :: proc(wnd: HWND, flags : u32) -> HMONITOR #foreign user32;
SetWindowPos :: proc(wnd: HWND, wndInsertAfter: HWND, x, y, width, height: i32, flags: u32) #foreign user32 "SetWindowPos";
GetWindowPlacement :: proc(wnd: HWND, wndpl: ^WINDOWPLACEMENT) -> BOOL #foreign user32;
SetWindowPlacement :: proc(wnd: HWND, wndpl: ^WINDOWPLACEMENT) -> BOOL #foreign user32;
GetWindowLongPtrA :: proc(wnd: HWND, index: i32) -> i64 #foreign user32;
SetWindowLongPtrA :: proc(wnd: HWND, index: i32, new: i64) -> i64 #foreign user32;
GetWindowText :: proc(wnd: HWND, str: ^byte, maxCount: i32) -> i32 #foreign user32;
HIWORD :: proc(wParam: WPARAM) -> u16 { return cast(u16)((cast(u32)wParam >> 16) & 0xffff); }
HIWORD :: proc(lParam: LPARAM) -> u16 { return cast(u16)((cast(u32)lParam >> 16) & 0xffff); }
LOWORD :: proc(wParam: WPARAM) -> u16 { return cast(u16)wParam; }
LOWORD :: proc(lParam: LPARAM) -> u16 { return cast(u16)lParam; }
BITMAPINFOHEADER :: struct #ordered {
size: u32,
width, height: i32,
+51 -7
View File
@@ -92,7 +92,8 @@ encode_rune :: proc(r: rune) -> ([4]byte, int) {
return buf, 4;
}
decode_rune :: proc(s: string) -> (rune, int) {
decode_rune :: proc(s: string) -> (rune, int) #inline { return decode_rune(cast([]byte)s); }
decode_rune :: proc(s: []byte) -> (rune, int) {
n := s.count;
if n < 1 {
return RUNE_ERROR, 0;
@@ -130,6 +131,46 @@ decode_rune :: proc(s: string) -> (rune, int) {
}
decode_last_rune :: proc(s: string) -> (rune, int) #inline { return decode_last_rune(cast([]byte)s); }
decode_last_rune :: proc(s: []byte) -> (rune, int) {
r: rune;
size: int;
start, end, limit: int;
end = s.count;
if end == 0 {
return RUNE_ERROR, 0;
}
start = end-1;
r = cast(rune)s[start];
if r < RUNE_SELF {
return r, 1;
}
limit = max(end - UTF_MAX, 0);
start--;
for start >= limit {
if rune_start(s[start]) {
break;
}
start--;
}
start = max(start, 0);
r, size = decode_rune(s[start..end]);
if start+size != end {
return RUNE_ERROR, 1;
}
return r, size;
}
valid_rune :: proc(r: rune) -> bool {
if r < 0 {
return false;
@@ -146,7 +187,7 @@ valid_string :: proc(s: string) -> bool {
for i := 0; i < n; {
si := s[i];
if si < RUNE_SELF { // ascii
i += 1;
i++;
continue;
}
x := accept_sizes[si];
@@ -174,25 +215,28 @@ valid_string :: proc(s: string) -> bool {
return true;
}
rune_count :: proc(s: string) -> int {
rune_start :: proc(b: byte) -> bool #inline { return b&0xc0 != 0x80; }
rune_count :: proc(s: string) -> int #inline { return rune_count(cast([]byte)s); }
rune_count :: proc(s: []byte) -> int {
count := 0;
n := s.count;
for i := 0; i < n; {
defer count += 1;
defer count++;
si := s[i];
if si < RUNE_SELF { // ascii
i += 1;
i++;
continue;
}
x := accept_sizes[si];
if x == 0xf1 {
i += 1;
i++;
continue;
}
size := cast(int)(x & 7);
if i+size > n {
i += 1;
i++;
continue;
}
ar := accept_ranges[x>>4];
+88 -33
View File
@@ -197,11 +197,11 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) {
}
}
// if (is_type_proc(dst)) {
// if (are_types_identical(src, dst)) {
// return 1;
// }
// }
if (is_type_proc(dst)) {
if (are_types_identical(src, dst)) {
return 3;
}
}
if (is_type_any(dst)) {
// NOTE(bill): Anything can cast to `Any`
@@ -2827,6 +2827,16 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
goto error;
}
}
if (entity == NULL &&
operand->type != NULL && is_type_untyped(operand->type) && is_type_string(operand->type)) {
String s = operand->value.value_string;
operand->mode = Addressing_Constant;
operand->value = make_exact_value_integer(s.len);
operand->type = t_untyped_integer;
return NULL;
}
if (entity == NULL) {
gbString op_str = expr_to_string(op_expr);
gbString type_str = type_to_string(operand->type);
@@ -2908,9 +2918,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
err = "Too many";
}
if (err) {
if (err != NULL) {
gbString expr = expr_to_string(ce->proc);
error(ce->close, "`%s` arguments for `%s`, expected %td, got %td",
error(ce->close, "%s arguments for `%s`, expected %td, got %td",
err, expr,
bp->arg_count, ce->args.count);
gb_string_free(expr);
@@ -2952,6 +2962,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
} break;
case BuiltinProc_new_slice: {
// new_slice :: proc(Type, len: int) -> []Type
// new_slice :: proc(Type, len, cap: int) -> []Type
Operand op = {0};
check_expr_or_type(c, &op, ce->args.e[0]);
Type *type = op.type;
@@ -2960,15 +2971,27 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
return false;
}
check_expr(c, &op, ce->args.e[1]);
if (op.mode == Addressing_Invalid) {
return false;
}
if (!is_type_integer(op.type)) {
gbString type_str = type_to_string(op.type);
error_node(call, "Length for `new_slice` must be an integer, got `%s`", type_str);
gb_string_free(type_str);
return false;
isize arg_count = ce->args.count;
if (arg_count < 2 || 3 < arg_count) {
error_node(ce->args.e[0], "`new_slice` expects 2 or 3 arguments, found %td", arg_count);
// NOTE(bill): Return the correct type to reduce errors
} else {
// If any are constant
i64 sizes[2] = {0};
isize size_count = 0;
for (isize i = 1; i < arg_count; i++) {
i64 val = 0;
bool ok = check_index_value(c, ce->args.e[i], -1, &val);
if (ok && val >= 0) {
GB_ASSERT(size_count < gb_count_of(sizes));
sizes[size_count++] = val;
}
}
if (size_count == 2 && sizes[0] > sizes[1]) {
error_node(ce->args.e[1], "`new_slice` count and capacity are swapped");
// No need quit
}
}
operand->mode = Addressing_Value;
@@ -3047,19 +3070,36 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
} break;
case BuiltinProc_append: {
// append :: proc([dynamic]Type, item: ...Type)
// append :: proc([dynamic]Type, item: ..Type)
// append :: proc([]Type, item: ..Type)
Type *type = operand->type;
type = base_type(type);
if (!is_type_dynamic_array(type)) {
bool is_pointer = is_type_pointer(type);
type = base_type(type_deref(type));
if (!is_type_dynamic_array(type) && !is_type_slice(type)) {
gbString str = type_to_string(type);
error_node(operand->expr, "Expected a dynamic array, got `%s`", str);
error_node(operand->expr, "Expected a slice or dynamic array, got `%s`", str);
gb_string_free(str);
return false;
}
// TODO(bill): Semi-memory leaks
Type *elem = type->DynamicArray.elem;
Type *slice_elem = make_type_slice(c->allocator, elem);
bool is_addressable = operand->mode == Addressing_Variable;
if (is_pointer) {
is_addressable = true;
}
if (!is_addressable) {
error_node(operand->expr, "`append` can only operate on addressable values");
return false;
}
Type *elem = NULL;
Type *slice_elem = NULL;
if (is_type_dynamic_array(type)) {
// TODO(bill): Semi-memory leaks
elem = type->DynamicArray.elem;
} else {
elem = type->Slice.elem;
}
slice_elem = make_type_slice(c->allocator, elem);
Type *proc_type_params = make_type_tuple(c->allocator);
proc_type_params->Tuple.variables = gb_alloc_array(c->allocator, Entity *, 2);
@@ -3394,7 +3434,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
} break;
case BuiltinProc_swizzle: {
// swizzle :: proc(v: {N}T, T...) -> {M}T
// swizzle :: proc(v: {N}T, T..) -> {M}T
Type *vector_type = base_type(operand->type);
if (!is_type_vector(vector_type)) {
gbString type_str = type_to_string(operand->type);
@@ -5110,6 +5150,10 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
switch (t->kind) {
case Type_Basic:
if (is_type_string(t)) {
if (se->index3) {
error_node(node, "3-index slice on a string in not needed");
goto error;
}
valid = true;
if (o->mode == Addressing_Constant) {
max_count = o->value.value_string.len;
@@ -5150,14 +5194,20 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
o->mode = Addressing_Value;
}
if (se->index3 && (se->high == NULL || se->max == NULL)) {
error(se->close, "2nd and 3rd indices are required in a 3-index slice");
goto error;
}
i64 indices[2] = {0};
AstNode *nodes[2] = {se->low, se->high};
AstNode *nodes[3] = {se->low, se->high, se->max};
for (isize i = 0; i < gb_count_of(nodes); i++) {
i64 index = max_count;
if (nodes[i] != NULL) {
i64 capacity = -1;
if (max_count >= 0)
if (max_count >= 0) {
capacity = max_count;
}
i64 j = 0;
if (check_index_value(c, nodes[i], capacity, &j)) {
index = j;
@@ -5423,13 +5473,17 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
str = write_expr_to_string(str, se->expr);
str = gb_string_appendc(str, "[");
str = write_expr_to_string(str, se->low);
str = gb_string_appendc(str, ":");
str = gb_string_appendc(str, "..");
str = write_expr_to_string(str, se->high);
if (se->index3) {
str = gb_string_appendc(str, "..");
str = write_expr_to_string(str, se->max);
}
str = gb_string_appendc(str, "]");
case_end;
case_ast_node(e, Ellipsis, node);
str = gb_string_appendc(str, "...");
str = gb_string_appendc(str, "..");
case_end;
case_ast_node(fv, FieldValue, node);
@@ -5445,9 +5499,10 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
case_ast_node(at, ArrayType, node);
str = gb_string_appendc(str, "[");
if (at->count->kind == AstNode_UnaryExpr &&
at->count->UnaryExpr.op.kind == Token_Hash) {
str = gb_string_appendc(str, "#");
if (at->count != NULL &&
at->count->kind == AstNode_UnaryExpr &&
at->count->UnaryExpr.op.kind == Token_Ellipsis) {
str = gb_string_appendc(str, "..");
} else {
str = write_expr_to_string(str, at->count);
}
@@ -5456,7 +5511,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
case_end;
case_ast_node(at, DynamicArrayType, node);
str = gb_string_appendc(str, "[...]");
str = gb_string_appendc(str, "[..]");
str = write_expr_to_string(str, at->elem);
case_end;
@@ -5489,7 +5544,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
str = gb_string_appendc(str, ": ");
}
if (f->flags&FieldFlag_ellipsis) {
str = gb_string_appendc(str, "...");
str = gb_string_appendc(str, "..");
}
str = write_expr_to_string(str, f->type);
case_end;
+48 -4
View File
@@ -421,6 +421,49 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
check_stmt(c, ts->stmt, flags);
case_end;
case_ast_node(s, IncDecStmt, node);
TokenKind op = s->op.kind;
switch (op) {
case Token_Inc: op = Token_Add; break;
case Token_Dec: op = Token_Sub; break;
default:
error_node(node, "Invalid inc/dec operation");
return;
}
Operand x = {0};
check_expr(c, &x, s->expr);
if (x.mode == Addressing_Invalid) {
return;
}
if (!is_type_integer(x.type) && !is_type_float(x.type)) {
gbString e = expr_to_string(s->expr);
gbString t = type_to_string(x.type);
error_node(node, "%s%.*s used on non-numeric type %s", e, LIT(s->op.string), t);
gb_string_free(t);
gb_string_free(e);
return;
}
AstNode *left = s->expr;
AstNode *right = gb_alloc_item(c->allocator, AstNode);
right->kind = AstNode_BasicLit;
right->BasicLit.pos = s->op.pos;
right->BasicLit.kind = Token_Integer;
right->BasicLit.string = str_lit("1");
AstNode *be = gb_alloc_item(c->allocator, AstNode);
be->kind = AstNode_BinaryExpr;
be->BinaryExpr.op = s->op;
be->BinaryExpr.op.kind = op;
be->BinaryExpr.left = left;
be->BinaryExpr.right = right;
check_binary_expr(c, &x, be);
if (x.mode == Addressing_Invalid) {
return;
}
check_assignment_variable(c, &x, left);
case_end;
case_ast_node(as, AssignStmt, node);
switch (as->op.kind) {
case Token_Eq: {
@@ -591,8 +634,9 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
if (fs->post != NULL) {
check_stmt(c, fs->post, 0);
if (fs->post->kind != AstNode_AssignStmt) {
error_node(fs->post, "`for` statement post statement must be an assignment");
if (fs->post->kind != AstNode_AssignStmt &&
fs->post->kind != AstNode_IncDecStmt) {
error_node(fs->post, "`for` statement post statement must be a simple statement");
}
}
check_stmt(c, fs->body, new_flags);
@@ -671,8 +715,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
TokenKind op = Token_Lt;
switch (ie->op.kind) {
case Token_HalfOpenRange: op = Token_Lt; break;
case Token_Ellipsis: op = Token_LtEq; break;
case Token_Ellipsis: op = Token_Lt; break;
default: error(ie->op, "Invalid range operator"); break;
}
bool ok = compare_exact_values(Token_Lt, a, b);
@@ -1215,6 +1258,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
case Entity_Variable: {
Type *t = base_type(type_deref(e->type));
if (is_type_struct(t) || is_type_raw_union(t)) {
// TODO(bill): Make it work for unions too
Scope **found = map_scope_get(&c->info.scopes, hash_pointer(t->Record.node));
GB_ASSERT(found != NULL);
for_array(i, (*found)->elements.entries) {
+1 -1
View File
@@ -68,7 +68,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
{STR_LIT(""), 0, false, Expr_Stmt},
{STR_LIT("new"), 1, false, Expr_Expr},
{STR_LIT("new_slice"), 2, false, Expr_Expr},
{STR_LIT("new_slice"), 2, true, Expr_Expr},
{STR_LIT("free"), 1, false, Expr_Stmt},
{STR_LIT("reserve"), 2, false, Expr_Stmt},
+4 -3
View File
@@ -274,8 +274,7 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
case ExactValue_Invalid:
return v;
case ExactValue_Integer:
i = v.value_integer;
i = ~i;
i = ~v.value_integer;
break;
default:
goto failure;
@@ -283,8 +282,10 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
// NOTE(bill): unsigned integers will be negative and will need to be
// limited to the types precision
if (precision > 0)
// IMPORTANT NOTE(bill): Max precision is 64 bits as that's how integers are stored
if (0 < precision && precision < 64) {
i &= ~((~0ll)<<precision);
}
return make_exact_value_integer(i);
} break;
+139 -102
View File
@@ -218,6 +218,7 @@ struct irProcedure {
TokenPos pos; \
irValue *low; \
irValue *high; \
irValue *max; \
bool is_substring; \
}) \
IR_INSTR_KIND(DebugDeclare, struct { \
@@ -233,6 +234,7 @@ struct irProcedure {
#define IR_CONV_KINDS \
IR_CONV_KIND(trunc) \
IR_CONV_KIND(zext) \
IR_CONV_KIND(sext) \
IR_CONV_KIND(fptrunc) \
IR_CONV_KIND(fpext) \
IR_CONV_KIND(fptoui) \
@@ -955,11 +957,12 @@ irValue *ir_make_instr_bounds_check(irProcedure *p, TokenPos pos, irValue *index
v->Instr.BoundsCheck.len = len;
return v;
}
irValue *ir_make_instr_slice_bounds_check(irProcedure *p, TokenPos pos, irValue *low, irValue *high, bool is_substring) {
irValue *ir_make_instr_slice_bounds_check(irProcedure *p, TokenPos pos, irValue *low, irValue *high, irValue *max, bool is_substring) {
irValue *v = ir_alloc_instr(p, irInstr_SliceBoundsCheck);
v->Instr.SliceBoundsCheck.pos = pos;
v->Instr.SliceBoundsCheck.low = low;
v->Instr.SliceBoundsCheck.high = high;
v->Instr.SliceBoundsCheck.max = max;
v->Instr.SliceBoundsCheck.is_substring = is_substring;
return v;
}
@@ -1844,6 +1847,7 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) {
switch (index) {
case 0: result_type = make_type_pointer(a, make_type_pointer(a, t->Slice.elem)); break;
case 1: result_type = make_type_pointer(a, t_int); break;
case 2: result_type = make_type_pointer(a, t_int); break;
}
} else if (is_type_string(t)) {
switch (index) {
@@ -2069,6 +2073,11 @@ irValue *ir_slice_count(irProcedure *proc, irValue *slice) {
GB_ASSERT(t->kind == Type_Slice);
return ir_emit_struct_ev(proc, slice, 1);
}
irValue *ir_slice_capacity(irProcedure *proc, irValue *slice) {
Type *t = base_type(ir_type(slice));
GB_ASSERT(t->kind == Type_Slice);
return ir_emit_struct_ev(proc, slice, 2);
}
irValue *ir_dynamic_array_elem(irProcedure *proc, irValue *da) {
Type *t = ir_type(da);
@@ -2105,8 +2114,19 @@ irValue *ir_string_len(irProcedure *proc, irValue *string) {
}
void ir_fill_slice(irProcedure *proc, irValue *slice_ptr, irValue *data, irValue *count, irValue *capacity) {
Type *t = ir_type(slice_ptr);
GB_ASSERT(is_type_pointer(t));
t = type_deref(t);
GB_ASSERT(is_type_slice(t));
ir_emit_store(proc, ir_emit_struct_ep(proc, slice_ptr, 0), data);
ir_emit_store(proc, ir_emit_struct_ep(proc, slice_ptr, 1), count);
ir_emit_store(proc, ir_emit_struct_ep(proc, slice_ptr, 2), capacity);
}
irValue *ir_add_local_slice(irProcedure *proc, Type *slice_type, irValue *base, irValue *low, irValue *high) {
irValue *ir_add_local_slice(irProcedure *proc, Type *slice_type, irValue *base, irValue *low, irValue *high, irValue *max) {
// TODO(bill): array bounds checking for slice creation
// TODO(bill): check that low < high <= max
gbAllocator a = proc->module->allocator;
@@ -2122,8 +2142,16 @@ irValue *ir_add_local_slice(irProcedure *proc, Type *slice_type, irValue *base,
case Type_Pointer: high = v_one; break;
}
}
if (max == NULL) {
switch (bt->kind) {
case Type_Array: high = ir_array_len(proc, base); break;
case Type_Slice: high = ir_slice_capacity(proc, base); break;
case Type_Pointer: high = v_one; break;
}
}
irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int);
irValue *cap = ir_emit_arith(proc, Token_Sub, max, low, t_int);
irValue *elem = NULL;
switch (bt->kind) {
@@ -2135,14 +2163,7 @@ irValue *ir_add_local_slice(irProcedure *proc, Type *slice_type, irValue *base,
elem = ir_emit_ptr_offset(proc, elem, low);
irValue *slice = ir_add_local_generated(proc, slice_type);
irValue *gep = NULL;
gep = ir_emit_struct_ep(proc, slice, 0);
ir_emit_store(proc, gep, elem);
gep = ir_emit_struct_ep(proc, slice, 1);
ir_emit_store(proc, gep, len);
ir_fill_slice(proc, slice, elem, len, cap);
return slice;
}
@@ -2240,12 +2261,23 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
i64 sz = type_size_of(proc->module->allocator, src);
i64 dz = type_size_of(proc->module->allocator, dst);
irConvKind kind = irConv_trunc;
if (sz == dz) {
if (dz == sz) {
// NOTE(bill): In LLVM, all integers are signed and rely upon 2's compliment
// NOTE(bill): Copy the value just for type correctness
kind = irConv_bitcast;
} else if (dz > sz) {
kind = irConv_zext;
// TODO(bill): figure out the rules completely
bool ss = !is_type_unsigned(src);
bool ds = !is_type_unsigned(dst);
if (ss && ds) {
kind = irConv_sext;
} else if (ss) {
kind = irConv_sext;
} else {
kind = irConv_zext;
}
}
return ir_emit(proc, ir_make_instr_conv(proc, kind, value, src, dst));
@@ -2374,7 +2406,8 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
ir_emit_store(proc, elem_ptr, elem);
irValue *len = ir_string_len(proc, value);
irValue *slice = ir_add_local_slice(proc, dst, elem_ptr, v_zero, len);
irValue *cap = len;
irValue *slice = ir_add_local_slice(proc, dst, elem_ptr, v_zero, len, cap);
return ir_emit_load(proc, slice);
}
@@ -2745,7 +2778,7 @@ void ir_emit_bounds_check(irProcedure *proc, Token token, irValue *index, irValu
ir_emit(proc, ir_make_instr_bounds_check(proc, token.pos, index, len));
}
void ir_emit_slice_bounds_check(irProcedure *proc, Token token, irValue *low, irValue *high, bool is_substring) {
void ir_emit_slice_bounds_check(irProcedure *proc, Token token, irValue *low, irValue *high, irValue *max, bool is_substring) {
if ((proc->module->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) {
return;
}
@@ -2753,10 +2786,11 @@ void ir_emit_slice_bounds_check(irProcedure *proc, Token token, irValue *low, ir
low = ir_emit_conv(proc, low, t_int);
high = ir_emit_conv(proc, high, t_int);
ir_emit(proc, ir_make_instr_slice_bounds_check(proc, token.pos, low, high, is_substring));
ir_emit(proc, ir_make_instr_slice_bounds_check(proc, token.pos, low, high, max, is_substring));
}
////////////////////////////////////////////////////////////////
//
// @Build
@@ -3134,7 +3168,8 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
case BuiltinProc_new_slice: {
ir_emit_comment(proc, str_lit("new_slice"));
// new_slice :: proc(Type, len: int) -> ^Type
// new_slice :: proc(Type, len: int) -> []Type
// new_slice :: proc(Type, len, cap: int) -> []Type
gbAllocator allocator = proc->module->allocator;
Type *type = type_of_expr(proc->module->info, ce->args.e[0]);
@@ -3148,10 +3183,15 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
irValue *elem_align = ir_make_const_int(allocator, a);
irValue *count = ir_emit_conv(proc, ir_build_expr(proc, ce->args.e[1]), t_int);
irValue *capacity = count;
ir_emit_slice_bounds_check(proc, ast_node_token(ce->args.e[1]), v_zero, count, false);
if (ce->args.count == 3) {
capacity = ir_emit_conv(proc, ir_build_expr(proc, ce->args.e[2]), t_int);
}
irValue *slice_size = ir_emit_arith(proc, Token_Mul, elem_size, count, t_int);
ir_emit_slice_bounds_check(proc, ast_node_token(ce->args.e[1]), v_zero, count, capacity, false);
irValue *slice_size = ir_emit_arith(proc, Token_Mul, elem_size, capacity, t_int);
irValue **args = gb_alloc_array(allocator, irValue *, 2);
args[0] = slice_size;
@@ -3161,10 +3201,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
irValue *ptr = ir_emit_conv(proc, call, ptr_type);
irValue *slice = ir_add_local_generated(proc, slice_type);
irValue *gep0 = ir_emit_struct_ep(proc, slice, 0);
irValue *gep1 = ir_emit_struct_ep(proc, slice, 1);
ir_emit_store(proc, gep0, ptr);
ir_emit_store(proc, gep1, count);
ir_fill_slice(proc, slice, ptr, count, capacity);
return ir_emit_load(proc, slice);
} break;
@@ -3299,12 +3336,25 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
ir_emit_comment(proc, str_lit("append"));
gbAllocator a = proc->module->allocator;
irValue *array_ptr = ir_build_addr(proc, ce->args.e[0]).addr;
Type *value_type = type_of_expr(proc->module->info, ce->args.e[0]);
irAddr array_addr = ir_build_addr(proc, ce->args.e[0]);
irValue *array_ptr = array_addr.addr;
if (is_type_pointer(value_type)) {
array_ptr = ir_addr_load(proc, array_addr);
}
Type *type = ir_type(array_ptr);
GB_ASSERT(is_type_pointer(type));
type = base_type(type_deref(type));
GB_ASSERT(is_type_dynamic_array(type));
Type *elem_type = type->DynamicArray.elem;
Type *elem_type = NULL;
bool is_slice = false;
if (is_type_dynamic_array(type)) {
elem_type = type->DynamicArray.elem;
} else if (is_type_slice(type)) {
is_slice = true;
elem_type = type->Slice.elem;
} else {
GB_PANIC("Invalid type to append");
}
irValue *elem_size = ir_make_const_int(a, type_size_of(a, elem_type));
irValue *elem_align = ir_make_const_int(a, type_align_of(a, elem_type));
@@ -3361,10 +3411,8 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
}
irValue *base_elem = ir_emit_array_epi(proc, base_array, 0);
irValue *slice_elem = ir_emit_struct_ep(proc, slice, 0);
ir_emit_store(proc, slice_elem, base_elem);
irValue *len = ir_make_const_int(a, slice_len);
ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 1), len);
ir_fill_slice(proc, slice, base_elem, len, len);
}
arg_count = 2;
@@ -3381,6 +3429,10 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
daa_args[2] = elem_align;
daa_args[3] = ir_emit_conv(proc, items, t_rawptr);
daa_args[4] = ir_emit_conv(proc, item_count, t_int);
if (is_slice) {
return ir_emit_global_call(proc, "__slice_append", daa_args, 5);
}
return ir_emit_global_call(proc, "__dynamic_array_append", daa_args, 5);
} break;
@@ -3526,8 +3578,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
Type *slice_type = make_type_slice(proc->module->allocator, type_deref(ir_type(ptr)));
irValue *slice = ir_add_local_generated(proc, slice_type);
ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 0), ptr);
ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 1), count);
ir_fill_slice(proc, slice, ptr, count, count);
return ir_emit_load(proc, slice);
} break;
@@ -3544,9 +3595,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
irValue *ptr = ir_emit_conv(proc, ir_slice_elem(proc, s), t_u8_ptr);
irValue *count = ir_slice_count(proc, s);
count = ir_emit_arith(proc, Token_Mul, count, ir_make_const_int(proc->module->allocator, elem_size), t_int);
ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 0), ptr);
ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 1), count);
ir_fill_slice(proc, slice, ptr, count, count);
return ir_emit_load(proc, slice);
} break;
@@ -3669,11 +3718,9 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
ir_emit_store(proc, addr, args[i]);
}
irValue *base_elem = ir_emit_array_epi(proc, base_array, 0);
irValue *slice_elem = ir_emit_struct_ep(proc, slice, 0);
ir_emit_store(proc, slice_elem, base_elem);
irValue *base_elem = ir_emit_array_epi(proc, base_array, 0);
irValue *len = ir_make_const_int(allocator, slice_len);
ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 1), len);
ir_fill_slice(proc, slice, base_elem, len, len);
}
arg_count = type->param_count;
@@ -4064,9 +4111,11 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
gbAllocator a = proc->module->allocator;
irValue *low = v_zero;
irValue *high = NULL;
irValue *max = NULL;
if (se->low != NULL) low = ir_build_expr(proc, se->low);
if (se->high != NULL) high = ir_build_expr(proc, se->high);
if (se->max != NULL) max = ir_build_expr(proc, se->max);
irValue *addr = ir_build_addr(proc, se->expr).addr;
irValue *base = ir_emit_load(proc, addr);
Type *type = base_type(ir_type(base));
@@ -4084,16 +4133,15 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
Type *slice_type = type;
if (high == NULL) high = ir_slice_count(proc, base);
if (max == NULL) max = ir_slice_capacity(proc, base);
ir_emit_slice_bounds_check(proc, se->open, low, high, false);
ir_emit_slice_bounds_check(proc, se->open, low, high, max, false);
irValue *elem = ir_emit_ptr_offset(proc, ir_slice_elem(proc, base), low);
irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int);
irValue *cap = ir_emit_arith(proc, Token_Sub, max, low, t_int);
irValue *slice = ir_add_local_generated(proc, slice_type);
ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 0), elem);
ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 1), len);
ir_fill_slice(proc, slice, elem, len, cap);
return ir_make_addr(slice);
}
@@ -4101,16 +4149,15 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
Type *dynamic_array = type;
if (high == NULL) high = ir_dynamic_array_count(proc, base);
if (max == NULL) max = ir_dynamic_array_capacity(proc, base);
ir_emit_slice_bounds_check(proc, se->open, low, high, false);
ir_emit_slice_bounds_check(proc, se->open, low, high, max, false);
irValue *elem = ir_emit_ptr_offset(proc, ir_dynamic_array_elem(proc, base), low);
irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int);
irValue *cap = ir_emit_arith(proc, Token_Sub, max, low, t_int);
irValue *slice = ir_add_local_generated(proc, dynamic_array);
ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 0), elem);
ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 1), len);
ir_fill_slice(proc, slice, elem, len, cap);
return ir_make_addr(slice);
}
@@ -4119,38 +4166,31 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
Type *slice_type = make_type_slice(a, type->Array.elem);
if (high == NULL) high = ir_array_len(proc, base);
if (max == NULL) max = ir_array_len(proc, base);
ir_emit_slice_bounds_check(proc, se->open, low, high, false);
ir_emit_slice_bounds_check(proc, se->open, low, high, max, false);
irValue *elem = ir_emit_ptr_offset(proc, ir_array_elem(proc, addr), low);
irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int);
irValue *cap = ir_emit_arith(proc, Token_Sub, max, low, t_int);
irValue *slice = ir_add_local_generated(proc, slice_type);
ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 0), elem);
ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 1), len);
ir_fill_slice(proc, slice, elem, len, cap);
return ir_make_addr(slice);
}
case Type_Basic: {
GB_ASSERT(type == t_string);
if (high == NULL) {
high = ir_string_len(proc, base);
}
if (high == NULL) high = ir_string_len(proc, base);
if (max == NULL) max = ir_string_len(proc, base);
ir_emit_slice_bounds_check(proc, se->open, low, high, true);
ir_emit_slice_bounds_check(proc, se->open, low, high, max, true);
irValue *elem, *len;
len = ir_emit_arith(proc, Token_Sub, high, low, t_int);
elem = ir_string_elem(proc, base);
elem = ir_emit_ptr_offset(proc, elem, low);
irValue *elem = ir_emit_ptr_offset(proc, ir_string_elem(proc, base), low);
irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int);
irValue *str = ir_add_local_generated(proc, t_string);
irValue *gep0 = ir_emit_struct_ep(proc, str, 0);
irValue *gep1 = ir_emit_struct_ep(proc, str, 1);
ir_emit_store(proc, gep0, elem);
ir_emit_store(proc, gep1, len);
ir_emit_store(proc, ir_emit_struct_ep(proc, str, 0), elem);
ir_emit_store(proc, ir_emit_struct_ep(proc, str, 1), len);
return ir_make_addr(str);
} break;
@@ -4357,13 +4397,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
ir_emit_store(proc, offset, ev);
}
irValue *gep0 = ir_emit_struct_ep(proc, v, 0);
irValue *gep1 = ir_emit_struct_ep(proc, v, 1);
irValue *gep2 = ir_emit_struct_ep(proc, v, 1);
ir_emit_store(proc, gep0, data);
ir_emit_store(proc, gep1, ir_make_const_int(proc->module->allocator, slice->ConstantSlice.count));
ir_emit_store(proc, gep2, ir_make_const_int(proc->module->allocator, slice->ConstantSlice.count));
irValue *count = ir_make_const_int(proc->module->allocator, slice->ConstantSlice.count);
ir_fill_slice(proc, v, data, count, count);
}
} break;
@@ -4730,8 +4765,7 @@ void ir_build_range_interval(irProcedure *proc, AstNodeIntervalExpr *node, Type
TokenKind op = Token_Lt;
switch (node->op.kind) {
case Token_HalfOpenRange: op = Token_Lt; break;
case Token_Ellipsis: op = Token_LtEq; break;
case Token_Ellipsis: op = Token_Lt; break;
default: GB_PANIC("Invalid interval operator"); break;
}
irValue *cond = ir_emit_comp(proc, op, ir_emit_load(proc, value), upper);
@@ -4769,6 +4803,15 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
ir_build_when_stmt(proc, ws);
case_end;
case_ast_node(s, IncDecStmt, node);
TokenKind op = Token_Add;
if (s->op.kind == Token_Dec) {
op = Token_Sub;
}
irAddr addr = ir_build_addr(proc, s->expr);
ir_build_assign_op(proc, addr, v_one, op);
case_end;
case_ast_node(vd, ValueDecl, node);
if (vd->is_var) {
irModule *m = proc->module;
@@ -6010,16 +6053,6 @@ void ir_add_foreign_library_path(irModule *m, Entity *e) {
array_add(&m->foreign_library_paths, library_path);
}
void ir_fill_slice(irProcedure *proc, irValue *slice_ptr, irValue *data, irValue *count) {
Type *t = ir_type(slice_ptr);
GB_ASSERT(is_type_pointer(t));
t = type_deref(t);
GB_ASSERT(is_type_slice(t));
irValue *elem = ir_emit_struct_ep(proc, slice_ptr, 0);
irValue *len = ir_emit_struct_ep(proc, slice_ptr, 1);
ir_emit_store(proc, elem, data);
ir_emit_store(proc, len, count);
}
void ir_gen_tree(irGen *s) {
irModule *m = &s->module;
@@ -6356,9 +6389,10 @@ void ir_gen_tree(irGen *s) {
irValue *global_type_table = ir_find_global_variable(proc, str_lit("__type_table"));
Type *type = base_type(type_deref(ir_type(ir_global_type_info_data)));
GB_ASSERT(is_type_array(type));
irValue *len = ir_make_const_int(proc->module->allocator, type->Array.count);
ir_fill_slice(proc, global_type_table,
ir_emit_array_epi(proc, ir_global_type_info_data, 0),
ir_make_const_int(proc->module->allocator, type->Array.count));
len, len);
}
@@ -6504,10 +6538,10 @@ void ir_gen_tree(irGen *s) {
irValue *variadic = ir_emit_struct_ep(proc, tag, 2);
irValue *convention = ir_emit_struct_ep(proc, tag, 3);
if (t->Proc.params) {
if (t->Proc.params != NULL) {
ir_emit_store(proc, params, ir_get_type_info_ptr(proc, t->Proc.params));
}
if (t->Proc.results) {
if (t->Proc.results != NULL) {
ir_emit_store(proc, results, ir_get_type_info_ptr(proc, t->Proc.results));
}
ir_emit_store(proc, variadic, ir_make_const_bool(a, t->Proc.variadic));
@@ -6525,8 +6559,8 @@ void ir_gen_tree(irGen *s) {
ir_emit_store(proc, ir_emit_struct_ep(proc, record, 4), align);
}
irValue *memory_types = ir_type_info_member_types_offset(proc, t->Record.field_count);
irValue *memory_names = ir_type_info_member_names_offset(proc, t->Record.field_count);
irValue *memory_types = ir_type_info_member_types_offset(proc, t->Tuple.variable_count);
irValue *memory_names = ir_type_info_member_names_offset(proc, t->Tuple.variable_count);
for (isize i = 0; i < t->Tuple.variable_count; i++) {
// NOTE(bill): offset is not used for tuples
@@ -6542,8 +6576,9 @@ void ir_gen_tree(irGen *s) {
}
}
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 0), memory_types, ir_make_const_int(a, t->Record.field_count));
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 1), memory_names, ir_make_const_int(a, t->Record.field_count));
irValue *count = ir_make_const_int(a, t->Tuple.variable_count);
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 0), memory_types, count, count);
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 1), memory_names, count, count);
} break;
case Type_Record: {
switch (t->Record.kind) {
@@ -6589,9 +6624,10 @@ void ir_gen_tree(irGen *s) {
ir_emit_store(proc, offset, ir_make_const_int(a, foffset));
}
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 0), memory_types, ir_make_const_int(a, t->Record.field_count));
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 1), memory_names, ir_make_const_int(a, t->Record.field_count));
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 2), memory_offsets, ir_make_const_int(a, t->Record.field_count));
irValue *count = ir_make_const_int(a, t->Record.field_count);
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 0), memory_types, count, count);
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 1), memory_names, count, count);
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 2), memory_offsets, count, count);
} break;
case TypeRecord_Union: {
ir_emit_comment(proc, str_lit("Type_Info_Union"));
@@ -6632,9 +6668,10 @@ void ir_gen_tree(irGen *s) {
}
ir_fill_slice(proc, ir_emit_struct_ep(proc, common_fields, 0), memory_types, ir_make_const_int(a, field_count));
ir_fill_slice(proc, ir_emit_struct_ep(proc, common_fields, 1), memory_names, ir_make_const_int(a, field_count));
ir_fill_slice(proc, ir_emit_struct_ep(proc, common_fields, 2), memory_offsets, ir_make_const_int(a, field_count));
irValue *count = ir_make_const_int(a, field_count);
ir_fill_slice(proc, ir_emit_struct_ep(proc, common_fields, 0), memory_types, count, count);
ir_fill_slice(proc, ir_emit_struct_ep(proc, common_fields, 1), memory_names, count, count);
ir_fill_slice(proc, ir_emit_struct_ep(proc, common_fields, 2), memory_offsets, count, count);
}
{
@@ -6661,9 +6698,8 @@ void ir_gen_tree(irGen *s) {
}
irValue *count = ir_make_const_int(a, variant_count);
ir_fill_slice(proc, variant_names, memory_names, count);
ir_fill_slice(proc, variant_types, memory_types, count);
ir_fill_slice(proc, variant_names, memory_names, count, count);
ir_fill_slice(proc, variant_types, memory_types, count, count);
}
} break;
@@ -6696,9 +6732,10 @@ void ir_gen_tree(irGen *s) {
}
}
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 0), memory_types, ir_make_const_int(a, t->Record.field_count));
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 1), memory_names, ir_make_const_int(a, t->Record.field_count));
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 2), memory_offsets, ir_make_const_int(a, t->Record.field_count));
irValue *count = ir_make_const_int(a, t->Record.field_count);
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 0), memory_types, count, count);
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 1), memory_names, count, count);
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 2), memory_offsets, count, count);
} break;
case TypeRecord_Enum:
ir_emit_comment(proc, str_lit("Type_Info_Enum"));
+13 -7
View File
@@ -191,7 +191,7 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
case Type_Slice:
ir_fprintf(f, "{");
ir_print_type(f, m, t->Slice.elem);
ir_fprintf(f, "*, i%lld}", word_bits);
ir_fprintf(f, "*, i%lld, i%lld}", word_bits, word_bits);
return;
case Type_DynamicArray:
ir_fprintf(f, "{");
@@ -664,6 +664,11 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
ir_fprintf(f, "\t");
switch (instr->kind) {
default: {
GB_PANIC("<unknown instr> %d\n", instr->kind);
ir_fprintf(f, "; <unknown instr> %d\n", instr->kind);
} break;
case irInstr_StartupRuntime: {
ir_fprintf(f, "call void ");
ir_print_encoded_global(f, str_lit(IR_STARTUP_RUNTIME_PROC_NAME), false);
@@ -1249,6 +1254,13 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
ir_fprintf(f, " ");
ir_print_value(f, m, bc->high, t_int);
if (!bc->is_substring) {
ir_fprintf(f, ", ");
ir_print_type(f, m, t_int);
ir_fprintf(f, " ");
ir_print_value(f, m, bc->max, t_int);
}
ir_fprintf(f, ")\n");
} break;
@@ -1274,12 +1286,6 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
ir_fprintf(f, "\n"); */
} break;
default: {
GB_PANIC("<unknown instr> %d\n", instr->kind);
ir_fprintf(f, "; <unknown instr> %d\n", instr->kind);
} break;
}
}
+54 -19
View File
@@ -151,8 +151,9 @@ AST_NODE_KIND(_ExprBegin, "", i32) \
AST_NODE_KIND(DerefExpr, "dereference expression", struct { Token op; AstNode *expr; }) \
AST_NODE_KIND(SliceExpr, "slice expression", struct { \
AstNode *expr; \
Token open, close, interval; \
AstNode *low, *high; \
Token open, close; \
bool index3; \
AstNode *low, *high, *max; \
}) \
AST_NODE_KIND(CallExpr, "call expression", struct { \
AstNode * proc; \
@@ -186,6 +187,10 @@ AST_NODE_KIND(_StmtBegin, "", i32) \
Token op; \
AstNodeArray lhs, rhs; \
}) \
AST_NODE_KIND(IncDecStmt, "increment decrement statement", struct { \
Token op; \
AstNode *expr; \
}) \
AST_NODE_KIND(_ComplexStmtBegin, "", i32) \
AST_NODE_KIND(BlockStmt, "block statement", struct { \
AstNodeArray stmts; \
@@ -467,6 +472,7 @@ Token ast_node_token(AstNode *node) {
case AstNode_ExprStmt: return ast_node_token(node->ExprStmt.expr);
case AstNode_TagStmt: return node->TagStmt.token;
case AstNode_AssignStmt: return node->AssignStmt.op;
case AstNode_IncDecStmt: return ast_node_token(node->IncDecStmt.expr);
case AstNode_BlockStmt: return node->BlockStmt.open;
case AstNode_IfStmt: return node->IfStmt.token;
case AstNode_WhenStmt: return node->WhenStmt.token;
@@ -662,14 +668,15 @@ AstNode *ast_index_expr(AstFile *f, AstNode *expr, AstNode *index, Token open, T
}
AstNode *ast_slice_expr(AstFile *f, AstNode *expr, Token open, Token close, Token interval, AstNode *low, AstNode *high) {
AstNode *ast_slice_expr(AstFile *f, AstNode *expr, Token open, Token close, bool index3, AstNode *low, AstNode *high, AstNode *max) {
AstNode *result = make_ast_node(f, AstNode_SliceExpr);
result->SliceExpr.expr = expr;
result->SliceExpr.open = open;
result->SliceExpr.close = close;
result->SliceExpr.interval = interval;
result->SliceExpr.index3 = index3;
result->SliceExpr.low = low;
result->SliceExpr.high = high;
result->SliceExpr.max = max;
return result;
}
@@ -802,6 +809,16 @@ AstNode *ast_assign_stmt(AstFile *f, Token op, AstNodeArray lhs, AstNodeArray rh
return result;
}
AstNode *ast_inc_dec_stmt(AstFile *f, Token op, AstNode *expr) {
AstNode *result = make_ast_node(f, AstNode_IncDecStmt);
result->IncDecStmt.op = op;
result->IncDecStmt.expr = expr;
return result;
}
AstNode *ast_block_stmt(AstFile *f, AstNodeArray stmts, Token open, Token close) {
AstNode *result = make_ast_node(f, AstNode_BlockStmt);
result->BlockStmt.stmts = stmts;
@@ -1930,37 +1947,49 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
// TODO(bill): Handle this
}
Token open = {0}, close = {0}, interval = {0};
AstNode *indices[2] = {0};
AstNode *indices[3] = {0};
isize ellipsis_count = 0;
Token ellipses[2] = {0};
f->expr_level++;
open = expect_token(f, Token_OpenBracket);
// if (f->curr_token.kind != Token_Ellipsis &&
// f->curr_token.kind != Token_HalfOpenRange) {
if (f->curr_token.kind != Token_Colon) {
if (f->curr_token.kind != Token_Ellipsis) {
indices[0] = parse_expr(f, false);
}
bool is_index = true;
// if (f->curr_token.kind == Token_Ellipsis ||
// f->curr_token.kind == Token_HalfOpenRange) {
if (f->curr_token.kind == Token_Colon) {
is_index = false;
interval = f->curr_token;
while (f->curr_token.kind == Token_Ellipsis && ellipsis_count < gb_count_of(ellipses)) {
ellipses[ellipsis_count++] = f->curr_token;
next_token(f);
if (f->curr_token.kind != Token_CloseBracket &&
if (f->curr_token.kind != Token_Ellipsis &&
f->curr_token.kind != Token_CloseBracket &&
f->curr_token.kind != Token_EOF) {
indices[1] = parse_expr(f, false);
indices[ellipsis_count] = parse_expr(f, false);
}
}
f->expr_level--;
close = expect_token(f, Token_CloseBracket);
if (is_index) {
operand = ast_index_expr(f, operand, indices[0], open, close);
if (ellipsis_count > 0) {
bool index3 = false;
if (ellipsis_count == 2) {
index3 = true;
// 2nd and 3rd index must be present
if (indices[1] == NULL) {
error(ellipses[0], "2nd index required in 3-index slice expression");
indices[1] = ast_bad_expr(f, ellipses[0], ellipses[1]);
}
if (indices[2] == NULL) {
error(ellipses[1], "3rd index required in 3-index slice expression");
indices[2] = ast_bad_expr(f, ellipses[1], close);
}
}
operand = ast_slice_expr(f, operand, open, close, index3, indices[0], indices[1], indices[2]);
} else {
operand = ast_slice_expr(f, operand, open, close, interval, indices[0], indices[1]);
operand = ast_index_expr(f, operand, indices[0], open, close);
}
} break;
@@ -2246,7 +2275,6 @@ AstNode *parse_simple_stmt(AstFile *f, bool in_stmt_ok) {
allow_token(f, Token_in);
AstNode *expr = parse_expr(f, false);
switch (f->curr_token.kind) {
case Token_HalfOpenRange:
case Token_Ellipsis: {
Token op = f->curr_token;
next_token(f);
@@ -2272,6 +2300,13 @@ AstNode *parse_simple_stmt(AstFile *f, bool in_stmt_ok) {
return ast_bad_stmt(f, token, f->curr_token);
}
switch (token.kind) {
case Token_Inc:
case Token_Dec:
next_token(f);
return ast_inc_dec_stmt(f, token, lhs.e[0]);
}
return ast_expr_stmt(f, lhs.e[0]);
}
+40 -18
View File
@@ -51,8 +51,8 @@ TOKEN_KIND(Token__AssignOpBegin, "_AssignOpBegin"), \
TOKEN_KIND(Token__AssignOpEnd, "_AssignOpEnd"), \
TOKEN_KIND(Token_ArrowRight, "->"), \
TOKEN_KIND(Token_ArrowLeft, "<-"), \
TOKEN_KIND(Token_Increment, "++"), \
TOKEN_KIND(Token_Decrement, "--"), \
TOKEN_KIND(Token_Inc, "++"), \
TOKEN_KIND(Token_Dec, "--"), \
\
TOKEN_KIND(Token__ComparisonBegin, "_ComparisonBegin"), \
TOKEN_KIND(Token_CmpEq, "=="), \
@@ -73,8 +73,8 @@ TOKEN_KIND(Token__ComparisonEnd, "_ComparisonEnd"), \
TOKEN_KIND(Token_Semicolon, ";"), \
TOKEN_KIND(Token_Period, "."), \
TOKEN_KIND(Token_Comma, ","), \
TOKEN_KIND(Token_Ellipsis, "..."), \
TOKEN_KIND(Token_HalfOpenRange, "..<"), \
TOKEN_KIND(Token_Ellipsis, ".."), \
/* TOKEN_KIND(Token_HalfOpenRange, "..<"), */ \
TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \
\
TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
@@ -225,6 +225,23 @@ void syntax_error_va(Token token, char *fmt, va_list va) {
gb_mutex_unlock(&global_error_collector.mutex);
}
void syntax_warning_va(Token token, char *fmt, va_list va) {
gb_mutex_lock(&global_error_collector.mutex);
global_error_collector.warning_count++;
// NOTE(bill): Duplicate error, skip it
if (!token_pos_eq(global_error_collector.prev, token.pos)) {
global_error_collector.prev = token.pos;
gb_printf_err("%.*s(%td:%td) Syntax Warning: %s\n",
LIT(token.pos.file), token.pos.line, token.pos.column,
gb_bprintf_va(fmt, va));
} else if (token.pos.line == 0) {
gb_printf_err("Warning: %s\n", gb_bprintf_va(fmt, va));
}
gb_mutex_unlock(&global_error_collector.mutex);
}
void warning(Token token, char *fmt, ...) {
va_list va;
@@ -247,6 +264,13 @@ void syntax_error(Token token, char *fmt, ...) {
va_end(va);
}
void syntax_warning(Token token, char *fmt, ...) {
va_list va;
va_start(va, fmt);
syntax_warning_va(token, fmt, va);
va_end(va);
}
void compiler_error(char *fmt, ...) {
va_list va;
@@ -834,13 +858,11 @@ Token tokenizer_get_token(Tokenizer *t) {
token.kind = Token_Period; // Default
if (t->curr_rune == '.') { // Could be an ellipsis
advance_to_next_rune(t);
if (t->curr_rune == '<') {
advance_to_next_rune(t);
token.kind = Token_HalfOpenRange;
} else if (t->curr_rune == '.') {
advance_to_next_rune(t);
token.kind = Token_Ellipsis;
}
token.kind = Token_Ellipsis;
// if (t->curr_rune == '<') {
// advance_to_next_rune(t);
// token.kind = Token_HalfOpenRange;
// }
}
break;
@@ -859,13 +881,13 @@ Token tokenizer_get_token(Tokenizer *t) {
case '{': token.kind = Token_OpenBrace; break;
case '}': token.kind = Token_CloseBrace; break;
case '*': token.kind = token_kind_variant2(t, Token_Mul, Token_MulEq); break;
case '%': token.kind = token_kind_variant2(t, Token_Mod, Token_ModEq); break;
case '=': token.kind = token_kind_variant2(t, Token_Eq, Token_CmpEq); break;
case '~': token.kind = token_kind_variant2(t, Token_Xor, Token_XorEq); break;
case '!': token.kind = token_kind_variant2(t, Token_Not, Token_NotEq); break;
case '+': token.kind = token_kind_variant3(t, Token_Add, Token_AddEq, '+', Token_Increment); break;
case '-': token.kind = token_kind_variant4(t, Token_Sub, Token_SubEq, '-', Token_Decrement, '>', Token_ArrowRight); break;
case '*': token.kind = token_kind_variant2(t, Token_Mul, Token_MulEq); break;
case '%': token.kind = token_kind_variant2(t, Token_Mod, Token_ModEq); break;
case '=': token.kind = token_kind_variant2(t, Token_Eq, Token_CmpEq); break;
case '~': token.kind = token_kind_variant2(t, Token_Xor, Token_XorEq); break;
case '!': token.kind = token_kind_variant2(t, Token_Not, Token_NotEq); break;
case '+': token.kind = token_kind_variant3(t, Token_Add, Token_AddEq, '+', Token_Inc); break;
case '-': token.kind = token_kind_variant4(t, Token_Sub, Token_SubEq, '-', Token_Dec, '>', Token_ArrowRight); break;
case '/': {
if (t->curr_rune == '/') {
while (t->curr_rune != '\n' && t->curr_rune != GB_RUNE_EOF) {
+25 -15
View File
@@ -1090,6 +1090,7 @@ gb_global Entity *entity__any_data = NULL;
gb_global Entity *entity__string_data = NULL;
gb_global Entity *entity__string_count = NULL;
gb_global Entity *entity__slice_count = NULL;
gb_global Entity *entity__slice_capacity = NULL;
gb_global Entity *entity__dynamic_array_count = NULL;
gb_global Entity *entity__dynamic_array_capacity = NULL;
@@ -1251,6 +1252,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
} else if (type->kind == Type_Slice) {
String data_str = str_lit("data");
String count_str = str_lit("count");
String capacity_str = str_lit("capacity");
if (str_eq(field_name, data_str)) {
selection_add_index(&sel, 0);
@@ -1265,7 +1267,16 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
sel.entity = entity__slice_count;
return sel;
} else if (str_eq(field_name, capacity_str)) {
selection_add_index(&sel, 2);
if (entity__slice_capacity == NULL) {
entity__slice_capacity = make_entity_field(a, NULL, make_token_ident(capacity_str), t_int, false, 2);
}
sel.entity = entity__slice_capacity;
return sel;
}
} else if (type->kind == Type_DynamicArray) {
String data_str = str_lit("data");
String count_str = str_lit("count");
@@ -1331,9 +1342,6 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
}
}
if (type->kind != Type_Record) {
return sel;
}
if (is_type) {
if (type->kind == Type_Record) {
if (type->Record.names != NULL &&
@@ -1384,7 +1392,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
}
}
}
} else {
} else if (type->kind == Type_Record) {
for (isize i = 0; i < type->Record.field_count; i++) {
Entity *f = type->Record.fields[i];
if (f->kind != Entity_Variable || (f->flags & EntityFlag_Field) == 0) {
@@ -1779,7 +1787,7 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
case Type_Slice: // ptr + count
return 2 * build_context.word_size;
return 3 * build_context.word_size;
case Type_Map: {
if (t->Map.count == 0) { // Dynamic
@@ -1875,23 +1883,24 @@ i64 type_offset_of(gbAllocator allocator, Type *t, i32 index) {
} else if (t->kind == Type_Basic) {
if (t->Basic.kind == Basic_string) {
switch (index) {
case 0: return 0; // data
case 0: return 0; // data
case 1: return build_context.word_size; // count
}
} else if (t->Basic.kind == Basic_any) {
switch (index) {
case 0: return 0; // type_info
case 0: return 0; // type_info
case 1: return build_context.word_size; // data
}
}
} else if (t->kind == Type_Slice) {
switch (index) {
case 0: return 0; // data
case 0: return 0; // data
case 1: return 1*build_context.word_size; // count
case 2: return 2*build_context.word_size; // capacity
}
} else if (t->kind == Type_DynamicArray) {
switch (index) {
case 0: return 0; // data
case 0: return 0; // data
case 1: return 1*build_context.word_size; // count
case 2: return 2*build_context.word_size; // capacity
case 3: return 3*build_context.word_size; // allocator
@@ -1928,6 +1937,13 @@ i64 type_offset_of_from_selection(gbAllocator allocator, Type *type, Selection s
}
}
break;
case Type_Slice:
switch (index) {
case 0: t = t_rawptr; break;
case 1: t = t_int; break;
case 2: t = t_int; break;
}
break;
case Type_DynamicArray:
switch (index) {
case 0: t = t_rawptr; break;
@@ -1936,12 +1952,6 @@ i64 type_offset_of_from_selection(gbAllocator allocator, Type *type, Selection s
case 3: t = t_allocator; break;
}
break;
case Type_Slice:
switch (index) {
case 0: t = t_rawptr; break;
case 1: t = t_int; break;
}
break;
}
}
}
+1
View File
@@ -6,6 +6,7 @@
#pragma warning(pop)
bool rune_is_letter(Rune r) {
if ((r < 0x80 && gb_char_is_alpha(cast(char)r)) ||
r == '_') {
+66 -44
View File
@@ -166,24 +166,24 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_encode_char(utf8proc_int32_t uc, ut
if (uc < 0x00) {
return 0;
} else if (uc < 0x80) {
dst[0] = uc;
dst[0] = (utf8proc_uint8_t) uc;
return 1;
} else if (uc < 0x800) {
dst[0] = 0xC0 + (uc >> 6);
dst[1] = 0x80 + (uc & 0x3F);
dst[0] = (utf8proc_uint8_t)(0xC0 + (uc >> 6));
dst[1] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F));
return 2;
// Note: we allow encoding 0xd800-0xdfff here, so as not to change
// the API, however, these are actually invalid in UTF-8
} else if (uc < 0x10000) {
dst[0] = 0xE0 + (uc >> 12);
dst[1] = 0x80 + ((uc >> 6) & 0x3F);
dst[2] = 0x80 + (uc & 0x3F);
dst[0] = (utf8proc_uint8_t)(0xE0 + (uc >> 12));
dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F));
dst[2] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F));
return 3;
} else if (uc < 0x110000) {
dst[0] = 0xF0 + (uc >> 18);
dst[1] = 0x80 + ((uc >> 12) & 0x3F);
dst[2] = 0x80 + ((uc >> 6) & 0x3F);
dst[3] = 0x80 + (uc & 0x3F);
dst[0] = (utf8proc_uint8_t)(0xF0 + (uc >> 18));
dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 12) & 0x3F));
dst[2] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F));
dst[3] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F));
return 4;
} else return 0;
}
@@ -193,28 +193,28 @@ static utf8proc_ssize_t unsafe_encode_char(utf8proc_int32_t uc, utf8proc_uint8_t
if (uc < 0x00) {
return 0;
} else if (uc < 0x80) {
dst[0] = uc;
dst[0] = (utf8proc_uint8_t)uc;
return 1;
} else if (uc < 0x800) {
dst[0] = 0xC0 + (uc >> 6);
dst[1] = 0x80 + (uc & 0x3F);
dst[0] = (utf8proc_uint8_t)(0xC0 + (uc >> 6));
dst[1] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F));
return 2;
} else if (uc == 0xFFFF) {
dst[0] = 0xFF;
dst[0] = (utf8proc_uint8_t)0xFF;
return 1;
} else if (uc == 0xFFFE) {
dst[0] = 0xFE;
dst[0] = (utf8proc_uint8_t)0xFE;
return 1;
} else if (uc < 0x10000) {
dst[0] = 0xE0 + (uc >> 12);
dst[1] = 0x80 + ((uc >> 6) & 0x3F);
dst[2] = 0x80 + (uc & 0x3F);
dst[0] = (utf8proc_uint8_t)(0xE0 + (uc >> 12));
dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F));
dst[2] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F));
return 3;
} else if (uc < 0x110000) {
dst[0] = 0xF0 + (uc >> 18);
dst[1] = 0x80 + ((uc >> 12) & 0x3F);
dst[2] = 0x80 + ((uc >> 6) & 0x3F);
dst[3] = 0x80 + (uc & 0x3F);
dst[0] = (utf8proc_uint8_t)(0xF0 + (uc >> 18));
dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 12) & 0x3F));
dst[2] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F));
dst[3] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F));
return 4;
} else return 0;
}
@@ -383,7 +383,7 @@ UTF8PROC_DLLEXPORT int utf8proc_charwidth(utf8proc_int32_t c) {
}
UTF8PROC_DLLEXPORT utf8proc_category_t utf8proc_category(utf8proc_int32_t c) {
return (utf8proc_category_t)utf8proc_get_property(c)->category;
return utf8proc_get_property(c)->category;
}
UTF8PROC_DLLEXPORT const char *utf8proc_category_string(utf8proc_int32_t c) {
@@ -391,11 +391,9 @@ UTF8PROC_DLLEXPORT const char *utf8proc_category_string(utf8proc_int32_t c) {
return s[utf8proc_category(c)];
}
#define utf8proc_decompose_lump(replacement_uc) \
return utf8proc_decompose_char((utf8proc_int32_t)(replacement_uc), dst, bufsize, \
(utf8proc_option_t)((utf8proc_int32_t)options & ~UTF8PROC_LUMP), last_boundclass)
return utf8proc_decompose_char((replacement_uc), dst, bufsize, \
options & ~UTF8PROC_LUMP, last_boundclass)
UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_char(utf8proc_int32_t uc, utf8proc_int32_t *dst, utf8proc_ssize_t bufsize, utf8proc_option_t options, int *last_boundclass) {
const utf8proc_property_t *property;
@@ -458,12 +456,12 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_char(utf8proc_int32_t uc,
category == UTF8PROC_CATEGORY_ME) return 0;
}
if (options & UTF8PROC_CASEFOLD) {
if ((utf8proc_int16_t)property->casefold_seqindex != UINT16_MAX) {
if (property->casefold_seqindex != UINT16_MAX) {
return seqindex_write_char_decomposed(property->casefold_seqindex, dst, bufsize, options, last_boundclass);
}
}
if (options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) {
if ((utf8proc_int16_t)property->decomp_seqindex != UINT16_MAX &&
if (property->decomp_seqindex != UINT16_MAX &&
(!property->decomp_type || (options & UTF8PROC_COMPAT))) {
return seqindex_write_char_decomposed(property->decomp_seqindex, dst, bufsize, options, last_boundclass);
}
@@ -485,6 +483,14 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_char(utf8proc_int32_t uc,
UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose(
const utf8proc_uint8_t *str, utf8proc_ssize_t strlen,
utf8proc_int32_t *buffer, utf8proc_ssize_t bufsize, utf8proc_option_t options
) {
return utf8proc_decompose_custom(str, strlen, buffer, bufsize, options, NULL, NULL);
}
UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_custom(
const utf8proc_uint8_t *str, utf8proc_ssize_t strlen,
utf8proc_int32_t *buffer, utf8proc_ssize_t bufsize, utf8proc_option_t options,
utf8proc_custom_func custom_func, void *custom_data
) {
/* strlen will be ignored, if UTF8PROC_NULLTERM is set in options */
utf8proc_ssize_t wpos = 0;
@@ -511,6 +517,9 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose(
rpos += utf8proc_iterate(str + rpos, strlen - rpos, &uc);
if (uc < 0) return UTF8PROC_ERROR_INVALIDUTF8;
}
if (custom_func != NULL) {
uc = custom_func(uc, custom_data); /* user-specified custom mapping */
}
decomp_result = utf8proc_decompose_char(
uc, buffer + wpos, (bufsize > wpos) ? (bufsize - wpos) : 0, options,
&boundclass
@@ -545,9 +554,8 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose(
return wpos;
}
UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_reencode(utf8proc_int32_t *buffer, utf8proc_ssize_t length, utf8proc_option_t options) {
/* UTF8PROC_NULLTERM option will be ignored, 'length' is never ignored
ASSERT: 'buffer' has one spare byte of free space at the end! */
UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_normalize_utf32(utf8proc_int32_t *buffer, utf8proc_ssize_t length, utf8proc_option_t options) {
/* UTF8PROC_NULLTERM option will be ignored, 'length' is never ignored */
if (options & (UTF8PROC_NLF2LS | UTF8PROC_NLF2PS | UTF8PROC_STRIPCC)) {
utf8proc_ssize_t rpos;
utf8proc_ssize_t wpos = 0;
@@ -621,7 +629,7 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_reencode(utf8proc_int32_t *buffer,
starter_property = unsafe_get_property(*starter);
}
if (starter_property->comb_index < 0x8000 &&
(utf8proc_int16_t)current_property->comb_index != UINT16_MAX &&
current_property->comb_index != UINT16_MAX &&
current_property->comb_index >= 0x8000) {
int sidx = starter_property->comb_index;
int idx = (current_property->comb_index & 0x3FFF) - utf8proc_combinations[sidx];
@@ -655,6 +663,14 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_reencode(utf8proc_int32_t *buffer,
}
length = wpos;
}
return length;
}
UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_reencode(utf8proc_int32_t *buffer, utf8proc_ssize_t length, utf8proc_option_t options) {
/* UTF8PROC_NULLTERM option will be ignored, 'length' is never ignored
ASSERT: 'buffer' has one spare byte of free space at the end! */
length = utf8proc_normalize_utf32(buffer, length, options);
if (length < 0) return length;
{
utf8proc_ssize_t rpos, wpos = 0;
utf8proc_int32_t uc;
@@ -676,15 +692,22 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_reencode(utf8proc_int32_t *buffer,
UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map(
const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_uint8_t **dstptr, utf8proc_option_t options
) {
return utf8proc_map_custom(str, strlen, dstptr, options, NULL, NULL);
}
UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map_custom(
const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_uint8_t **dstptr, utf8proc_option_t options,
utf8proc_custom_func custom_func, void *custom_data
) {
utf8proc_int32_t *buffer;
utf8proc_ssize_t result;
*dstptr = NULL;
result = utf8proc_decompose(str, strlen, NULL, 0, options);
result = utf8proc_decompose_custom(str, strlen, NULL, 0, options, custom_func, custom_data);
if (result < 0) return result;
buffer = (utf8proc_int32_t *) malloc(result * sizeof(utf8proc_int32_t) + 1);
if (!buffer) return UTF8PROC_ERROR_NOMEM;
result = utf8proc_decompose(str, strlen, buffer, result, options);
result = utf8proc_decompose_custom(str, strlen, buffer, result, options, custom_func, custom_data);
if (result < 0) {
free(buffer);
return result;
@@ -705,29 +728,28 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map(
UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFD(const utf8proc_uint8_t *str) {
utf8proc_uint8_t *retval;
utf8proc_map(str, 0, &retval, (utf8proc_option_t)(UTF8PROC_NULLTERM | UTF8PROC_STABLE |
UTF8PROC_DECOMPOSE));
utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
UTF8PROC_DECOMPOSE);
return retval;
}
UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFC(const utf8proc_uint8_t *str) {
utf8proc_uint8_t *retval;
utf8proc_map(str, 0, &retval, (utf8proc_option_t)(UTF8PROC_NULLTERM | UTF8PROC_STABLE |
UTF8PROC_COMPOSE));
utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
UTF8PROC_COMPOSE);
return retval;
}
UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKD(const utf8proc_uint8_t *str) {
utf8proc_uint8_t *retval;
utf8proc_map(str, 0, &retval, (utf8proc_option_t)(UTF8PROC_NULLTERM | UTF8PROC_STABLE |
UTF8PROC_DECOMPOSE | UTF8PROC_COMPAT));
utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
UTF8PROC_DECOMPOSE | UTF8PROC_COMPAT);
return retval;
}
UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC(const utf8proc_uint8_t *str) {
utf8proc_uint8_t *retval;
utf8proc_map(str, 0, &retval, (utf8proc_option_t)(UTF8PROC_NULLTERM | UTF8PROC_STABLE |
UTF8PROC_COMPOSE | UTF8PROC_COMPAT));
utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
UTF8PROC_COMPOSE | UTF8PROC_COMPAT);
return retval;
}
+81 -25
View File
@@ -71,14 +71,15 @@
/** The MAJOR version number (increased when backwards API compatibility is broken). */
#define UTF8PROC_VERSION_MAJOR 2
/** The MINOR version number (increased when new functionality is added in a backwards-compatible manner). */
#define UTF8PROC_VERSION_MINOR 0
#define UTF8PROC_VERSION_MINOR 1
/** The PATCH version (increased for fixes that do not change the API). */
#define UTF8PROC_VERSION_PATCH 2
#define UTF8PROC_VERSION_PATCH 0
/** @} */
#include <stdlib.h>
#include <sys/types.h>
#ifdef _MSC_VER
#if defined(_MSC_VER) && _MSC_VER < 1800
// MSVC prior to 2013 lacked stdbool.h and inttypes.h
typedef signed char utf8proc_int8_t;
typedef unsigned char utf8proc_uint8_t;
typedef short utf8proc_int16_t;
@@ -93,12 +94,18 @@ typedef int utf8proc_ssize_t;
typedef unsigned int utf8proc_size_t;
# endif
# ifndef __cplusplus
// emulate C99 bool
typedef unsigned char utf8proc_bool;
// enum {false, true};
# ifndef __bool_true_false_are_defined
# define false 0
# define true 1
# define __bool_true_false_are_defined 1
# endif
# else
typedef bool utf8proc_bool;
# endif
#else
# include <stddef.h>
# include <stdbool.h>
# include <inttypes.h>
typedef int8_t utf8proc_int8_t;
@@ -108,22 +115,12 @@ typedef uint16_t utf8proc_uint16_t;
typedef int32_t utf8proc_int32_t;
typedef uint32_t utf8proc_uint32_t;
typedef size_t utf8proc_size_t;
typedef ssize_t utf8proc_ssize_t;
typedef ptrdiff_t utf8proc_ssize_t;
typedef bool utf8proc_bool;
#endif
#include <limits.h>
#ifdef _WIN32
# ifdef UTF8PROC_EXPORTS
# define UTF8PROC_DLLEXPORT __declspec(dllexport)
# else
# define UTF8PROC_DLLEXPORT /*__declspec(dllimport)*/
# endif
#elif __GNUC__ >= 4
# define UTF8PROC_DLLEXPORT __attribute__ ((visibility("default")))
#else
# define UTF8PROC_DLLEXPORT
#endif
#define UTF8PROC_DLLEXPORT
#ifdef __cplusplus
extern "C" {
@@ -134,7 +131,7 @@ extern "C" {
#endif
#ifndef UINT16_MAX
# define UINT16_MAX ~(utf8proc_uint16_t)0
# define UINT16_MAX 65535U
#endif
/**
@@ -373,6 +370,13 @@ typedef enum {
UTF8PROC_BOUNDCLASS_E_BASE_GAZ = 18, /**< E_BASE + GLUE_AFTER_ZJW */
} utf8proc_boundclass_t;
/**
* Function pointer type passed to @ref utf8proc_map_custom and
* @ref utf8proc_decompose_custom, which is used to specify a user-defined
* mapping of codepoints to be applied in conjunction with other mappings.
*/
typedef utf8proc_int32_t (*utf8proc_custom_func)(utf8proc_int32_t codepoint, void *data);
/**
* Array containing the byte lengths of a UTF-8 encoded codepoint based
* on the first byte.
@@ -480,6 +484,7 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_char(
* `buffer` (which must contain at least `bufsize` entries). In case of
* success, the number of codepoints written is returned; in case of an
* error, a negative error code is returned (@ref utf8proc_errmsg).
* See @ref utf8proc_decompose_custom to supply additional transformations.
*
* If the number of written codepoints would be bigger than `bufsize`, the
* required buffer size is returned, while the buffer will be overwritten with
@@ -491,8 +496,20 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose(
);
/**
* Reencodes the sequence of `length` codepoints pointed to by `buffer`
* UTF-8 data in-place (i.e., the result is also stored in `buffer`).
* The same as @ref utf8proc_decompose, but also takes a `custom_func` mapping function
* that is called on each codepoint in `str` before any other transformations
* (along with a `custom_data` pointer that is passed through to `custom_func`).
* The `custom_func` argument is ignored if it is `NULL`. See also @ref utf8proc_map_custom.
*/
UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_custom(
const utf8proc_uint8_t *str, utf8proc_ssize_t strlen,
utf8proc_int32_t *buffer, utf8proc_ssize_t bufsize, utf8proc_option_t options,
utf8proc_custom_func custom_func, void *custom_data
);
/**
* Normalizes the sequence of `length` codepoints pointed to by `buffer`
* in-place (i.e., the result is also stored in `buffer`).
*
* @param buffer the (native-endian UTF-32) unicode codepoints to re-encode.
* @param length the length (in codepoints) of the buffer.
@@ -507,9 +524,37 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose(
* the unicode versioning stability
*
* @return
* In case of success, the length (in bytes) of the resulting UTF-8 string is
* In case of success, the length (in codepoints) of the normalized UTF-32 string is
* returned; otherwise, a negative error code is returned (@ref utf8proc_errmsg).
*
* @warning The entries of the array pointed to by `str` have to be in the
* range `0x0000` to `0x10FFFF`. Otherwise, the program might crash!
*/
UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_normalize_utf32(utf8proc_int32_t *buffer, utf8proc_ssize_t length, utf8proc_option_t options);
/**
* Reencodes the sequence of `length` codepoints pointed to by `buffer`
* UTF-8 data in-place (i.e., the result is also stored in `buffer`).
* Can optionally normalize the UTF-32 sequence prior to UTF-8 conversion.
*
* @param buffer the (native-endian UTF-32) unicode codepoints to re-encode.
* @param length the length (in codepoints) of the buffer.
* @param options a bitwise or (`|`) of one or more of the following flags:
* - @ref UTF8PROC_NLF2LS - convert LF, CRLF, CR and NEL into LS
* - @ref UTF8PROC_NLF2PS - convert LF, CRLF, CR and NEL into PS
* - @ref UTF8PROC_NLF2LF - convert LF, CRLF, CR and NEL into LF
* - @ref UTF8PROC_STRIPCC - strip or convert all non-affected control characters
* - @ref UTF8PROC_COMPOSE - try to combine decomposed codepoints into composite
* codepoints
* - @ref UTF8PROC_STABLE - prohibit combining characters that would violate
* the unicode versioning stability
* - @ref UTF8PROC_CHARBOUND - insert 0xFF bytes before each grapheme cluster
*
* @return
* In case of success, the length (in bytes) of the resulting nul-terminated
* UTF-8 string is returned; otherwise, a negative error code is returned
* (@ref utf8proc_errmsg).
*
* @warning The amount of free space pointed to by `buffer` must
* exceed the amount of the input data by one byte, and the
* entries of the array pointed to by `str` have to be in the
@@ -595,7 +640,8 @@ UTF8PROC_DLLEXPORT const char *utf8proc_category_string(utf8proc_int32_t codepoi
* in any case the result will be NULL terminated (though it might
* contain NULL characters with the string if `str` contained NULL
* characters). Other flags in the `options` field are passed to the
* functions defined above, and regarded as described.
* functions defined above, and regarded as described. See also
* @ref utfproc_map_custom to supply a custom codepoint transformation.
*
* In case of success the length of the new string is returned,
* otherwise a negative error code is returned.
@@ -607,6 +653,17 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map(
const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_uint8_t **dstptr, utf8proc_option_t options
);
/**
* Like @ref utf8proc_map, but also takes a `custom_func` mapping function
* that is called on each codepoint in `str` before any other transformations
* (along with a `custom_data` pointer that is passed through to `custom_func`).
* The `custom_func` argument is ignored if it is `NULL`.
*/
UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map_custom(
const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_uint8_t **dstptr, utf8proc_option_t options,
utf8proc_custom_func custom_func, void *custom_data
);
/** @name Unicode normalization
*
* Returns a pointer to newly allocated memory of a NFD, NFC, NFKD or NFKC
@@ -619,9 +676,9 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map(
UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFD(const utf8proc_uint8_t *str);
/** NFC normalization (@ref UTF8PROC_COMPOSE). */
UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFC(const utf8proc_uint8_t *str);
/** NFD normalization (@ref UTF8PROC_DECOMPOSE and @ref UTF8PROC_COMPAT). */
/** NFKD normalization (@ref UTF8PROC_DECOMPOSE and @ref UTF8PROC_COMPAT). */
UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKD(const utf8proc_uint8_t *str);
/** NFD normalization (@ref UTF8PROC_COMPOSE and @ref UTF8PROC_COMPAT). */
/** NFKC normalization (@ref UTF8PROC_COMPOSE and @ref UTF8PROC_COMPAT). */
UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC(const utf8proc_uint8_t *str);
/** @} */
@@ -630,4 +687,3 @@ UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC(const utf8proc_uint8_t *str);
#endif
#endif
+10 -15
View File
@@ -1,7 +1,4 @@
#pragma warning(push)
#pragma warning(disable: 4838)
const utf8proc_uint16_t utf8proc_sequences[] = {
static const utf8proc_uint16_t utf8proc_sequences[] = {
97, 98, 99, 100, 101, 102, 103,
104, 105, 106, 107, 108, 109, 110, 111,
112, 113, 114, 115, 116, 117, 118, 119,
@@ -1179,7 +1176,7 @@ const utf8proc_uint16_t utf8proc_sequences[] = {
56603, 55354, 56604, 55354, 56605, 55354, 56606, 55354,
56607, 55354, 56608, 55354, 56609, };
const utf8proc_uint16_t utf8proc_stage1table[] = {
static const utf8proc_uint16_t utf8proc_stage1table[] = {
0, 256, 512, 768, 1024, 1280, 1536,
1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584,
3840, 4096, 4352, 4608, 4864, 5120, 5376, 5632,
@@ -1726,7 +1723,7 @@ const utf8proc_uint16_t utf8proc_stage1table[] = {
18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432,
38656, };
const utf8proc_uint16_t utf8proc_stage2table[] = {
static const utf8proc_uint16_t utf8proc_stage2table[] = {
1, 2, 2, 2, 2, 2, 2,
2, 2, 3, 4, 3, 5, 6, 2,
2, 2, 2, 2, 2, 2, 2, 2,
@@ -5899,7 +5896,7 @@ const utf8proc_uint16_t utf8proc_stage2table[] = {
540, 540, 540, 1180, 0, 0, 0, 0,
0, 1154, 1154, 1154, 1154, 1154, 1154, 1154,
1154, 1154, 1154, 0, 0, 0, 0, 1103,
1158, 0, 0, 0, 0, 0, 0, 0,
1103, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -6593,7 +6590,7 @@ const utf8proc_uint16_t utf8proc_stage2table[] = {
3984, 3984, 3984, 3984, 3984, 3984, 3984, 0,
0, };
const utf8proc_property_t utf8proc_properties[] = {
static const utf8proc_property_t utf8proc_properties[] = {
{0, 0, 0, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false,false,false,false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL},
{UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL},
@@ -7850,7 +7847,7 @@ const utf8proc_property_t utf8proc_properties[] = {
{UTF8PROC_CATEGORY_MN, 122, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND},
{UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 9523, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 9525, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NOBREAK, 1335, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NOBREAK, 1335, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_MN, 216, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND},
{UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER},
@@ -10478,7 +10475,7 @@ const utf8proc_property_t utf8proc_properties[] = {
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1470, UINT16_MAX, 1470, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1478, UINT16_MAX, 1478, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5132, UINT16_MAX, 5132, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1480, UINT16_MAX, 1480, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1480, UINT16_MAX, 1480, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5133, UINT16_MAX, 5133, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5134, UINT16_MAX, 5134, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1482, UINT16_MAX, 1482, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
@@ -12168,7 +12165,7 @@ const utf8proc_property_t utf8proc_properties[] = {
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6787, UINT16_MAX, 6787, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6789, UINT16_MAX, 6789, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6791, UINT16_MAX, 6791, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6793, UINT16_MAX, 6793, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6793, UINT16_MAX, 6793, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6795, UINT16_MAX, 6795, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6797, UINT16_MAX, 6797, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6799, UINT16_MAX, 6799, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
@@ -12204,7 +12201,7 @@ const utf8proc_property_t utf8proc_properties[] = {
{UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9104, UINT16_MAX, 9104, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9106, UINT16_MAX, 9106, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9108, UINT16_MAX, 9108, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9110, UINT16_MAX, 9110, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9110, UINT16_MAX, 9110, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9112, UINT16_MAX, 9112, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9114, UINT16_MAX, 9114, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9116, UINT16_MAX, 9116, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
@@ -13423,7 +13420,7 @@ const utf8proc_property_t utf8proc_properties[] = {
{UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7975, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER},
};
const utf8proc_uint16_t utf8proc_combinations[] = {
static const utf8proc_uint16_t utf8proc_combinations[] = {
0, 46, 192, 193, 194, 195, 196, 197, 0,
256, 258, 260, 550, 461, 0, 0, 512,
514, 0, 0, 0, 0, 0, 0, 0,
@@ -14386,5 +14383,3 @@ const utf8proc_uint16_t utf8proc_combinations[] = {
72, 75,
1, 53694, 1, 53696,
};
#pragma warning(pop)