mu issueshttps://gitlab.anu.edu.au/groups/mu/-/issues2017-06-11T19:34:41+10:00https://gitlab.anu.edu.au/mu/mu-impl-fast/-/issues/37[x86-64] Passing a 128-bit integer to a C function using CCALL2017-06-11T19:34:41+10:00Isaac Garianoisaac@ecs.vuw.ac.nz[x86-64] Passing a 128-bit integer to a C function using CCALLPassing a 128-bit integer to a C function (ussing CCALL) dosn't work on x86-64, e.g:
I wrote a test to check that 128-bit integers are passed correctly when calling functions (it is designed to cause the last argument to be placed on th...Passing a 128-bit integer to a C function (ussing CCALL) dosn't work on x86-64, e.g:
I wrote a test to check that 128-bit integers are passed correctly when calling functions (it is designed to cause the last argument to be placed on the stack on x86, but on aarch64 it should be in a register).
arg_overflow.uir:
```
.funcsig test_arg_overflow_sig = () -> ()
.funcdef my_main<()->()>
{
entry():
CCALL #DEFAULT <ufuncptr<test_arg_overflow_sig> test_arg_overflow_sig> <ufuncptr<test_arg_overflow_sig>>EXTERN "c_test_arg_overflow" ()
CALL <test_arg_overflow_sig> mu_test_arg_overflow()
RET
}
.funcsig arg_overflow_sig = (int<64> int<128> int<128> int<128>) -> ()
.funcdef mu_test_arg_overflow<test_arg_overflow_sig>
{
entry():
int128_0 = ADD <int<128>> <int<128>>0 <int<128>>0
int128_F = ADD <int<128>> <int<128>>0 <int<128>>0xFFFFFFFFFFFFFFFF0000000000000000
CCALL #DEFAULT <ufuncptr<arg_overflow_sig> arg_overflow_sig> <ufuncptr<arg_overflow_sig>>EXTERN "arg_overflow" (<int<64>>0 int128_0 int128_0 int128_F)
RET
}
```
It needs to be compiled with the following C code:
arg_overflow.c
```
#include <stdint.h>
#include <stdio.h>
void arg_overflow(uint64_t a, __int128_t b, __int128_t c, __int128_t d) {
printf("d = %016lX%016lX\n", (uint64_t)(d >> 64), (uint64_t)d);
}
void c_test_arg_overflow()
{
arg_overflow(0, 0, 0, (__int128_t)(0xFFFFFFFFFFFFFFFF) << 64);
}
```
On x86-64 using the line ` ./muc -r -f my_main arg_overflow.uir arg_overflow/arg_overflow`, (using the latest commit in the aarch64 branch) it fails to compile, giving the error:
```
thread '<unnamed>' panicked at 'not yet implemented', src/compiler/backend/arch/x86_64/inst_sel.rs:3181
stack backtrace:
0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace
at /checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
1: std::sys_common::backtrace::_print
at /checkout/src/libstd/sys_common/backtrace.rs:71
2: std::panicking::default_hook::{{closure}}
at /checkout/src/libstd/sys_common/backtrace.rs:60
at /checkout/src/libstd/panicking.rs:355
3: std::panicking::default_hook
at /checkout/src/libstd/panicking.rs:371
4: std::panicking::rust_panic_with_hook
at /checkout/src/libstd/panicking.rs:549
5: std::panicking::begin_panic
6: mu::compiler::backend::x86_64::inst_sel::InstructionSelection::emit_c_call_ir
7: mu::compiler::backend::x86_64::inst_sel::InstructionSelection::instruction_select
8: <mu::compiler::backend::x86_64::inst_sel::InstructionSelection as mu::compiler::passes::CompilerPass>::visit_function
9: mu::compiler::passes::CompilerPass::execute
10: mu::compiler::Compiler::compile
11: mu::vm::vm::VM::make_boot_image_internal
12: mu::vm::api::api_bridge::_forwarder__MuCtx__make_boot_image
13: main
14: __libc_start_main
15: _start
fatal runtime error: failed to initiate panic, error 5
Aborted (core dumped)
```
On aarch64 it compiles (well Zebu fails at linking, but it works if I add 'arg_overflow.c' to the clang command) and runs correctly, printing:
```
d = FFFFFFFFFFFFFFFF0000000000000000
d = FFFFFFFFFFFFFFFF0000000000000000
```Yi LinYi Linhttps://gitlab.anu.edu.au/mu/mu-impl-fast/-/issues/33Rework on pin/unpin2017-07-19T15:02:01+10:00Yi LinRework on pin/unpinCurrent `PIN`/`UNPIN` directly get translated into a runtime call into GC to pin/unpin the object, which simply push/remove the object reference to/from a root set (synchronisation required). This is inefficient, and also the behaviour i...Current `PIN`/`UNPIN` directly get translated into a runtime call into GC to pin/unpin the object, which simply push/remove the object reference to/from a root set (synchronisation required). This is inefficient, and also the behaviour is different from the spec (in which you need unpin operations to match every pin operation).
This will need rework, probably along with #12 .
And it is also related with https://gitlab.anu.edu.au/mu/mu-spec/issues/7, which proposes to separate immovability and immortal semantics of `PIN` instruction.https://gitlab.anu.edu.au/mu/general-issue-tracker/-/issues/73License2018-06-28T23:11:33+10:00John ZhangLicenseWe have decided to use the Apache 2.0 license for all our code.
The following two commits put forward a draft for the license file.
verbatim: mu/mu-perf-benchmarks@47045501
added ANU copyright: mu/mu-perf-benchmarks@76b1b7ca
If...We have decided to use the Apache 2.0 license for all our code.
The following two commits put forward a draft for the license file.
verbatim: mu/mu-perf-benchmarks@47045501
added ANU copyright: mu/mu-perf-benchmarks@76b1b7ca
If there is no problem, then I will merge the branch into master, and you can all put a copy of the LICENSE file into your project.https://gitlab.anu.edu.au/mu/mu-impl-fast/-/issues/32Calling function defined in another bundle does not work2017-06-07T00:22:48+10:00Isaac Garianoisaac@ecs.vuw.ac.nzCalling function defined in another bundle does not workI am trying to define a function in one bundle, and call it another, and i'm getting an error:
Heres an example that will reproduce the problem:
file argc_exit.uir:
```
.funcsig @exit_sig = (int<32>) -> ()
.funcdef @argc.exit <@...I am trying to define a function in one bundle, and call it another, and i'm getting an error:
Heres an example that will reproduce the problem:
file argc_exit.uir:
```
.funcsig @exit_sig = (int<32>) -> ()
.funcdef @argc.exit <@exit_sig>
{
%entry(<int<32>>%arg):
CCALL #DEFAULT <ufuncptr<@exit_sig> @exit_sig> <ufuncptr<@exit_sig>>EXTERN "exit"(%arg)
RET
}
```
file argc_inline.uir:
```
.typedef %char = int<8>
.funcdef @my_main <(int<32> uptr<uptr<%char>>)->(int<32>)> VERSION @my_main_v1
{
%entry(<int<32>>%argc <uptr<uptr<%char>>>%argv):
CALL <(int<32>)->()> @argc.exit (%argc)
RET <int<32>>1
}
```
Then using my mu-tool-compiler:
`./muc -r -f my_main argc_exit.uir argc_inline.uir emit/argc`
(use -c if you wan't to see the API calls it uses).
`thread '<unnamed>' panicked at 'Operand 1013' is neither a local var or a global var', src/vm/api/api_impl/muirbuilder.rs:1290 stack backtrace:`
(the symbol with Id 1013 is @argc.exit).
I tracked the error down and it appears to be comming from the function `get_treenode` in (src\vm\api\api_impl\muirbuilder.rs).
My guess is the API implementation only looks for things defined in the current bundle and not other bundles.
However from my understanding of the Mu-spec you should be able to refer to entities declared in previously loaded bundles.
A workaround is to combine both files into the same bundle such as with `./muc -r -f my_main <(cat argc_exit.uir && cat argc_inline.uir) emit/argc`.Kunshan WangKunshan Wanghttps://gitlab.anu.edu.au/mu/mu-impl-fast/-/issues/31[x86_64] floating point/int128 conversion2017-06-13T13:38:11+10:00Yi Lin[x86_64] floating point/int128 conversionunimplemented for nowunimplemented for nowYi LinYi Linhttps://gitlab.anu.edu.au/mu/mu-spec/-/issues/13Signature list missing from summary in `common-insts.rst`2018-01-26T04:47:41+11:00Pavel ZakopayloSignature list missing from summary in `common-insts.rst`The top of `common-insts.rst` currently looks like (code below). However, this list does not mention the signature list, which is both a required parameter in the IR-building API (`muapi.h`) and is discussed in later sections of the same...The top of `common-insts.rst` currently looks like (code below). However, this list does not mention the signature list, which is both a required parameter in the IR-building API (`muapi.h`) and is discussed in later sections of the same document (`common-insts.rst`) .
```markdown
**Common Instructions** (sometimes abbreviated as "comminst") are instructions
that have a common format and are used with the ``COMMINST`` super instruction.
They have:
1. An ID and a name. (This means, they are *identified*. See `<ir.rst>`__.)
2. A flag list.
3. A type parameter list.
4. A value parameter list.
5. An optional exception clause.
6. A possibly empty (which means optional) keep-alive clause.
```https://gitlab.anu.edu.au/mu/mu-impl-fast/-/issues/29Implement SWITCH with switch table2017-06-06T15:10:22+10:00Yi LinImplement SWITCH with switch tableCurrently the compiler generates cascading conditional branches for SWITCH instruction. We should consider using switch table if there are many case arms.Currently the compiler generates cascading conditional branches for SWITCH instruction. We should consider using switch table if there are many case arms.https://gitlab.anu.edu.au/mu/general-issue-tracker/-/issues/72Alternative serialisable format (such as JSON/YAML/XML/...)2018-06-28T23:11:33+10:00Kunshan WangAlternative serialisable format (such as JSON/YAML/XML/...)I am glad to see the [mu-tool-compiler](https://gitlab.anu.edu.au/mu/mu-tool-compiler) project existing.
I have conjectured having an alternative serialisable and human-readable format to the current text-based IR. In fact, the text-ba...I am glad to see the [mu-tool-compiler](https://gitlab.anu.edu.au/mu/mu-tool-compiler) project existing.
I have conjectured having an alternative serialisable and human-readable format to the current text-based IR. In fact, the text-based Mu IR is a thing that I am unhappy with. It has various problems.
- It requires a dedicated parser, which has to be implemented by hand.
- When new features are added, the grammar changes, and the parser needs to be modified.
- The text-based IR is confined by aesthetic considerations, and has many inconsistencies. For example:
- The reason why `.funcdef ... <@sig>` has a signature is because it also works as a syntax sugar, using which a human writer only needs to write a `.funcdef` to create both a function and its first version.
- As a convention, types and signatures in Mu instructions are in angular brackets, such as `ADD <@i32> %x %y`. But instructions may have more than types and signatures. One example is `GETFIELDIREF`. It has a integer literal argument. But the current form `GETFIELDIREF <@type 3> %ref` is ugly. The number `3` looks out of place.
I suggest there should be a Mu IR format in a well-known structured data format, such as JSON, YAML, XML, and so on.
Related work:
- LLVM yaml2obj: http://llvm.org/docs/yaml2obj.html
Potential advantages:
- There are mature open-source parsers available.
- Easy to extend.
- Easy to specify (in mu-spec).
For example, if we want to add an externally-usable symbol to an exposed function, we only need to add a property, not redesigning the grammar:
```yaml
name: foo
func: func
callconv: DEFAULT
cookie: cookie
symbol: externally_visible_symbol # This is an added property
```
It is easy to specify because we can define the IR as an (abstract) object tree with properties, similar to [how the HTML5 DOM is defined](https://html.spec.whatwg.org/multipage/dom.html#elements-in-the-dom).
There are also potential disadvantages:
- More verbose
- Less human-readable than the current text form, but human readability should not be the primary concern.
XML example:
```xml
<bundle>
<type id="i8" ctor="int" length="8" /> <!-- note: XML ID is actually a name -->
<type id="i32" ctor="int" length="32" />
<type id="i64" ctor="int" length="64" />
<type id="pi8" ctor="uptr" type="i8" />
<type id="ppi8" ctor="uptr" type="pi8" />
<type id="refi32" kind="ref" type="i32" />
<funcsig id="mainsig" />
<paramty type="i32" />
<paramty type="ppi8" />
<retty type="i32" />
</funcsig>
<const id="I32_42" type="i32" value="42" />
<const id="I64_0" type="i64" value="0" />
<global id="errno" type="i32" />
<funcdecl id="main" sig="mainsig" />
<funcdef func="main" />
<bb lname="entry"> <!-- lname = local name -->
<param type="i32" lname="argc" />
<param type="ppi8" lname="argv" />
<inst opcode="ADD" flags="V" type="i32" opnd1="%argc" opnd2="@I32_42">
<result lname="res" />
<result lname="ovf" />
</inst>
<inst opcode="CALL" sig="some_sig" callee="some_callee">
<arg val="argc" />
<result lname="r1" />
<nor-dest name="bb2">
<pass-value val="r1" />
</nor-dest>
<exc-dest name="bb3" />
</inst>
<inst opcode="SWAPSTACK" swappee="%some_hypothetic_stack">
<return-with>
<result type="i32" lname="ss_res1" />
<result type="i32" lname="ss_res2" />
</return-with>
<pass-values>
<pass-value type="i32" val="%res" />
<pass-value type="i32" val="%r1" />
</pass-valuse>
</inst>
<!-- more instructions here -->
</bb>
<bb lname="bb2">
<param type="i32" lname="r1" />
<!-- more instructions here -->
</bb>
<bb lname="bb3">
<exc-param lname="exc" />
<!-- more instructions here -->
</bb>
</funcdef>
<expose id="exposed_main" symbol="c_callable_symbol_of_exposed_main"
func="main" callconv="DEFAULT" cookie="@I64_0" />
</bundle>
```
A YAML example:
```yaml
types:
- name: i8
ctor: int
length: 8
- {name: "i32", ctor: "int", length: 32}
- {name: "i64", ctor: "int", length: 64}
- {name: "double", ctor: "double"}
function_signatures:
- name: "mainsig"
paramtys: ["i32", "ppi8"]
rettys: ["i32"]
constants:
- {name: "I32_42", type: "i32", value: 42}
- {name: "I64_0", type: "i64", value: 0}
- {name: "D_0", type: "double", value: 0.0}
- name: "D_NAN"
type: "double"
value_from_int: 0x7ff0000000000001
globals:
- {name: "errno", type: "i32"}
functions:
- name: "main"
sig: "main_sig"
initial_version:
- bbname: "entry"
params:
- {type: "i32", lname: "argc"}
- {type: "ppi8", lname: "argv"}
insts:
- {opcode: "ADD", flags: "V", type: "i32", opnd1: "%argc", opnd2: "@I32_42",
results: ["res", "ovf"]}
- opcode: "CALL"
sig: "some_sig"
callee: "some_callee"
args: ["%argc"]
results: ["r1"]
nor_dest:
bb: "bb2"
pass_values: ["%r1"]
exc_dest:
bb: "bb3"
- opcode: "SWAPSTACK"
swappee: "%some_hypothetic_stack"
ret_with:
- {type: "i32", lname: "ss_res1"}
- {type: "i32", lname: "ss_res2"}
pass_value:
- {type: "i32", val: "%res"}
- {type: "i32", val: "%r1"}
# more instructions here
- bbname: "bb2"
params:
- {type: "i32", lname: "r1"}
insts:
# more instructions here
- bbname: "bb2"
excparam: "exc"
insts:
# more instructions here
exposed_functions:
- name: "exposed_main"
symbol: "c_callable_symbol_of_exposed_main"
func: "main"
callconv: "DEFAULT"
cookie: "@I64_0"
```
LISP:
```lisp
(type i8 int 8)
(type i32 int 32)
(type i64 int 64)
(type pi8 ptr i8)
(type ppi8 ptr pi8)
(funcsig mainsig (i32 ppi8) (i32))
(const I32_42 i32 42)
(const I64_0 i64 0)
(global errno i32)
(funcdecl main main_sig)
(funcdef main.v1 main
(bb entry ((i32 argc) (ppi8 argv))
(ADD i32 %argc @I32_42 res
((C carry)
(V ovf)
))
(CALL some_sig some_callee (%argc) (r1)
((bb2 (%r1)) (bb3)))
(SWAPSTACK %some_hypothetic_stack
(ret-with ((i32 ss_res1)
(i64 ss_res2)))
(pass-values ((i32 %res)
(i32 %r1))))
(bb bb2 ((i32 r1))
# More instructions here
)
(bb bb2 (exc)
# More instructions here
)
(expose exposed_main main DEFAULT @I64_0
((symbol "c_callable_symbol_of_exposed_main")))
```https://gitlab.anu.edu.au/mu/mu-spec/-/issues/11Indirect branch2018-01-26T04:47:41+11:00Tony Hoskingantony.hosking@anu.edu.auIndirect branchI notice that the branch instruction is direct (dest must be a block label).
Why don't we support indirect branches?
DO we have a way of emulating with TAILCALL?
I know that the only code addresses that we can talk about in our type syst...I notice that the branch instruction is direct (dest must be a block label).
Why don't we support indirect branches?
DO we have a way of emulating with TAILCALL?
I know that the only code addresses that we can talk about in our type system are function references. So, we don't even have a way to compute code addresses otherwise. In note that LLVM has indirect branch.Kunshan WangKunshan Wanghttps://gitlab.anu.edu.au/mu/mu-spec/-/issues/10Should MuCString be const?2018-01-26T04:47:41+11:00Isaac Garianoisaac@ecs.vuw.ac.nzShould MuCString be const?In muapi.h the type `MuCString` is defined as `typedef char *MuCString`. It is used by some functions such as `gen_sym`, which is often called with a string literal argument. Should we make `MuCString` a typedef for `const char*` as I do...In muapi.h the type `MuCString` is defined as `typedef char *MuCString`. It is used by some functions such as `gen_sym`, which is often called with a string literal argument. Should we make `MuCString` a typedef for `const char*` as I don't believe `gen_sym` (or any other functions that take a `MuCString`) has a reason to modify the parsed string. I am current using muapi.h with C++, and so I haved to use a `const_cast` (which is unsafe, the other alternative is to create a temporary buffer for the string, copy it into the buffer and then free it after the call (this would be perfectly safe but is probably unnecessary)).https://gitlab.anu.edu.au/mu/mu-impl-ref2/-/issues/8Persisting VM flags2018-09-09T12:42:37+10:00John ZhangPersisting VM flags## Problem Description
After `make_boot_image`, I would have thought that the boot image should persist the VM args that were passed when starting the VM. However, the same arguments are still needed to be passed to `runmu.sh` to load...## Problem Description
After `make_boot_image`, I would have thought that the boot image should persist the VM args that were passed when starting the VM. However, the same arguments are still needed to be passed to `runmu.sh` to load the boot image.
I think this is quite inconvenient and counter-intuitive.
Maybe this is some problem that needs to be fixed?https://gitlab.anu.edu.au/mu/mu-perf-benchmarks/-/issues/3Predefined tasks2018-09-14T20:32:48+10:00Zixian CaiPredefined tasksJohn ZhangJohn Zhanghttps://gitlab.anu.edu.au/mu/mu-spec/-/issues/9Void type allocation2018-01-26T04:47:41+11:00John ZhangVoid type allocationJust wondering, does Mu permit `NEW <@void>`?Just wondering, does Mu permit `NEW <@void>`?https://gitlab.anu.edu.au/mu/mu-client-pypy/-/issues/15CCALL a ufuncptr of an exposed Mu function2017-10-05T22:02:34+11:00John ZhangCCALL a ufuncptr of an exposed Mu function### Problem Description
At compile time, when RPython compiler is transforming the CFG into `JIT bytecode`, it creates `JitCode` for the callees of regular calls ([jtransform.py:433](rpython/jit/codewriter/jtransform.py#L433)). In doi...### Problem Description
At compile time, when RPython compiler is transforming the CFG into `JIT bytecode`, it creates `JitCode` for the callees of regular calls ([jtransform.py:433](rpython/jit/codewriter/jtransform.py#L433)). In doing so, it casts the function pointer of the corresponding graph into `Address` ([call.py:183](rpython/jit/codewriter/call.py#L183)), and stores it in the `JitCode` instance ([call.py:168](rpython/jit/codewriter/call.py#L168)). In the blackhole interpreter, it gets the function address, casts it to an integer and passes it to a call instruction ([blackhole.py:1211](rpython/jit/metainterp/blackhole.py#L1211)).
RPython also supports casting a stored function address back to a function pointer to be invoked. This is demonstrated in the following test code snippet I wrote:
``` python
def test_fakeaddress_fncptr():
def f(a, b):
return a + b
def g(a, b):
return a - b
...
fp_f = lltype.getfunctionptr(graph_f)
fp_g = lltype.getfunctionptr(graph_g)
FUNCPTR = lltype.typeOf(fp_f)
fncadrs = map(llmemory.cast_ptr_to_adr, [fp_f, fp_g])
def main(argv):
fncadr = fncadrs[int(argv[1])]
fncptr = rffi.cast(FUNCPTR, fncadr)
print fncptr(int(argv[2]), int(argv[3]))
return 0
```
The code when compiles through the default C back-end runs correctly.
This raises the question on how Mu back-end should handle these cases.
Some issues raised by RPython's practices include:
##### casting a function pointer to data pointer
This is generally not a good practice in C. It is an undefined behaviour according to C standard and is *conditionally supported* in C++11. However, practically it is supported by major compilers on major platforms (the return value of `dlsym()` depends on this to work).
For Mu back-end, however, it may not be necessary to perform such cast. It may be good enough just to store the function reference. But we are limited by the RPython source code. This ultimately reveals another mismatch of assumptions. RPython is built with the philosophy of C and there are many assumptions built-in to the compiler itself (especially JIT, since it was designed to emit machine code).
##### how to get a `ufuncptr` from `funcref`
One way is through exposing the Mu function. Since the described scenario produces the function pointer in a heap object, this can be done statically.
Another potential way is through 'pinning' a Mu function. This is raised in the relevant discussion in Mu Spec issue tracker (mu/mu-spec#8).
##### how to call a `ufuncptr` from within Mu
This touches on the semantic of `CCALL` instruction. From the discussions in mu/mu-spec#8, it seems that we can `CCALL` an exposed Mu function pointer. But at this time the reference implementation has not dealt with this case.
### Current Progress
As mentioned above, relevant issues are raised and discussed in mu/mu-spec#8.
Currently waiting reference implementation to deal with this case.
On the RPython side, most of the work has been done. The back-end now can store a `ufuncptr` as a result of statically exposing a Mu function; when it loads it back at run time, calling it is done through CCALL.
This is achieved through:
- adding a `_muexposedfunc` value type to `mutype.py`;
- modifying `graph_closure` function to add the function graph pointed to by `llmemory.fakeaddress` to the graph closure set;
- type, value and operation translation in `ll2mu`;
- database picking up the exposed function
- code generator to declare the exposed function, and handle the case in heap building.
The code is committed on `mu-rewrite-aot-jitsupport-issue15-ufuncptr-problem` branch, see commit ec1322ee.https://gitlab.anu.edu.au/mu/mu-spec/-/issues/8Calling an exposed Mu function in Mu2018-01-26T04:47:41+11:00John ZhangCalling an exposed Mu function in MuThis problem has been raised before and discussed, but has not been properly documented. How existing (especially reference implementation) handles it also needs to be documented. This thread shall serve these purposes
### Problem Des...This problem has been raised before and discussed, but has not been properly documented. How existing (especially reference implementation) handles it also needs to be documented. This thread shall serve these purposes
### Problem Description
RPython allows casting a function pointer to and from an address. A situation can occur when the code loads a function address, cast it back to a function pointer and calls it.
This poses some problem for Mu because the function is of type `funcref`, and currently `Address` is translated as `uptr<void>`. `ufuncptr` in Mu is specifically for native interface. A Mu function can be 'exposed' to get a `ufuncptr`, but it is expected that it will be called from C rather than from within Mu itself.
What should Mu do in such case? Should the instruction be `CALL` or `CCALL`?
I do acknowledge that the deeper issue is the mismatch of type system assumptions that's built into RPython compiler. Handling it though can be quite tricky.
In previous discussions, Yi did point out that in the Zebu implementation this is not a problem. But I believe that this is a problem for the current reference implementation.https://gitlab.anu.edu.au/mu/mu-impl-ref2/-/issues/7Potential bug in MuIRBuilder.new_exp_func()2018-09-09T12:42:37+10:00John ZhangPotential bug in MuIRBuilder.new_exp_func()### Description
It seems that the function id required in `new_exp_func()` must be defined first before calling it. This is a bit counter-intuitive to the `gen_sym()` first and resolve symbol later API design philosophy we are doing.
...### Description
It seems that the function id required in `new_exp_func()` must be defined first before calling it. This is a bit counter-intuitive to the `gen_sym()` first and resolve symbol later API design philosophy we are doing.
### Code & Error Message
```python
def test_exposed_func():
from rpython.rlib.rmu import holstein as rmu
mu = rmu.MuVM()
ctx = mu.new_context()
bldr = ctx.new_ir_builder()
"""
Builds the following bundle:
.typedef @i64 = int<64>
.const @c_1 <@i64> = 1
.const @c_0 <@i64> = 0
.funcsig @sig_i64_i64 = (@i64) -> (@i64)
.expose @inc_exposed = @inc <DEFAULT> @c_0
.funcdef @inc VERSION @inc.v1 <@sig_i64_i64> {
%blk0(<@i64> %n):
%n_suc = ADD <@i64> %n @c_1
RET (%n_suc)
}
:type rmu: rpython.rlib.rmu.holstein
:type bldr: rpython.rlib.rmu.holstein.MuIRBuilder
:return: None
"""
i64 = bldr.gen_sym('@i64'); bldr.new_type_int(i64, 64)
c_1 = bldr.gen_sym('@c_1'); bldr.new_const_int(c_1, i64, 1)
c_0 = bldr.gen_sym('@c_0'); bldr.new_const_int(c_0, i64, 0)
sig = bldr.gen_sym('@sig_i64_i64'); bldr.new_funcsig(sig, [i64], [i64])
inc = bldr.gen_sym('@inc'); # bldr.new_func(inc, sig) # having it here works
inc_exposed = bldr.gen_sym('@inc_exposed'); bldr.new_exp_func(inc_exposed, inc, rmu.MuCallConv.DEFAULT, c_0)
bldr.new_func(inc, sig) # having it here causes an error
inc_v1 = bldr.gen_sym('@inc.v1')
blk0 = bldr.gen_sym('@inc.blk0')
n = bldr.gen_sym('@inc.blk0.n')
n_suc = bldr.gen_sym('@inc.blk0.n_suc')
op_add = bldr.gen_sym(); bldr.new_binop(op_add, n_suc, rmu.MuBinOptr.ADD, i64, n, c_1)
op_ret = bldr.gen_sym(); bldr.new_ret(op_ret, [n_suc])
bldr.new_bb(blk0, [n], [i64], rmu.MU_NO_ID, [op_add, op_ret])
bldr.new_func_ver(inc_v1, inc, [blk0])
bldr.load()
```
Error message:
```
11:36:01.567 [main] ERROR uvm.refimpl.nat.NativeClientSupport$ - Error thrown in Mu while native is calling MuIRBuilder.load. This is fatal.
uvm.ir.irbuilder.UnknownIDException: MuID 65540 (name: @inc) is not defined. If your Mu IR bundle refers to previously loaded entities, make sure the IDs are correct. If it refers to entities in the current bundle, make sure they have the appropriate types. Also check if all instructions in a basic block are listed in the new_bb's arguments.
at uvm.ir.irbuilder.BundleConstructor$$anonfun$cascadeLookup$1$$anonfun$apply$4.apply(BundleConstructor.scala:35)
at uvm.ir.irbuilder.BundleConstructor$$anonfun$cascadeLookup$1$$anonfun$apply$4.apply(BundleConstructor.scala:33)
at scala.Option.getOrElse(Option.scala:121)
at uvm.ir.irbuilder.BundleConstructor$$anonfun$cascadeLookup$1.apply(BundleConstructor.scala:33)
at uvm.ir.irbuilder.BundleConstructor$$anonfun$cascadeLookup$1.apply(BundleConstructor.scala:33)
at scala.Option.getOrElse(Option.scala:121)
at uvm.ir.irbuilder.BundleConstructor.cascadeLookup(BundleConstructor.scala:32)
at uvm.ir.irbuilder.BundleConstructor.resFunc(BundleConstructor.scala:51)
at uvm.ir.irbuilder.BundleConstructor$$anonfun$uvm$ir$irbuilder$BundleConstructor$$_resFunc$1$1.apply(BundleConstructor.scala:78)
at uvm.ir.irbuilder.BundleConstructor$$anonfun$uvm$ir$irbuilder$BundleConstructor$$_resFunc$1$1.apply(BundleConstructor.scala:78)
at uvm.ir.irbuilder.BundleConstructor$$anonfun$makeBundle$5.apply(BundleConstructor.scala:185)
at uvm.ir.irbuilder.BundleConstructor$$anonfun$makeBundle$5.apply(BundleConstructor.scala:172)
at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59)
at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48)
at uvm.ir.irbuilder.BundleConstructor.makeBundle(BundleConstructor.scala:172)
at uvm.ir.irbuilder.IRBuilder.makeBundle(IRBuilder.scala:79)
at uvm.ir.irbuilder.IRBuilder.load(IRBuilder.scala:83)
at uvm.refimpl.nat.CDefs$$anonfun$96.apply(cStubs.scala:1022)
at uvm.refimpl.nat.CDefs$$anonfun$96.apply(cStubs.scala:1019)
at uvm.refimpl.nat.SimpleClosure.invoke(cStubsHelperFunctions.scala:29)
at com.kenai.jffi.ClosurePool$Proxy.invoke(ClosurePool.java:334)
```Kunshan WangKunshan Wanghttps://gitlab.anu.edu.au/mu/mu-client-pypy/-/issues/14Translation fails on mu-rewrite-aot-jitsupport with -Ojit2018-06-18T22:18:37+10:00Timm Allmantallman@cs.umass.eduTranslation fails on mu-rewrite-aot-jitsupport with -OjitI can't commit to mu-rewrite-aot-jitsupport so code is on mu-jit-2.
Translation fails in a bunch of places looking for attributes that don't exist.I can't commit to mu-rewrite-aot-jitsupport so code is on mu-jit-2.
Translation fails in a bunch of places looking for attributes that don't exist.Zixian CaiZixian Caihttps://gitlab.anu.edu.au/mu/mu-spec/-/issues/7Separation of immovability and immortality in `@uvm.native.pin` instruction2018-01-26T04:47:41+11:00John ZhangSeparation of immovability and immortality in `@uvm.native.pin` instruction## Problem Description
Currently `@uvm.native.pin` instruction bestows both immovability (not able to move) and immortality (kept alive) on the pinned object. However some times we might only want an object to be immovable but can sti...## Problem Description
Currently `@uvm.native.pin` instruction bestows both immovability (not able to move) and immortality (kept alive) on the pinned object. However some times we might only want an object to be immovable but can still be collected by the GC.
This need was raised in mu/mu-client-pypy#10. When an object `p` in PyPy heap (Mu heap) is bound to an object `o` in C (`CCALL malloc`), `p` is pinned and `o` keeps the address of `p` as an integer, and the reference count on `o` is set to a special value to mark this bounding. PyPy's GC, however, can still collect `p`, and it has different implications on `o` depending on the reference count. This behaviour is currently not supported in Mu. The current semantic of `@uvm.native.pin` can result in memory leak as `p` is never collected.
Currently the spec doesn't seem to have a very clear specification on this issue. In mu/general-issue-tracker#28 it is mentioned that the pointer **can be used** until the object is unpinned. This does imply both immovability and immortality until a corresponding `@uvm.native.unpin` instruction. This should be clarified further in the spec.
This does raise the problem of pointer validity. If an object is pinned with the option of being mortal, when it is collected, the pointer become invalid. Do we just then push the responsibility to the client and say that the client must know what they are doing and must not access an invalid pointer in this way?
## Proposed change
Add an optional flag to `@uvm.native.pin` instruction to allow mortal pinning:
```
[0x240]@uvm.native.pin [#MORTAL] <T> (%opnd: T) -> uptr<U>
```
- The presence of the flag `#MORTAL` allows the pinned object to be collected by the GC when it becomes unreachable. When the object is collected, all derived `uptr`s become invalid.https://gitlab.anu.edu.au/mu/general-issue-tracker/-/issues/70Debugging facilities for Mu clients2018-06-28T23:11:33+10:00Zixian CaiDebugging facilities for Mu clientshttps://gitlab.anu.edu.au/mu/mu-impl-ref2/-/issues/5Migrating to Scala 2.122018-09-09T12:42:37+10:00Kunshan WangMigrating to Scala 2.12As of April 2017, the official stable version of Scala is 2.12.2. Currently, Holstein is implemented on Scala 2.11.x, which is now a legacy version.
I have tested locally that there is no problem switching to 2.12.x.As of April 2017, the official stable version of Scala is 2.12.2. Currently, Holstein is implemented on Scala 2.11.x, which is now a legacy version.
I have tested locally that there is no problem switching to 2.12.x.