Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into bugfix/eabi-no-pic
Browse files Browse the repository at this point in the history
  • Loading branch information
RX14 committed Nov 11, 2024
2 parents 69b2323 + caf57c2 commit b4b1452
Show file tree
Hide file tree
Showing 12 changed files with 67 additions and 25 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/mingw-w64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ jobs:
shell: msys2 {0}
run: |
mkdir bin
cc crystal.obj -o bin/crystal.exe \
cc crystal.obj -o bin/crystal.exe -municode \
$(pkg-config bdw-gc libpcre2-8 iconv zlib libffi --libs) \
$(llvm-config --libs --system-libs --ldflags) \
-lole32 -lWS2_32 -Wl,--stack,0x800000
Expand Down
2 changes: 2 additions & 0 deletions spec/std/socket/socket_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ describe Socket, tags: "network" do

expect_raises(IO::TimeoutError) { server.accept }
expect_raises(IO::TimeoutError) { server.accept? }
ensure
server.try &.close
end

it "sends messages" do
Expand Down
2 changes: 2 additions & 0 deletions spec/std/socket/udp_socket_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ describe UDPSocket, tags: "network" do
socket = UDPSocket.new(family)
socket.bind(address, 0)
socket.local_address.address.should eq address
ensure
socket.try &.close
end

it "sends and receives messages" do
Expand Down
15 changes: 13 additions & 2 deletions src/compiler/crystal/loader/mingw.cr
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ require "crystal/system/win32/library_archive"
# The core implementation is derived from the MSVC loader. Main deviations are:
#
# - `.parse` follows GNU `ld`'s style, rather than MSVC `link`'s;
# - `.parse` automatically inserts a C runtime library if `-mcrtdll` isn't
# supplied;
# - `#library_filename` follows the usual naming of the MinGW linker: `.dll.a`
# for DLL import libraries, `.a` for other libraries;
# - `.default_search_paths` relies solely on `.cc_each_library_path`.
Expand All @@ -28,6 +30,11 @@ class Crystal::Loader
file_paths = [] of String
extra_search_paths = [] of String

# note that `msvcrt` is a default runtime chosen at MinGW-w64 build time,
# `ucrt` is always UCRT (even in a MINGW64 environment), and
# `msvcrt-os` is always MSVCRT (even in a UCRT64 environment)
crt_dll = "msvcrt"

OptionParser.parse(args.dup) do |parser|
parser.on("-L DIRECTORY", "--library-path DIRECTORY", "Add DIRECTORY to library search path") do |directory|
extra_search_paths << directory
Expand All @@ -39,17 +46,21 @@ class Crystal::Loader
raise LoadError.new "static libraries are not supported by Crystal's runtime loader"
end
parser.unknown_args do |args, after_dash|
file_paths.concat args
file_paths.concat args.reject(&.starts_with?("-mcrtdll="))
end

parser.invalid_option do |arg|
unless arg.starts_with?("-Wl,")
if crt_dll_arg = arg.lchop?("-mcrtdll=")
# the GCC spec is `%{!mcrtdll=*:-lmsvcrt} %{mcrtdll=*:-l%*}`
crt_dll = crt_dll_arg
elsif !arg.starts_with?("-Wl,")
raise LoadError.new "Not a recognized linker flag: #{arg}"
end
end
end

search_paths = extra_search_paths + search_paths
libnames << crt_dll

begin
loader = new(search_paths)
Expand Down
12 changes: 5 additions & 7 deletions src/crystal/system/win32/wmain.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@ require "c/stringapiset"
require "c/winnls"
require "c/stdlib"

{% begin %}
# we have both `main` and `wmain`, so we must choose an unambiguous entry point
# we have both `main` and `wmain`, so we must choose an unambiguous entry point
{% if flag?(:msvc) %}
@[Link({{ flag?(:static) ? "libcmt" : "msvcrt" }})]
{% if flag?(:msvc) %}
@[Link(ldflags: "/ENTRY:wmainCRTStartup")]
{% elsif flag?(:gnu) && !flag?(:interpreted) %}
@[Link(ldflags: "-municode")]
{% end %}
@[Link(ldflags: "/ENTRY:wmainCRTStartup")]
{% elsif flag?(:gnu) && !flag?(:interpreted) %}
@[Link(ldflags: "-municode")]
{% end %}
lib LibCrystalMain
end
Expand Down
4 changes: 4 additions & 0 deletions src/dir/glob.cr
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ class Dir

# Returns an array of all files that match against any of *patterns*.
#
# ```
# Dir.glob "path/to/folder/*.txt" # Returns all files in the target folder that end in ".txt".
# Dir.glob "path/to/folder/**/*" # Returns all files in the target folder and its subfolders.
# ```
# The pattern syntax is similar to shell filename globbing, see `File.match?` for details.
#
# NOTE: Path separator in patterns needs to be always `/`. The returned file names use system-specific path separators.
Expand Down
2 changes: 1 addition & 1 deletion src/empty.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require "primitives"

{% if flag?(:win32) %}
{% if flag?(:msvc) %}
@[Link({{ flag?(:static) ? "libcmt" : "msvcrt" }})] # For `mainCRTStartup`
{% end %}
lib LibCrystalMain
Expand Down
39 changes: 33 additions & 6 deletions src/gc/none.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{% if flag?(:win32) %}
require "c/process"
require "c/heapapi"
{% end %}
require "crystal/tracing"

Expand All @@ -11,21 +12,42 @@ module GC
# :nodoc:
def self.malloc(size : LibC::SizeT) : Void*
Crystal.trace :gc, "malloc", size: size
# libc malloc is not guaranteed to return cleared memory, so we need to
# explicitly clear it. Ref: https://github.com/crystal-lang/crystal/issues/14678
LibC.malloc(size).tap(&.clear)

{% if flag?(:win32) %}
LibC.HeapAlloc(LibC.GetProcessHeap, LibC::HEAP_ZERO_MEMORY, size)
{% else %}
# libc malloc is not guaranteed to return cleared memory, so we need to
# explicitly clear it. Ref: https://github.com/crystal-lang/crystal/issues/14678
LibC.malloc(size).tap(&.clear)
{% end %}
end

# :nodoc:
def self.malloc_atomic(size : LibC::SizeT) : Void*
Crystal.trace :gc, "malloc", size: size, atomic: 1
LibC.malloc(size)

{% if flag?(:win32) %}
LibC.HeapAlloc(LibC.GetProcessHeap, 0, size)
{% else %}
LibC.malloc(size)
{% end %}
end

# :nodoc:
def self.realloc(pointer : Void*, size : LibC::SizeT) : Void*
Crystal.trace :gc, "realloc", size: size
LibC.realloc(pointer, size)

{% if flag?(:win32) %}
# realloc with a null pointer should behave like plain malloc, but Win32
# doesn't do that
if pointer
LibC.HeapReAlloc(LibC.GetProcessHeap, LibC::HEAP_ZERO_MEMORY, pointer, size)
else
LibC.HeapAlloc(LibC.GetProcessHeap, LibC::HEAP_ZERO_MEMORY, size)
end
{% else %}
LibC.realloc(pointer, size)
{% end %}
end

def self.collect
Expand All @@ -39,7 +61,12 @@ module GC

def self.free(pointer : Void*) : Nil
Crystal.trace :gc, "free"
LibC.free(pointer)

{% if flag?(:win32) %}
LibC.HeapFree(LibC.GetProcessHeap, 0, pointer)
{% else %}
LibC.free(pointer)
{% end %}
end

def self.is_heap_ptr(pointer : Void*) : Bool
Expand Down
4 changes: 2 additions & 2 deletions src/levenshtein.cr
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ module Levenshtein
# end
# best_match # => "ello"
# ```
def self.find(name, tolerance = nil, &)
def self.find(name, tolerance = nil, &) : String?
Finder.find(name, tolerance) do |sn|
yield sn
end
Expand All @@ -154,7 +154,7 @@ module Levenshtein
# Levenshtein.find("hello", ["hullo", "hel", "hall", "hell"], 2) # => "hullo"
# Levenshtein.find("hello", ["hurlo", "hel", "hall"], 1) # => nil
# ```
def self.find(name, all_names, tolerance = nil)
def self.find(name, all_names, tolerance = nil) : String?
Finder.find(name, all_names, tolerance)
end
end
2 changes: 1 addition & 1 deletion src/lib_c.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% if flag?(:win32) %}
{% if flag?(:msvc) %}
@[Link({{ flag?(:static) ? "libucrt" : "ucrt" }})]
{% end %}
lib LibC
Expand Down
2 changes: 2 additions & 0 deletions src/lib_c/x86_64-windows-msvc/c/heapapi.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
require "c/winnt"

lib LibC
HEAP_ZERO_MEMORY = 0x00000008

fun GetProcessHeap : HANDLE
fun HeapAlloc(hHeap : HANDLE, dwFlags : DWORD, dwBytes : SizeT) : Void*
fun HeapReAlloc(hHeap : HANDLE, dwFlags : DWORD, lpMem : Void*, dwBytes : SizeT) : Void*
Expand Down
6 changes: 1 addition & 5 deletions src/string.cr
Original file line number Diff line number Diff line change
Expand Up @@ -1798,11 +1798,7 @@ class String
def rchop? : String?
return if empty?

if to_unsafe[bytesize - 1] < 0x80 || single_byte_optimizable?
return unsafe_byte_slice_string(0, bytesize - 1)
end

self[0, size - 1]
unsafe_byte_slice_string(0, Char::Reader.new(at_end: self).pos, @length > 0 ? @length - 1 : 0)
end

# Returns a new `String` with *suffix* removed from the end of the string if possible, else returns `nil`.
Expand Down

0 comments on commit b4b1452

Please sign in to comment.