Last active
November 17, 2018 07:45
-
-
Save thautwarm/aae87071ee66247e9aed2e1d0e8ce868 to your computer and use it in GitHub Desktop.
compelling variable sized struct in LLVM IR
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
[<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