-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add compiler support for AVR architecture (Arduino) (#14393)
Co-authored-by: Sijawusz Pur Rahnama <[email protected]>
- Loading branch information
1 parent
89f2e43
commit 7ecb968
Showing
11 changed files
with
382 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
require "spec" | ||
|
||
{% if flag?(:interpreted) && !flag?(:win32) %} | ||
# TODO: figure out how to link against libstdc++ in interpreted code (#14398) | ||
pending LLVM::ABI::AVR | ||
{% skip_file %} | ||
{% end %} | ||
|
||
require "llvm" | ||
|
||
{% if LibLLVM::BUILT_TARGETS.includes?(:avr) %} | ||
LLVM.init_avr | ||
{% end %} | ||
|
||
private def abi | ||
triple = "avr-unknown-unknown-atmega328p" | ||
target = LLVM::Target.from_triple(triple) | ||
machine = target.create_target_machine(triple) | ||
machine.enable_global_isel = false | ||
LLVM::ABI::AVR.new(machine) | ||
end | ||
|
||
private def test(msg, &block : LLVM::ABI, LLVM::Context ->) | ||
it msg do | ||
abi = abi() | ||
ctx = LLVM::Context.new | ||
block.call(abi, ctx) | ||
end | ||
end | ||
|
||
class LLVM::ABI | ||
describe AVR do | ||
{% if LibLLVM::BUILT_TARGETS.includes?(:avr) %} | ||
describe "align" do | ||
test "for integer" do |abi, ctx| | ||
abi.align(ctx.int1).should be_a(::Int32) | ||
abi.align(ctx.int1).should eq(1) | ||
abi.align(ctx.int8).should eq(1) | ||
abi.align(ctx.int16).should eq(1) | ||
abi.align(ctx.int32).should eq(1) | ||
abi.align(ctx.int64).should eq(1) | ||
end | ||
|
||
test "for pointer" do |abi, ctx| | ||
abi.align(ctx.int8.pointer).should eq(1) | ||
end | ||
|
||
test "for float" do |abi, ctx| | ||
abi.align(ctx.float).should eq(1) | ||
end | ||
|
||
test "for double" do |abi, ctx| | ||
abi.align(ctx.double).should eq(1) | ||
end | ||
|
||
test "for struct" do |abi, ctx| | ||
abi.align(ctx.struct([ctx.int32, ctx.int64])).should eq(1) | ||
abi.align(ctx.struct([ctx.int8, ctx.int16])).should eq(1) | ||
end | ||
|
||
test "for packed struct" do |abi, ctx| | ||
abi.align(ctx.struct([ctx.int32, ctx.int64], packed: true)).should eq(1) | ||
end | ||
|
||
test "for array" do |abi, ctx| | ||
abi.align(ctx.int16.array(10)).should eq(1) | ||
end | ||
end | ||
|
||
describe "size" do | ||
test "for integer" do |abi, ctx| | ||
abi.size(ctx.int1).should be_a(::Int32) | ||
abi.size(ctx.int1).should eq(1) | ||
abi.size(ctx.int8).should eq(1) | ||
abi.size(ctx.int16).should eq(2) | ||
abi.size(ctx.int32).should eq(4) | ||
abi.size(ctx.int64).should eq(8) | ||
end | ||
|
||
test "for pointer" do |abi, ctx| | ||
abi.size(ctx.int8.pointer).should eq(2) | ||
end | ||
|
||
test "for float" do |abi, ctx| | ||
abi.size(ctx.float).should eq(4) | ||
end | ||
|
||
test "for double" do |abi, ctx| | ||
abi.size(ctx.double).should eq(8) | ||
end | ||
|
||
test "for struct" do |abi, ctx| | ||
abi.size(ctx.struct([ctx.int32, ctx.int64])).should eq(12) | ||
abi.size(ctx.struct([ctx.int16, ctx.int8])).should eq(3) | ||
abi.size(ctx.struct([ctx.int32, ctx.int8, ctx.int8])).should eq(6) | ||
end | ||
|
||
test "for packed struct" do |abi, ctx| | ||
abi.size(ctx.struct([ctx.int32, ctx.int8], packed: true)).should eq(5) | ||
end | ||
|
||
test "for array" do |abi, ctx| | ||
abi.size(ctx.int16.array(10)).should eq(20) | ||
end | ||
end | ||
|
||
describe "abi_info" do | ||
{% for bits in [1, 8, 16, 32, 64] %} | ||
test "int{{bits}}" do |abi, ctx| | ||
arg_type = ArgType.direct(ctx.int{{bits}}) | ||
info = abi.abi_info([ctx.int{{bits}}], ctx.int{{bits}}, true, ctx) | ||
info.arg_types.size.should eq(1) | ||
info.arg_types[0].should eq(arg_type) | ||
info.arg_types[0].kind.should eq(LLVM::ABI::ArgKind::Direct) | ||
info.return_type.should eq(arg_type) | ||
info.return_type.kind.should eq(LLVM::ABI::ArgKind::Direct) | ||
end | ||
{% end %} | ||
|
||
test "float" do |abi, ctx| | ||
arg_type = ArgType.direct(ctx.float) | ||
info = abi.abi_info([ctx.float], ctx.float, true, ctx) | ||
info.arg_types.size.should eq(1) | ||
info.arg_types[0].should eq(arg_type) | ||
info.arg_types[0].kind.should eq(LLVM::ABI::ArgKind::Direct) | ||
info.return_type.should eq(arg_type) | ||
info.return_type.kind.should eq(LLVM::ABI::ArgKind::Direct) | ||
end | ||
|
||
test "double" do |abi, ctx| | ||
arg_type = ArgType.direct(ctx.double) | ||
info = abi.abi_info([ctx.double], ctx.double, true, ctx) | ||
info.arg_types.size.should eq(1) | ||
info.arg_types[0].should eq(arg_type) | ||
info.arg_types[0].kind.should eq(LLVM::ABI::ArgKind::Direct) | ||
info.return_type.should eq(arg_type) | ||
info.return_type.kind.should eq(LLVM::ABI::ArgKind::Direct) | ||
end | ||
|
||
test "multiple arguments" do |abi, ctx| | ||
args = 9.times.map { ctx.int16 }.to_a | ||
info = abi.abi_info(args, ctx.int8, false, ctx) | ||
info.arg_types.size.should eq(9) | ||
info.arg_types.each(&.kind.should eq(LLVM::ABI::ArgKind::Direct)) | ||
end | ||
|
||
test "multiple arguments above registers" do |abi, ctx| | ||
args = 5.times.map { ctx.int32 }.to_a | ||
info = abi.abi_info(args, ctx.int8, false, ctx) | ||
info.arg_types.size.should eq(5) | ||
info.arg_types[0].kind.should eq(LLVM::ABI::ArgKind::Direct) | ||
info.arg_types[1].kind.should eq(LLVM::ABI::ArgKind::Direct) | ||
info.arg_types[2].kind.should eq(LLVM::ABI::ArgKind::Direct) | ||
info.arg_types[3].kind.should eq(LLVM::ABI::ArgKind::Direct) | ||
info.arg_types[4].kind.should eq(LLVM::ABI::ArgKind::Indirect) | ||
end | ||
|
||
test "struct args within 18 bytes" do |abi, ctx| | ||
args = [ | ||
ctx.int8, # rounded to 2 bytes | ||
ctx.struct([ctx.int32, ctx.int32]), # 8 bytes | ||
ctx.struct([ctx.int32, ctx.int32]), # 8 bytes | ||
] | ||
info = abi.abi_info(args, ctx.void, false, ctx) | ||
info.arg_types.size.should eq(3) | ||
info.arg_types[0].kind.should eq(LLVM::ABI::ArgKind::Direct) | ||
info.arg_types[1].kind.should eq(LLVM::ABI::ArgKind::Direct) | ||
info.arg_types[2].kind.should eq(LLVM::ABI::ArgKind::Direct) | ||
end | ||
|
||
test "struct args over 18 bytes" do |abi, ctx| | ||
args = [ | ||
ctx.int32, # 4 bytes | ||
ctx.struct([ctx.int32, ctx.int32]), # 8 bytes | ||
ctx.struct([ctx.int32, ctx.int32]), # 8 bytes | ||
] | ||
info = abi.abi_info(args, ctx.void, false, ctx) | ||
info.arg_types.size.should eq(3) | ||
info.arg_types[0].kind.should eq(LLVM::ABI::ArgKind::Direct) | ||
info.arg_types[1].kind.should eq(LLVM::ABI::ArgKind::Direct) | ||
info.arg_types[2].kind.should eq(LLVM::ABI::ArgKind::Indirect) | ||
end | ||
|
||
test "returns struct within 8 bytes" do |abi, ctx| | ||
rty = ctx.struct([ctx.int32, ctx.int32]) | ||
info = abi.abi_info([] of Type, rty, true, ctx) | ||
info.return_type.kind.should eq(LLVM::ABI::ArgKind::Direct) | ||
end | ||
|
||
test "returns struct over 8 bytes" do |abi, ctx| | ||
rty = ctx.struct([ctx.int32, ctx.int32, ctx.int8]) | ||
info = abi.abi_info([] of Type, rty, true, ctx) | ||
info.return_type.kind.should eq(LLVM::ABI::ArgKind::Indirect) | ||
end | ||
end | ||
{% end %} | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.