Zenを使ってみた4

 Zenを使ってみた3でLLVM-IRの時点でadd関数が消えてしまったのは、i16にしても、消えていた。

 関数にexportを付けるとLLVM-IRに関数を吐き出すようなので物は試しでwrapperを作ることにした。

export fn add_wrapper(a: i16, b: i16)
i16
{
    var a_wrapper: i15 = @intCast(i15, a);
    var b_wrapper: i15 = @intCast(i15, b);
    return add(a_wrapper, b_wrapper);
}

fn add(a: i15, b: i15)
i15
{
  var c: i15 = 0;

  c = a + b;

  return c;
}

 これでCソースコードからZenを呼び出して、Zenの内部は15bitで使えるコードをエラーを出さずに作れるはず・・・。

$ zen build-obj -target wasm32-freestanding-none --emit llvm-ir add.zen 

 できあがったLLVM-IRは・・・

; ModuleID = 'add'
source_filename = "add"
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
target triple = "wasm32-unknown-unknown-unknown"

%"[]u8" = type { i8*, i32 }
%std.builtin.StackTrace = type { i32, %"[]usize" }
%"[]usize" = type { i32*, i32 }

@panic = internal unnamed_addr constant void (%"[]u8"*, %std.builtin.StackTrace*)* @std.builtin.default_panic, align 4
@os = internal unnamed_addr constant i6 0, align 1
@0 = internal unnamed_addr constant [27 x i8] c"integer cast truncated bits", align 1
@1 = internal unnamed_addr constant %"[]u8" { i8* getelementptr inbounds ([27 x i8], [27 x i8]* @0, i32 0, i32 0), i32 27 }, align 4
@2 = internal unnamed_addr constant [16 x i8] c"integer overflow", align 1
@3 = internal unnamed_addr constant %"[]u8" { i8* getelementptr inbounds ([16 x i8], [16 x i8]* @2, i32 0, i32 0), i32 16 }, align 4

; Function Attrs: cold nobuiltin noreturn nounwind
define internal fastcc void @std.builtin.default_panic(%"[]u8"* nonnull readonly align 4, %std.builtin.StackTrace* align 4) unnamed_addr #0 {
Entry:
  %error_return_trace = alloca %std.builtin.StackTrace*, align 4
  store %std.builtin.StackTrace* %1, %std.builtin.StackTrace** %error_return_trace, align 4
  br label %WhileCond

WhileCond:                                        ; preds = %WhileCond, %Entry
  call void @llvm.debugtrap()
  br label %WhileCond
}

; Function Attrs: nounwind
declare void @llvm.debugtrap() #1

; Function Attrs: nobuiltin nounwind
define i16 @add_wrapper(i16, i16) #2 {
Entry:
  %a_wrapper = alloca i15, align 2
  %b_wrapper = alloca i15, align 2
  %a = alloca i16, align 2
  %b = alloca i16, align 2
  store i16 %0, i16* %a, align 2
  store i16 %1, i16* %b, align 2
  %2 = load i16, i16* %a, align 2
  %3 = trunc i16 %2 to i15
  %4 = sext i15 %3 to i16
  %5 = icmp eq i16 %2, %4
  br i1 %5, label %CastShortenOk, label %CastShortenFail

CastShortenOk:                                    ; preds = %Entry
  store i15 %3, i15* %a_wrapper, align 2
  %6 = load i16, i16* %b, align 2
  %7 = trunc i16 %6 to i15
  %8 = sext i15 %7 to i16
  %9 = icmp eq i16 %6, %8
  br i1 %9, label %CastShortenOk1, label %CastShortenFail2

CastShortenFail:                                  ; preds = %Entry
  call fastcc void @std.builtin.default_panic(%"[]u8"* @1, %std.builtin.StackTrace* null)
  unreachable

CastShortenOk1:                                   ; preds = %CastShortenOk
  store i15 %7, i15* %b_wrapper, align 2
  %10 = load i15, i15* %a_wrapper, align 2
  %11 = load i15, i15* %b_wrapper, align 2
  %12 = call fastcc i15 @add(i15 %10, i15 %11)
  %13 = sext i15 %12 to i16
  ret i16 %13

CastShortenFail2:                                 ; preds = %CastShortenOk
  call fastcc void @std.builtin.default_panic(%"[]u8"* @1, %std.builtin.StackTrace* null)
  unreachable
}

; Function Attrs: nobuiltin nounwind
define internal fastcc i15 @add(i15, i15) unnamed_addr #2 {
Entry:
  %c = alloca i15, align 2
  %a = alloca i15, align 2
  %b = alloca i15, align 2
  store i15 %0, i15* %a, align 2
  store i15 %1, i15* %b, align 2
  store i15 0, i15* %c, align 2
  %2 = load i15, i15* %a, align 2
  %3 = load i15, i15* %b, align 2
  %4 = call { i15, i1 } @llvm.sadd.with.overflow.i15(i15 %2, i15 %3)
  %5 = extractvalue { i15, i1 } %4, 0
  %6 = extractvalue { i15, i1 } %4, 1
  br i1 %6, label %OverflowFail, label %OverflowOk

OverflowFail:                                     ; preds = %Entry
  call fastcc void @std.builtin.default_panic(%"[]u8"* @3, %std.builtin.StackTrace* null)
  unreachable

OverflowOk:                                       ; preds = %Entry
  store i15 %5, i15* %c, align 2
  %7 = load i15, i15* %c, align 2
  ret i15 %7
}

; Function Attrs: nounwind readnone speculatable
declare { i15, i1 } @llvm.sadd.with.overflow.i15(i15, i15) #3

attributes #0 = { cold nobuiltin noreturn nounwind "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" }
attributes #1 = { nounwind }
attributes #2 = { nobuiltin nounwind "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" }
attributes #3 = { nounwind readnone speculatable }

!llvm.module.flags = !{!0, !1}
!llvm.dbg.cu = !{!2}

!0 = !{i32 2, !"Debug Info Version", i32 3}
!1 = !{i32 2, !"Dwarf Version", i32 4}
!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "zen 0.8.20191124", isOptimized: false, runtimeVersion: 0, emissionKind: NoDebug, enums: !4)
!3 = !DIFile(filename: "add", directory: ".")
!4 = !{!5}
!5 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "std.target.Os", scope: !6, file: !6, line: 12, baseType: !7, size: 6, align: 8, elements: !8)
!6 = !DIFile(filename: "target.zen", directory: "/home/hidemi/workspace/zen/zen-linux-x86_64-0.8.20191124+552247019/lib/zen/std")
!7 = !DIBasicType(name: "u6", size: 8, encoding: DW_ATE_unsigned)
!8 = !{!9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, !37, !38, !39, !40, !41, !42, !43, !44, !45}
!9 = !DIEnumerator(name: "freestanding", value: 0)
!10 = !DIEnumerator(name: "ananas", value: 1)
!11 = !DIEnumerator(name: "cloudabi", value: 2)
!12 = !DIEnumerator(name: "dragonfly", value: 3)
!13 = !DIEnumerator(name: "freebsd", value: 4)
!14 = !DIEnumerator(name: "fuchsia", value: 5)
!15 = !DIEnumerator(name: "ios", value: 6)
!16 = !DIEnumerator(name: "kfreebsd", value: 7)
!17 = !DIEnumerator(name: "linux", value: 8)
!18 = !DIEnumerator(name: "lv2", value: 9)
!19 = !DIEnumerator(name: "macosx", value: 10)
!20 = !DIEnumerator(name: "netbsd", value: 11)
!21 = !DIEnumerator(name: "openbsd", value: 12)
!22 = !DIEnumerator(name: "solaris", value: 13)
!23 = !DIEnumerator(name: "windows", value: 14)
!24 = !DIEnumerator(name: "haiku", value: 15)
!25 = !DIEnumerator(name: "minix", value: 16)
!26 = !DIEnumerator(name: "rtems", value: 17)
!27 = !DIEnumerator(name: "nacl", value: 18)
!28 = !DIEnumerator(name: "cnk", value: 19)
!29 = !DIEnumerator(name: "aix", value: 20)
!30 = !DIEnumerator(name: "cuda", value: 21)
!31 = !DIEnumerator(name: "nvcl", value: 22)
!32 = !DIEnumerator(name: "amdhsa", value: 23)
!33 = !DIEnumerator(name: "ps4", value: 24)
!34 = !DIEnumerator(name: "elfiamcu", value: 25)
!35 = !DIEnumerator(name: "tvos", value: 26)
!36 = !DIEnumerator(name: "watchos", value: 27)
!37 = !DIEnumerator(name: "mesa3d", value: 28)
!38 = !DIEnumerator(name: "contiki", value: 29)
!39 = !DIEnumerator(name: "amdpal", value: 30)
!40 = !DIEnumerator(name: "hermit", value: 31)
!41 = !DIEnumerator(name: "hurd", value: 32)
!42 = !DIEnumerator(name: "wasi", value: 33)
!43 = !DIEnumerator(name: "emscripten", value: 34)
!44 = !DIEnumerator(name: "zen", value: 35)
!45 = !DIEnumerator(name: "uefi", value: 36)

 おっ、ちゃんと関数も残ってるし、いい感じにできましたよ♪

write: 2019/11/25/ 22:59:09