Skip to content

Commit

Permalink
Support building the interpreter on Windows (#12397)
Browse files Browse the repository at this point in the history
  • Loading branch information
HertzDevil authored Aug 31, 2022
1 parent d192a97 commit 3694469
Show file tree
Hide file tree
Showing 10 changed files with 47 additions and 45 deletions.
1 change: 1 addition & 0 deletions src/compiler/crystal/interpreter/context.cr
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ class Crystal::Repl::Context
# FIXME: Part 1: This is a workaround for initial integration of the interpreter:
# The loader can't handle the static libgc.a usually shipped with crystal and loading as a shared library conflicts
# with the compiler's own GC.
# (MSVC doesn't seem to have this issue)
args.delete("-lgc")

Crystal::Loader.parse(args).tap do |loader|
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/crystal/interpreter/instructions.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2016,12 +2016,12 @@ require "./repl"
libm_powi_f32: {
pop_values: [value : Float32, power : Int32],
push: true,
code: LibM.powi_f32(value, power),
code: {% if flag?(:win32) %} LibM.pow_f32(value, power.to_f32) {% else %} LibM.powi_f32(value, power) {% end %},
},
libm_powi_f64: {
pop_values: [value : Float64, power : Int32],
push: true,
code: LibM.powi_f64(value, power),
code: {% if flag?(:win32) %} LibM.pow_f64(value, power.to_f64) {% else %} LibM.powi_f64(value, power) {% end %},
},
libm_min_f32: {
pop_values: [value1 : Float32, value2 : Float32],
Expand Down
2 changes: 2 additions & 0 deletions src/compiler/crystal/loader/msvc.cr
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ class Crystal::Loader
end

def load_file?(path : String | ::Path) : Bool
return false unless File.file?(path)

# On Windows, each `.lib` import library may reference any number of `.dll`
# files, whose base names may not match the library's. Thus it is necessary
# to extract this information from the library archive itself.
Expand Down
4 changes: 3 additions & 1 deletion src/crystal/system/win32/file_descriptor.cr
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,9 @@ module Crystal::System::FileDescriptor
handle = LibC._get_osfhandle(fd)
if handle != -1
handle = LibC::HANDLE.new(handle)
if LibC.GetConsoleMode(handle, out old_mode) != 0
# TODO: use `out old_mode` after implementing interpreter out closured var
old_mode = uninitialized LibC::DWORD
if LibC.GetConsoleMode(handle, pointerof(old_mode)) != 0
console_handle = true
if fd == 1 || fd == 2 # STDOUT or STDERR
if LibC.SetConsoleMode(handle, old_mode | LibC::ENABLE_VIRTUAL_TERMINAL_PROCESSING) != 0
Expand Down
6 changes: 4 additions & 2 deletions src/crystal/system/win32/wmain.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ require "c/stringapiset"
require "c/winnls"
require "c/stdlib"

# we have both `main` and `wmain`, so we must choose an unambiguous entry point
@[Link(ldflags: "/ENTRY:wmainCRTStartup")]
{% begin %}
# we have both `main` and `wmain`, so we must choose an unambiguous entry point
@[Link({{ flag?(:preview_dll) ? "msvcrt" : "libcmt" }}, ldflags: "/ENTRY:wmainCRTStartup")]
{% end %}
lib LibCrystalMain
end

Expand Down
6 changes: 3 additions & 3 deletions src/exception/call_stack.cr
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{% if flag?(:win32) %}
require "./call_stack/stackwalk"
{% elsif flag?(:interpreted) %}
{% if flag?(:interpreted) %}
require "./call_stack/interpreter"
{% elsif flag?(:win32) %}
require "./call_stack/stackwalk"
{% elsif flag?(:wasm32) %}
require "./call_stack/null"
{% else %}
Expand Down
5 changes: 1 addition & 4 deletions src/exception/call_stack/interpreter.cr
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
require "c/dlfcn"
require "c/stdio"
require "c/string"
require "../lib_unwind"
require "../../crystal/system/print_error"

# :nodoc:
struct Exception::CallStack
Expand Down
2 changes: 1 addition & 1 deletion src/lib_c.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{% if flag?(:win32) %}
@[Link({{ flag?(:preview_dll) ? "msvcrt" : "libcmt" }})]
@[Link({{ flag?(:preview_dll) ? "ucrt" : "libucrt" }})]
{% end %}
lib LibC
alias Char = UInt8
Expand Down
1 change: 1 addition & 0 deletions src/lib_c/x86_64-windows-msvc/c/processenv.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require "c/winnt"

@[Link("kernel32")]
lib LibC
fun GetCurrentDirectoryW(nBufferLength : DWORD, lpBuffer : LPWSTR) : DWORD
fun SetCurrentDirectoryW(lpPathname : LPWSTR) : BOOL
Expand Down
61 changes: 29 additions & 32 deletions src/raise.cr
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ private def traverse_eh_table(leb, start, ip, actions)
return nil
end

{% if flag?(:win32) %}
{% if flag?(:interpreted) %}
# interpreter does not need `__crystal_personality`
{% elsif flag?(:win32) %}
require "exception/lib_unwind"

lib LibC
Expand All @@ -100,21 +102,6 @@ end
def throw_info : Void*
end

# Raises the *exception*.
#
# This will set the exception's callstack if it hasn't been already.
# Re-raising a previously caught exception won't replace the callstack.
def raise(exception : Exception) : NoReturn
{% if flag?(:debug_raise) %}
STDERR.puts
STDERR.puts "Attempting to raise: "
exception.inspect_with_backtrace(STDERR)
{% end %}

exception.callstack ||= Exception::CallStack.new
LibC._CxxThrowException(pointerof(exception).as(Void*), throw_info)
end

# :nodoc:
@[Raises]
fun __crystal_raise(unwind_ex : LibUnwind::Exception*) : NoReturn
Expand Down Expand Up @@ -190,11 +177,6 @@ end
LibC.exit(1)
0u64
end

def raise(exception : Exception) : NoReturn
LibC.printf("EXITING: Attempting to raise:\n#{exception.inspect_with_backtrace}")
LibC.exit(1)
end
{% else %}
# :nodoc:
fun __crystal_personality(version : Int32, actions : LibUnwind::Action, exception_class : UInt64, exception_object : LibUnwind::Exception*, context : Void*) : LibUnwind::ReasonCode
Expand All @@ -214,7 +196,7 @@ end
end
{% end %}

{% unless flag?(:win32) || flag?(:wasm32) %}
{% unless flag?(:interpreted) || flag?(:win32) || flag?(:wasm32) %}
# :nodoc:
@[Raises]
fun __crystal_raise(unwind_ex : LibUnwind::Exception*) : NoReturn
Expand All @@ -229,7 +211,14 @@ end
fun __crystal_get_exception(unwind_ex : LibUnwind::Exception*) : UInt64
unwind_ex.value.exception_object.address
end
{% end %}

{% if flag?(:wasm32) %}
def raise(exception : Exception) : NoReturn
LibC.printf("EXITING: Attempting to raise:\n#{exception.inspect_with_backtrace}")
LibC.exit(1)
end
{% else %}
# Raises the *exception*.
#
# This will set the exception's callstack if it hasn't been already.
Expand All @@ -251,16 +240,24 @@ def raise(message : String) : NoReturn
raise Exception.new(message)
end

# :nodoc:
{% if flag?(:interpreted) %} @[Primitive(:interpreter_raise_without_backtrace)] {% end %}
def raise_without_backtrace(exception : Exception) : NoReturn
unwind_ex = Pointer(LibUnwind::Exception).malloc
unwind_ex.value.exception_class = LibC::SizeT.zero
unwind_ex.value.exception_cleanup = LibC::SizeT.zero
unwind_ex.value.exception_object = exception.as(Void*)
unwind_ex.value.exception_type_id = exception.crystal_type_id
__crystal_raise(unwind_ex)
end
{% if flag?(:win32) %}
# :nodoc:
{% if flag?(:interpreted) %} @[Primitive(:interpreter_raise_without_backtrace)] {% end %}
def raise_without_backtrace(exception : Exception) : NoReturn
LibC._CxxThrowException(pointerof(exception).as(Void*), throw_info)
end
{% else %}
# :nodoc:
{% if flag?(:interpreted) %} @[Primitive(:interpreter_raise_without_backtrace)] {% end %}
def raise_without_backtrace(exception : Exception) : NoReturn
unwind_ex = Pointer(LibUnwind::Exception).malloc
unwind_ex.value.exception_class = LibC::SizeT.zero
unwind_ex.value.exception_cleanup = LibC::SizeT.zero
unwind_ex.value.exception_object = exception.as(Void*)
unwind_ex.value.exception_type_id = exception.crystal_type_id
__crystal_raise(unwind_ex)
end
{% end %}

# :nodoc:
fun __crystal_raise_string(message : UInt8*)
Expand Down

0 comments on commit 3694469

Please sign in to comment.