Hi,
I'm using swiftc to output LLVM IR then compiling this to AVR machine code using a custom built LLC.exe. This is all working well in most cases but there's an issue with the pointers.
Can anyone give me pointers in the swift code how I can change the datalayout that's output to specify 16 bit pointers please?
To be specific, I'm trying to get the LLVM datalayout to support 16 bit pointers.
Here's an example program and how it compiles to SIL and then to LLVM IR.
program:
import AVR
typealias IntegerLiteralType = UInt8
pinMode(pin: 4, mode: INPUT)
setupTimerIntervalInterruptCallback(tenthsOfAMillisecond: 1000) {
}
while(true) {
}
SIL:
sil_stage raw
import Builtin
import Swift
import SwiftShims
// INPUT
sil_global [let] @INPUT : $Bool
sil_scope 1 { parent @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 }
sil_scope 2 { loc "main.swift":22:1 parent 1 }
// main
sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):
%2 = global_addr @INPUT : $*Bool, scope 1 // user: %8
// function_ref pinMode(pin : UInt8, mode : Bool) -> ()
%3 = function_ref @_TF3AVR7pinModeFT3pinVs5UInt84modeSb_T_ : $@convention(thin) (UInt8, Bool) -> (), loc "main.swift":5:1, scope 1 // user: %9
// function_ref UInt8.init(_builtinIntegerLiteral : Builtin.Int2048) -> UInt8
%4 = function_ref @_TFVs5UInt8CfT22_builtinIntegerLiteralBi2048__S_ : $@convention(method) (Builtin.Int2048, @thin UInt8.Type) -> UInt8, loc "main.swift":5:14, scope 1 // user: %7
%5 = metatype $@thin UInt8.Type, loc "main.swift":5:14, scope 1 // user: %7
%6 = integer_literal $Builtin.Int2048, 4, loc "main.swift":5:14, scope 1 // user: %7
%7 = apply %4(%6, %5) : $@convention(method) (Builtin.Int2048, @thin UInt8.Type) -> UInt8, loc "main.swift":5:14, scope 1 // user: %9
%8 = load_borrow %2 : $*Bool, loc "main.swift":5:23, scope 1 // user: %9
%9 = apply %3(%7, %8) : $@convention(thin) (UInt8, Bool) -> (), loc "main.swift":5:28, scope 1
// function_ref setupTimerIntervalInterruptCallback(tenthsOfAMillisecond : UInt16, callback : @convention(c) () -> ()) -> ()
%10 = function_ref @_TF3AVR35setupTimerIntervalInterruptCallbackFT20tenthsOfAMillisecondVs6UInt168callbackcT_T__T_ : $@convention(thin) (UInt16, @convention(c) () -> ()) -> (), loc "main.swift":7:1, scope 1 // user: %16
// function_ref UInt16.init(_builtinIntegerLiteral : Builtin.Int2048) -> UInt16
%11 = function_ref @_TFVs6UInt16CfT22_builtinIntegerLiteralBi2048__S_ : $@convention(method) (Builtin.Int2048, @thin UInt16.Type) -> UInt16, loc "main.swift":7:59, scope 1 // user: %14
%12 = metatype $@thin UInt16.Type, loc "main.swift":7:59, scope 1 // user: %14
%13 = integer_literal $Builtin.Int2048, 1000, loc "main.swift":7:59, scope 1 // user: %14
%14 = apply %11(%13, %12) : $@convention(method) (Builtin.Int2048, @thin UInt16.Type) -> UInt16, loc "main.swift":7:59, scope 1 // user: %16
// function_ref @objc (closure #1)
%15 = function_ref @_TToF4mainU_FT_T_ : $@convention(c) () -> (), loc "main.swift":7:65, scope 1 // user: %16
%16 = apply %10(%14, %15) : $@convention(thin) (UInt16, @convention(c) () -> ()) -> (), loc "main.swift":19:1, scope 1
br bb1, loc "main.swift":21:1, scope 2 // id: %17
bb1: // Preds: bb2 bb0
// function_ref Bool._getBuiltinLogicValue() -> Builtin.Int1
%18 = function_ref @_TFSb21_getBuiltinLogicValuefT_Bi1_ : $@convention(method) (Bool) -> Builtin.Int1, loc "main.swift":21:7, scope 2 // user: %23
// function_ref Bool.init(_builtinBooleanLiteral : Builtin.Int1) -> Bool
%19 = function_ref @_TFSbCfT22_builtinBooleanLiteralBi1__Sb : $@convention(method) (Builtin.Int1, @thin Bool.Type) -> Bool, loc "main.swift":21:7, scope 2 // user: %22
%20 = metatype $@thin Bool.Type, loc "main.swift":21:7, scope 2 // user: %22
%21 = integer_literal $Builtin.Int1, -1, loc "main.swift":21:7, scope 2 // user: %22
%22 = apply %19(%21, %20) : $@convention(method) (Builtin.Int1, @thin Bool.Type) -> Bool, loc "main.swift":21:7, scope 2 // user: %23
%23 = apply %18(%22) : $@convention(method) (Bool) -> Builtin.Int1, loc "main.swift":21:11, scope 2 // user: %24
cond_br %23, bb2, bb3, loc "main.swift":21:11, scope 2 // id: %24
bb2: // Preds: bb1
br bb1, loc "main.swift":22:1, scope 2 // id: %25
bb3: // Preds: bb1
%26 = integer_literal $Builtin.Int32, 0, scope 2 // user: %27
%27 = struct $Int32 (%26 : $Builtin.Int32), scope 2 // user: %28
return %27 : $Int32, scope 2 // id: %28
} // end sil function 'main'
// pinMode(pin : UInt8, mode : Bool) -> ()
sil @_TF3AVR7pinModeFT3pinVs5UInt84modeSb_T_ : $@convention(thin) (UInt8, Bool) -> ()
// UInt8.init(_builtinIntegerLiteral : Builtin.Int2048) -> UInt8
sil [transparent] [fragile] @_TFVs5UInt8CfT22_builtinIntegerLiteralBi2048__S_ : $@convention(method) (Builtin.Int2048, @thin UInt8.Type) -> UInt8
// setupTimerIntervalInterruptCallback(tenthsOfAMillisecond : UInt16, callback : @convention(c) () -> ()) -> ()
sil @_TF3AVR35setupTimerIntervalInterruptCallbackFT20tenthsOfAMillisecondVs6UInt168callbackcT_T__T_ : $@convention(thin) (UInt16, @convention(c) () -> ()) -> ()
// UInt16.init(_builtinIntegerLiteral : Builtin.Int2048) -> UInt16
sil [transparent] [fragile] @_TFVs6UInt16CfT22_builtinIntegerLiteralBi2048__S_ : $@convention(method) (Builtin.Int2048, @thin UInt16.Type) -> UInt16
sil_scope 3 { loc "main.swift":7:65 parent @_TF4mainU_FT_T_ : $@convention(thin) () -> () }
sil_scope 4 { loc "main.swift":19:1 parent 3 }
// (closure #1)
sil shared @_TF4mainU_FT_T_ : $@convention(thin) () -> () {
bb0:
%0 = tuple (), loc "main.swift":19:1, scope 4 // user: %1
return %0 : $(), loc "main.swift":19:1, scope 4 // id: %1
} // end sil function '_TF4mainU_FT_T_'
sil_scope 5 { loc "main.swift":7:65 parent @_TToF4mainU_FT_T_ : $@convention(c) () -> () }
// @objc (closure #1)
sil shared [thunk] @_TToF4mainU_FT_T_ : $@convention(c) () -> () {
bb0:
// function_ref (closure #1)
%0 = function_ref @_TF4mainU_FT_T_ : $@convention(thin) () -> (), scope 5 // user: %1
%1 = apply %0() : $@convention(thin) () -> (), scope 5 // user: %2
return %1 : $(), scope 5 // id: %2
} // end sil function '_TToF4mainU_FT_T_'
// Bool._getBuiltinLogicValue() -> Builtin.Int1
sil [transparent] [fragile] @_TFSb21_getBuiltinLogicValuefT_Bi1_ : $@convention(method) (Bool) -> Builtin.Int1
// Bool.init(_builtinBooleanLiteral : Builtin.Int1) -> Bool
sil [transparent] [fragile] @_TFSbCfT22_builtinBooleanLiteralBi1__Sb : $@convention(method) (Builtin.Int1, @thin Bool.Type) -> Bool
And the final, resulting LLVM IR:
; ModuleID = 'main.ll'
source_filename = "main.ll"
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.9"
@INPUT = external local_unnamed_addr constant i8, align 1
@__swift_reflection_version = linkonce_odr hidden constant i16 1
@llvm.used = appending global [1 x i8*] [i8* bitcast (i16* @__swift_reflection_version to i8*)], section "llvm.metadata"
; Function Attrs: noreturn
define i32 @main(i32, i8** nocapture readnone) local_unnamed_addr #0 {
entry:
%2 = load i1, i1* bitcast (i8* @INPUT to i1*), align 1
tail call void @_TF3AVR7pinModeFT3pinVs5UInt84modeSb_T_(i8 4, i1 %2)
tail call void @_TF3AVR35setupTimerIntervalInterruptCallbackFT20tenthsOfAMillisecondVs6UInt168callbackcT_T__T_(i16 1000, i8* bitcast (void ()* @_TToF4mainU_FT_T_ to i8*))
br label %3
; <label>:3: ; preds = %3, %entry
br label %3
}
declare void @_TF3AVR7pinModeFT3pinVs5UInt84modeSb_T_(i8, i1) local_unnamed_addr #1
declare void @_TF3AVR35setupTimerIntervalInterruptCallbackFT20tenthsOfAMillisecondVs6UInt168callbackcT_T__T_(i16, i8*) local_unnamed_addr #1
; Function Attrs: norecurse nounwind
define linkonce_odr hidden void @_TToF4mainU_FT_T_() #2 {
entry:
ret void
}
attributes #0 = { noreturn "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "target-cpu"="core2" "target-features"="+ssse3,+cx16,+fxsr,+mmx,+x87,+sse,+sse2,+sse3" }
attributes #1 = { "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "target-cpu"="core2" "target-features"="+ssse3,+cx16,+fxsr,+mmx,+x87,+sse,+sse2,+sse3" }
attributes #2 = { norecurse nounwind "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "target-cpu"="core2" "target-features"="+ssse3,+cx16,+fxsr,+mmx,+x87,+sse,+sse2,+sse3" }
!0 = !{i32 1, !"Objective-C Version", i32 2}
!1 = !{i32 1, !"Objective-C Image Info Version", i32 0}
!2 = !{i32 1, !"Objective-C Image Info Section", !"__DATA, __objc_imageinfo, regular, no_dead_strip"}
!3 = !{i32 4, !"Objective-C Garbage Collection", i32 1024}
!4 = !{i32 1, !"Objective-C Class Properties", i32 64}
!5 = !{i32 6, !"Linker Options", !6}
!6 = !{!7, !8}
!7 = !{!"-lswiftCore"}
!8 = !{!"-lobjc"}
!9 = !{i32 1, !"PIC Level", i32 2}
!10 = !{i32 1, !"Swift Version", i32 4}
The problem is ultimately the LLVM back end for the AVR processor cannot handle 64 bit pointers. The Apple developers who studied the problem at WWDC said I'll need to recompile the swift compiler source with a patch to make it 16 bit.
Any help would be greatly appreciated!
Regards,
Carl