Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: crystal-lang/crystal
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 1f491996e363
Choose a base ref
...
head repository: crystal-lang/crystal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: e5d2bc64cccc
Choose a head ref
  • 8 commits
  • 49 files changed
  • 1 contributor

Commits on Nov 1, 2016

  1. AArch64: ABI

    ysbaddaden committed Nov 1, 2016
    Copy the full SHA
    d060f9c View commit details
  2. Copy the full SHA
    572df72 View commit details
  3. AArch64: std fixes

    - libxml2 is likely to miss unwind tables
    - libyaml bindings
    - libgmp bindings
    ysbaddaden committed Nov 1, 2016
    Copy the full SHA
    4058154 View commit details
  4. Copy the full SHA
    a5d073a View commit details
  5. Fix: use Time.now for Random#new_seed on ARM/AArch64

    Not the safest choice, but LLVM.read_cycle_counter is unavailable.
    Maybe we should use `/dev/urandom` instead.
    ysbaddaden committed Nov 1, 2016
    Copy the full SHA
    b1e8082 View commit details
  6. AArch64: compiler fixes

    ysbaddaden committed Nov 1, 2016
    Copy the full SHA
    6be63fe View commit details

Commits on Nov 2, 2016

  1. Fix: some LLVM targets may not be available

    For example Homebrew distributes LLVM without the AArch64 target by
    default.
    ysbaddaden committed Nov 2, 2016
    Copy the full SHA
    51ce238 View commit details
  2. Merge pull request #3491 from ysbaddaden/aarch64-support

    AArch64 support (ARMv8-A)
    ysbaddaden authored Nov 2, 2016
    Copy the full SHA
    e5d2bc6 View commit details
Showing with 1,328 additions and 77 deletions.
  1. +141 −0 spec/std/llvm/aarch64_spec.cr
  2. +4 −0 spec/std/llvm/arm_abi_spec.cr
  3. +4 −0 spec/std/llvm/x86_64_abi_spec.cr
  4. +4 −0 spec/std/llvm/x86_abi_spec.cr
  5. +1 −1 src/big/lib_gmp.cr
  6. +1 −1 src/compiler/crystal/codegen/primitives.cr
  7. +2 −0 src/compiler/crystal/codegen/target_machine.cr
  8. +52 −0 src/fiber.cr
  9. +1 −1 src/lib_c.cr
  10. +9 −0 src/lib_c/aarch64-linux-gnu/c/arpa/inet.cr
  11. +18 −0 src/lib_c/aarch64-linux-gnu/c/dirent.cr
  12. +21 −0 src/lib_c/aarch64-linux-gnu/c/dlfcn.cr
  13. +83 −0 src/lib_c/aarch64-linux-gnu/c/errno.cr
  14. +32 −0 src/lib_c/aarch64-linux-gnu/c/fcntl.cr
  15. +9 −0 src/lib_c/aarch64-linux-gnu/c/iconv.cr
  16. +39 −0 src/lib_c/aarch64-linux-gnu/c/netdb.cr
  17. +42 −0 src/lib_c/aarch64-linux-gnu/c/netinet/in.cr
  18. +6 −0 src/lib_c/aarch64-linux-gnu/c/netinet/tcp.cr
  19. +19 −0 src/lib_c/aarch64-linux-gnu/c/pthread.cr
  20. +41 −0 src/lib_c/aarch64-linux-gnu/c/signal.cr
  21. +3 −0 src/lib_c/aarch64-linux-gnu/c/stddef.cr
  22. +10 −0 src/lib_c/aarch64-linux-gnu/c/stdint.cr
  23. +8 −0 src/lib_c/aarch64-linux-gnu/c/stdio.cr
  24. +25 −0 src/lib_c/aarch64-linux-gnu/c/stdlib.cr
  25. +8 −0 src/lib_c/aarch64-linux-gnu/c/string.cr
  26. +31 −0 src/lib_c/aarch64-linux-gnu/c/sys/mman.cr
  27. +14 −0 src/lib_c/aarch64-linux-gnu/c/sys/select.cr
  28. +64 −0 src/lib_c/aarch64-linux-gnu/c/sys/socket.cr
  29. +56 −0 src/lib_c/aarch64-linux-gnu/c/sys/stat.cr
  30. +3 −0 src/lib_c/aarch64-linux-gnu/c/sys/syscall.cr
  31. +15 −0 src/lib_c/aarch64-linux-gnu/c/sys/time.cr
  32. +12 −0 src/lib_c/aarch64-linux-gnu/c/sys/times.cr
  33. +61 −0 src/lib_c/aarch64-linux-gnu/c/sys/types.cr
  34. +8 −0 src/lib_c/aarch64-linux-gnu/c/sys/un.cr
  35. +8 −0 src/lib_c/aarch64-linux-gnu/c/sys/wait.cr
  36. +120 −0 src/lib_c/aarch64-linux-gnu/c/termios.cr
  37. +37 −0 src/lib_c/aarch64-linux-gnu/c/time.cr
  38. +39 −0 src/lib_c/aarch64-linux-gnu/c/unistd.cr
  39. +40 −15 src/llvm.cr
  40. +58 −0 src/llvm/abi.cr
  41. +158 −0 src/llvm/abi/aarch64.cr
  42. +2 −52 src/llvm/abi/arm.cr
  43. +6 −0 src/llvm/lib_llvm.cr
  44. +2 −0 src/llvm/target_machine.cr
  45. +7 −3 src/random.cr
  46. +1 −1 src/unwind.cr
  47. +1 −1 src/xml/error.cr
  48. +1 −1 src/xml/xpath_context.cr
  49. +1 −1 src/yaml/lib_yaml.cr
141 changes: 141 additions & 0 deletions spec/std/llvm/aarch64_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
require "spec"
require "llvm"

{% if LibLLVM::BUILT_TARGETS.includes?(:aarch64) %}
LLVM.init_aarch64
{% end %}

private def abi
triple = "aarch64-unknown-linux-gnu"
target = LLVM::Target.from_triple(triple)
machine = target.create_target_machine(triple)
LLVM::ABI::AArch64.new(machine)
end

class LLVM::ABI
describe AArch64 do
{% if LibLLVM::BUILT_TARGETS.includes?(:aarch64) %}
describe "align" do
it "for integer" do
abi.align(LLVM::Int1).should be_a(::Int32)
abi.align(LLVM::Int1).should eq(1)
abi.align(LLVM::Int8).should eq(1)
abi.align(LLVM::Int16).should eq(2)
abi.align(LLVM::Int32).should eq(4)
abi.align(LLVM::Int64).should eq(8)
end

it "for pointer" do
abi.align(LLVM::Int8.pointer).should eq(8)
end

it "for float" do
abi.align(LLVM::Float).should eq(4)
end

it "for double" do
abi.align(LLVM::Double).should eq(8)
end

it "for struct" do
abi.align(LLVM::Type.struct([LLVM::Int32, LLVM::Int64])).should eq(8)
abi.align(LLVM::Type.struct([LLVM::Int8, LLVM::Int16])).should eq(2)
end

it "for packed struct" do
abi.align(LLVM::Type.struct([LLVM::Int32, LLVM::Int64], packed: true)).should eq(1)
end

it "for array" do
abi.align(LLVM::Int16.array(10)).should eq(2)
end
end

describe "size" do
it "for integer" do
abi.size(LLVM::Int1).should be_a(::Int32)
abi.size(LLVM::Int1).should eq(1)
abi.size(LLVM::Int8).should eq(1)
abi.size(LLVM::Int16).should eq(2)
abi.size(LLVM::Int32).should eq(4)
abi.size(LLVM::Int64).should eq(8)
end

it "for pointer" do
abi.size(LLVM::Int8.pointer).should eq(8)
end

it "for float" do
abi.size(LLVM::Float).should eq(4)
end

it "for double" do
abi.size(LLVM::Double).should eq(8)
end

it "for struct" do
abi.size(LLVM::Type.struct([LLVM::Int32, LLVM::Int64])).should eq(16)
abi.size(LLVM::Type.struct([LLVM::Int16, LLVM::Int8])).should eq(4)
abi.size(LLVM::Type.struct([LLVM::Int32, LLVM::Int8, LLVM::Int8])).should eq(8)
end

it "for packed struct" do
abi.size(LLVM::Type.struct([LLVM::Int32, LLVM::Int64], packed: true)).should eq(12)
end

it "for array" do
abi.size(LLVM::Int16.array(10)).should eq(20)
end
end

describe "abi_info" do
it "does with primitives" do
arg_types = [LLVM::Int32, LLVM::Int64]
return_type = LLVM::Int8
info = abi.abi_info(arg_types, return_type, true)
info.arg_types.size.should eq(2)

info.arg_types[0].should eq(ArgType.direct(LLVM::Int32))
info.arg_types[1].should eq(ArgType.direct(LLVM::Int64))
info.return_type.should eq(ArgType.direct(LLVM::Int8))
end

it "does with structs less than 64 bits" do
str = LLVM::Type.struct([LLVM::Int8, LLVM::Int16])
arg_types = [str]
return_type = str

info = abi.abi_info(arg_types, return_type, true)
info.arg_types.size.should eq(1)

info.arg_types[0].should eq(ArgType.direct(str, cast: LLVM::Int32))
info.return_type.should eq(ArgType.direct(str, cast: LLVM::Int32))
end

it "does with structs between 64 and 128 bits" do
str = LLVM::Type.struct([LLVM::Int64, LLVM::Int16])
arg_types = [str]
return_type = str

info = abi.abi_info(arg_types, return_type, true)
info.arg_types.size.should eq(1)

info.arg_types[0].should eq(ArgType.direct(str, cast: LLVM::Type.array(LLVM::Int64, 2)))
info.return_type.should eq(ArgType.direct(str, cast: LLVM::Type.array(LLVM::Int64, 2)))
end

it "does with structs between 64 and 128 bits" do
str = LLVM::Type.struct([LLVM::Int64, LLVM::Int64, LLVM::Int8])
arg_types = [str]
return_type = str

info = abi.abi_info(arg_types, return_type, true)
info.arg_types.size.should eq(1)

info.arg_types[0].should eq(ArgType.indirect(str, Attribute::ByVal))
info.return_type.should eq(ArgType.indirect(str, Attribute::StructRet))
end
end
{% end %}
end
end
4 changes: 4 additions & 0 deletions spec/std/llvm/arm_abi_spec.cr
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
require "spec"
require "llvm"

{% if LibLLVM::BUILT_TARGETS.includes?(:arm) %}
LLVM.init_arm
{% end %}

private def abi
triple = "arm-unknown-linux-gnueabihf"
@@ -12,6 +14,7 @@ end

class LLVM::ABI
describe ARM do
{% if LibLLVM::BUILT_TARGETS.includes?(:arm) %}
describe "align" do
it "for integer" do
abi.align(LLVM::Int1).should be_a(::Int32)
@@ -133,5 +136,6 @@ class LLVM::ABI
info.return_type.should eq(ArgType.indirect(str, Attribute::StructRet))
end
end
{% end %}
end
end
4 changes: 4 additions & 0 deletions spec/std/llvm/x86_64_abi_spec.cr
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
require "spec"
require "llvm"

{% if LibLLVM::BUILT_TARGETS.includes?(:x86) %}
LLVM.init_x86
{% end %}

private def abi
triple = LLVM.default_target_triple.gsub(/^(.+?)-/, "x86_64-")
@@ -12,6 +14,7 @@ end

class LLVM::ABI
describe X86_64 do
{% if LibLLVM::BUILT_TARGETS.includes?(:x86) %}
describe "align" do
it "for integer" do
abi.align(LLVM::Int1).should be_a(::Int32)
@@ -133,5 +136,6 @@ class LLVM::ABI
info.return_type.should eq(ArgType.indirect(str, Attribute::StructRet))
end
end
{% end %}
end
end
4 changes: 4 additions & 0 deletions spec/std/llvm/x86_abi_spec.cr
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
require "spec"
require "llvm"

{% if LibLLVM::BUILT_TARGETS.includes?(:x86) %}
LLVM.init_x86
{% end %}

private def abi
triple = {% if flag?(:darwin) %}
@@ -16,6 +18,7 @@ end

class LLVM::ABI
describe X86 do
{% if LibLLVM::BUILT_TARGETS.includes?(:x86) %}
describe "align" do
it "for integer" do
abi.align(LLVM::Int1).should be_a(::Int32)
@@ -137,5 +140,6 @@ class LLVM::ABI
info.return_type.should eq(ArgType.indirect(str, Attribute::StructRet))
end
end
{% end %}
end
end
2 changes: 1 addition & 1 deletion src/big/lib_gmp.cr
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ lib LibGMP
alias Double = LibC::Double
alias BitcntT = ULong

{% if flag?(:x86_64) %}
{% if flag?(:x86_64) || flag?(:aarch64) %}
alias MpExp = Int64
{% else %}
alias MpExp = Int32
2 changes: 1 addition & 1 deletion src/compiler/crystal/codegen/primitives.cr
Original file line number Diff line number Diff line change
@@ -830,7 +830,7 @@ class Crystal::CodeGenVisitor
when CharType
inst.alignment = 4
else
inst.alignment = @program.has_flag?("x86_64") ? 8 : 4
inst.alignment = @program.has_flag?("x86_64") || @program.has_flag?("aarch64") ? 8 : 4
end
end

2 changes: 2 additions & 0 deletions src/compiler/crystal/codegen/target_machine.cr
Original file line number Diff line number Diff line change
@@ -7,6 +7,8 @@ module Crystal
case target_triple
when /^(x86_64|i[3456]86|amd64)/
LLVM.init_x86
when /^aarch64/
LLVM.init_aarch64
when /^arm/
LLVM.init_arm

52 changes: 52 additions & 0 deletions src/fiber.cr
Original file line number Diff line number Diff line change
@@ -48,6 +48,13 @@ class Fiber
stack_ptr[0] = self.as(Void*) # First argument passed on the stack
stack_ptr[-1] = Pointer(Void).null # Empty space to keep the stack alignment (16 bytes)
stack_ptr[-2] = fiber_main.pointer # Initial `resume` will `ret` to this address
{% elsif flag?(:aarch64) %}
# In ARMv6 / ARVMv7, the context switch push/pops 19 registers.
# Add one more to store the argument of `fiber_main`
@stack_top = (stack_ptr - 21).as(Void*)

stack_ptr[-1] = self.as(Void*) # This will be `pop` into r0 (first argument)
stack_ptr[-13] = fiber_main.pointer # Initial `resume` will `ret` to this address
{% elsif flag?(:arm) %}
# In ARMv6 / ARVMv7, the context switch push/pops 8 registers.
# Add one more to store the argument of `fiber_main`
@@ -174,6 +181,51 @@ class Fiber
popl \%ebx
popl \%edi"
:: "r"(current), "r"(to))
{% elsif flag?(:aarch64) %}
# Adapted from https://github.com/ldc-developers/druntime/blob/ldc/src/core/threadasm.S
#
# preserve/restore AAPCS64 registers
# r19-r28 5.1.1 64-bit callee saved
# r29 fp, or possibly callee saved reg - depends on platform choice 5.2.3)
# r30 lr
# d8-d15 5.1.2 says callee only must save bottom 64-bits (the "d" regs)
#
asm("
stp d15, d14, [sp, #-22*8]!
stp d13, d12, [sp, #2*8]
stp d11, d10, [sp, #4*8]
stp d9, d8, [sp, #6*8]
stp x30, x29, [sp, #8*8] // lr, fp
stp x28, x27, [sp, #10*8]
stp x26, x25, [sp, #12*8]
stp x24, x23, [sp, #14*8]
stp x22, x21, [sp, #16*8]
stp x20, x19, [sp, #18*8]
str x0, [sp, #20*8]
mov x19, sp
str x19, [$0]
ldr x19, [$1]
mov sp, x19
ldr x0, [sp, #20*8]
ldp x20, x19, [sp, #18*8]
ldp x22, x21, [sp, #16*8]
ldp x24, x23, [sp, #14*8]
ldp x26, x25, [sp, #12*8]
ldp x28, x27, [sp, #10*8]
ldp x30, x29, [sp, #8*8] // lr, fp
ldp d9, d8, [sp, #6*8]
ldp d11, d10, [sp, #4*8]
ldp d13, d12, [sp, #2*8]
ldp d15, d14, [sp], #22*8
// avoid a stack corruption that will confuse the unwinder
mov x16, x30 // save lr
mov x30, #0 // reset lr
br x16 // jump to new pc value
"
:: "r"(current), "r"(to))
{% elsif flag?(:armhf) %}
# we eventually reset LR to zero to avoid the ARM unwinder to mistake the
# context switch as a regular call.
2 changes: 1 addition & 1 deletion src/lib_c.cr
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ lib LibC
alias Int = Int32
alias UInt = UInt32

{% if flag?(:x86_64) %}
{% if flag?(:x86_64) || flag?(:aarch64) %}
alias Long = Int64
alias ULong = UInt64
{% elsif flag?(:i686) || flag?(:arm) %}
9 changes: 9 additions & 0 deletions src/lib_c/aarch64-linux-gnu/c/arpa/inet.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
require "../netinet/in"
require "../stdint"

lib LibC
fun htons(hostshort : UInt16T) : UInt16T
fun ntohs(netshort : UInt16T) : UInt16T
fun inet_ntop(af : Int, cp : Void*, buf : Char*, len : SocklenT) : Char*
fun inet_pton(af : Int, cp : Char*, buf : Void*) : Int
end
18 changes: 18 additions & 0 deletions src/lib_c/aarch64-linux-gnu/c/dirent.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
require "./sys/types"

lib LibC
type DIR = Void

struct Dirent
d_ino : InoT
d_off : Long
d_reclen : UShort
d_type : Char
d_name : StaticArray(Char, 256)
end

fun closedir(dirp : DIR*) : Int
fun opendir(name : Char*) : DIR*
fun readdir(dirp : DIR*) : Dirent*
fun rewinddir(dirp : DIR*) : Void
end
21 changes: 21 additions & 0 deletions src/lib_c/aarch64-linux-gnu/c/dlfcn.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
@[Link("dl")]
lib LibC
RTLD_LAZY = 0x00001
RTLD_NOW = 0x00002
RTLD_GLOBAL = 0x00100
RTLD_LOCAL = 0
RTLD_DEFAULT = Pointer(Void).new(0)

struct DlInfo
dli_fname : Char*
dli_fbase : Void*
dli_sname : Char*
dli_saddr : Void*
end

fun dlclose(handle : Void*) : Int
fun dlerror : Char*
fun dlopen(file : Char*, mode : Int) : Void*
fun dlsym(handle : Void*, name : Char*) : Void*
fun dladdr(address : Void*, info : DlInfo*) : Int
end
Loading