Skip to content

Commit 62bb206

Browse files
author
Ary Borenszweig
committedDec 23, 2016
Fixed stalled compilation when using LLVM 3.5
1 parent f15f5a8 commit 62bb206

File tree

3 files changed

+66
-44
lines changed

3 files changed

+66
-44
lines changed
 

Diff for: ‎src/compiler/crystal/compiler.cr

+56-20
Original file line numberDiff line numberDiff line change
@@ -406,8 +406,6 @@ module Crystal
406406
bc_name = self.bc_name
407407
object_name = self.object_name
408408

409-
memory_buffer = llvm_mod.write_bitcode_to_memory_buffer
410-
411409
# To compile a file we first generate a `.bc` file and then
412410
# create an object file from it. These `.bc` files are stored
413411
# in the cache directory.
@@ -418,27 +416,61 @@ module Crystal
418416
# `.bc` file is exactly the same as the old one. In that case
419417
# the `.o` file will also be the same, so we simply reuse the
420418
# old one. Generating an `.o` file is what takes most time.
421-
if !compiler.emit && !@bc_flags_changed && File.exists?(bc_name) && File.exists?(object_name)
422-
memory_io = IO::Memory.new(memory_buffer.to_slice)
423-
changed = File.open(bc_name) { |bc_file| !FileUtils.cmp(bc_file, memory_io) }
424-
425-
# If the user cancelled a previous compilation
426-
# it might be that the .o file is empty
427-
if !changed && File.size(object_name) > 0
428-
# We can skip compilation
429-
memory_buffer.dispose
430-
memory_buffer = nil
431-
else
432-
# We need to compile, so we'll write the memory buffer to file
419+
420+
must_compile = true
421+
can_reuse_previous_compilation =
422+
!compiler.emit && !@bc_flags_changed && File.exists?(bc_name) && File.exists?(object_name)
423+
424+
{% if LibLLVM::IS_35 %}
425+
# In LLVM 3.5 we can't write a bitcode to memory,
426+
# so instead we write it to another file
427+
bc_name_new = self.bc_name_new
428+
llvm_mod.write_bitcode_to_file(bc_name_new)
429+
430+
if can_reuse_previous_compilation
431+
if FileUtils.cmp(bc_name, bc_name_new)
432+
# If the user cancelled a previous compilation it might be that
433+
# the .o file is empty
434+
if File.size(object_name) > 0
435+
File.delete bc_name_new
436+
must_compile = false
437+
end
438+
end
433439
end
434-
end
435440

436-
# If there's a memory buffer, it means we must create a .o from it
437-
if memory_buffer
438-
# Create the .bc file (for next compilations)
439-
File.write(bc_name, memory_buffer.to_slice)
440-
memory_buffer.dispose
441+
if must_compile
442+
# Create/overwrite the .bc file (for next compilations)
443+
File.rename(bc_name_new, bc_name)
444+
compiler.optimize llvm_mod if compiler.release?
445+
compiler.target_machine.emit_obj_to_file llvm_mod, object_name
446+
end
447+
{% else %}
448+
memory_buffer = llvm_mod.write_bitcode_to_memory_buffer
449+
450+
if can_reuse_previous_compilation
451+
memory_io = IO::Memory.new(memory_buffer.to_slice)
452+
changed = File.open(bc_name) { |bc_file| !FileUtils.cmp(bc_file, memory_io) }
453+
454+
# If the user cancelled a previous compilation
455+
# it might be that the .o file is empty
456+
if !changed && File.size(object_name) > 0
457+
must_compile = false
458+
memory_buffer.dispose
459+
memory_buffer = nil
460+
else
461+
# We need to compile, so we'll write the memory buffer to file
462+
end
463+
end
441464

465+
# If there's a memory buffer, it means we must create a .o from it
466+
if memory_buffer
467+
# Create the .bc file (for next compilations)
468+
File.write(bc_name, memory_buffer.to_slice)
469+
memory_buffer.dispose
470+
end
471+
{% end %}
472+
473+
if must_compile
442474
compiler.optimize llvm_mod if compiler.release?
443475
compiler.target_machine.emit_obj_to_file llvm_mod, object_name
444476
end
@@ -477,6 +509,10 @@ module Crystal
477509
"#{@output_dir}/#{@name}.bc"
478510
end
479511

512+
def bc_name_new
513+
"#{@output_dir}/#{@name}.new.bc"
514+
end
515+
480516
def ll_name
481517
"#{@output_dir}/#{@name}.ll"
482518
end

Diff for: ‎src/llvm/memory_buffer.cr

+6-12
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
11
class LLVM::MemoryBuffer
2-
def initialize(@unwrap : LibLLVM::MemoryBufferRef | Bytes)
2+
def initialize(@unwrap : LibLLVM::MemoryBufferRef)
33
@finalized = false
44
end
55

66
def to_slice
7-
if (unwrap = @unwrap).is_a?(Bytes)
8-
unwrap
9-
else
10-
Slice.new(
11-
LibLLVM.get_buffer_start(unwrap),
12-
LibLLVM.get_buffer_size(unwrap),
13-
)
14-
end
7+
Slice.new(
8+
LibLLVM.get_buffer_start(@unwrap),
9+
LibLLVM.get_buffer_size(@unwrap),
10+
)
1511
end
1612

1713
def dispose
@@ -23,9 +19,7 @@ class LLVM::MemoryBuffer
2319
def finalize
2420
return if @finalized
2521

26-
if (unwrap = @unwrap).is_a?(LibLLVM::MemoryBufferRef)
27-
LibLLVM.dispose_memory_buffer(unwrap)
28-
end
22+
LibLLVM.dispose_memory_buffer(@unwrap)
2923
end
3024

3125
def to_unsafe

Diff for: ‎src/llvm/module.cr

+4-12
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,11 @@ class LLVM::Module
3434
LibLLVM.write_bitcode_to_file self, filename
3535
end
3636

37-
def write_bitcode_to_memory_buffer
38-
{% if LibLLVM::IS_35 %}
39-
# LLVMWriteBitcodeToMemoryBuffer doesn't exist in LLVM 3.5.0
40-
slice = IO.pipe do |r, w|
41-
write_bitcode_to_fd(w.fd)
42-
w.close
43-
r.gets_to_end.to_slice
44-
end
45-
MemoryBuffer.new(slice)
46-
{% else %}
37+
{% unless LibLLVM::IS_35 %}
38+
def write_bitcode_to_memory_buffer
4739
MemoryBuffer.new(LibLLVM.write_bitcode_to_memory_buffer self)
48-
{% end %}
49-
end
40+
end
41+
{% end %}
5042

5143
def write_bitcode_to_fd(fd : Int, should_close = false, buffered = false)
5244
LibLLVM.write_bitcode_to_fd(self, fd, should_close ? 1 : 0, buffered ? 1 : 0)

0 commit comments

Comments
 (0)
Please sign in to comment.