Skip to content

Instantly share code, notes, and snippets.

@thautwarm
Last active November 17, 2018 07:45
Show Gist options
  • Save thautwarm/aae87071ee66247e9aed2e1d0e8ce868 to your computer and use it in GitHub Desktop.
Save thautwarm/aae87071ee66247e9aed2e1d0e8ce868 to your computer and use it in GitHub Desktop.
compelling variable sized struct in LLVM IR
[<Fact>]
let ``nested push32`` () =
let var = ref None
let var2 = ref None
let var3 = ref None
let arg1 = ref <| Some "arg1"
let arg2 = ref <| Some "arg2"
let type_here = Push32 <| I 32
// now we intro the push32 type who's variable-sized!
let type_here = Push32 <| type_here
// let's design a vivid case:
// head: i32 = 2
// - subhead1: i32 = 3
// 1 : i32
// 2 : i32
// 3 : i32
// - subhead2: i32 = 2
// 1 : i32
// 2 : i32
// the size of them (in bytes) is
// 3 * 4(3 i32 heads) + 5 * 4(3 + 2 elems) = 32
// so we should allocate 32/4 = 8
let num = 8
let body = Suite [
// allocate 2 to gain a 12-bytes memory piece(4 + 8).
Tmp(var, Alloca(type_here, Some num))
//prepare data
Let(var2,
Bitcast(Get var, Ptr <| I 32),
let prepare_data a b =
Store(GEP(Get var2, integer 32 a, []),
integer 32 b)
Suite [
prepare_data 0 2 // head = 2
prepare_data 1 3 // subhead1 = 3
prepare_data 2 10 // subhead[1] = 10
prepare_data 3 20 // subhead[2] = 20
prepare_data 4 30 // subhead[3] = 30
prepare_data 5 2 // subhead2 = 2
prepare_data 6 40 // subhead2[1] = 40
prepare_data 7 50 // subhead2[2] = 50
])
(let index_fst_level =
GEPEx(Get var, integer 32 0, Some <| Get arg1)
let index_snd_level =
GEPEx(index_fst_level, integer 32 0, Some <| Get arg2)
Load index_snd_level)
]
let defun = Defun("my_func2", ["arg1", I 32; "arg2", I 32], I 32, body)
let defun = Suite [
Decl("printf", [Ptr <| I 8; I 32], I 32)
defun
]
let my_module =
try
h.compile defun
|> h.Parse
with LLException e ->
failwithf "%A" e
//h.Optimize my_module
//printf1 "%A" my_module
h.Load my_module
let fp = h.FindSymbol "my_func2"
let f = Marshal.GetDelegateForFunctionPointer(fp.Address, typeof<intint2int>) :?> intint2int
for i = 0 to 1 do
for j = 0 to 2 do
printf1 "%d\n" <| f.Invoke(i, j)
let res = f.Invoke(0, 0) //subhead1[1]
Assert.Equal(res, 10)
let res = f.Invoke(0, 1) //subhead1[2]
Assert.Equal(res, 20)
let res = f.Invoke(0, 2) //subhead1[3]
Assert.Equal(res, 30)
let res = f.Invoke(1, 0) //subhead2[1]
Assert.Equal(res, 40)
let res = f.Invoke(1, 1) //subhead2[2]
Assert.Equal(res, 50)
h.Unload my_module
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment