Create helpers to split the block at the current insertion point and to
replace one instruction with another. The logic to do this was inline in
insertConditionalPointBlock, but `invoke` insertion will need to do the
same things.
gc.safepoint_poll() helper required by Safepoint placement pass was an
empty function. This change fixes this to call the correct runtime helper
to perform the CLR GC Poll.
The current strategy is to use an unconditional call to the GCPoll helper.
Inlining the GCPoll helper is future work.
Issue #32
LLVM's support for calling conventions does not handle aggregate
parameters or return values in a way that is consistent with the
rules for a particular calling convention. Instead of applying
whatever rules are particular to a given calling convention, it
simply recursively decomposes aggregates into a linear sequence
of arguments of non-aggregate type. It is the frontend's
responsibility, then, to emit calls such that the backend will
lower them appropriately for the target calling convention.
Practically speaking, this means that the frontend must do the
work to determine how each argument to a function--aggregate or
otherwise--should be passed (e.g. directly/indirectly, as an
expanded series of arguments, etc.) when generating calls and
function symbols. To this end, this change adds abstractions
to encapsulate ABI information and compute argument and result
passing information for a function signature (i.e. a calling
convention, result type, and argument types). These abstractions
are then used to emit function calls, home method arguments, and
return method results in a way that is compatible with the
backend.
When storing an element of struct type we call rdrCallWriteBarrierHelper.
We were passing array address instead of element address as the first argument.
This resulted in bad codegen when compiling Roslyn.
Change the return type of genArrayElemAddress from Value * to IRNode * and
eliminate a few casts.
Remove some unnecessary semicolons and fix a comment typo.
Update python filter with the following changes. These chagnes are needed to
allow applying filter easily from runtest.py.
1. Add ApplyAll to apply filter recursively on a directory.
2. Wrap the original functionality into ApplyOne.
3. Make script applyfilter main function to use ApplyOne to make it compatbile with before
4. Command line parsing added.
Set the GC strategy on the generated function to "statepoint-example"
only if the JitContext specifies using precise GC.
Also fixed format-spacing
Rename safepoint_poll creation method to createSafepointPoll()
Allocate a local to hold the security object. Zero initialize it and then pass it's address to the prolog helper.
Ultimately we'll need to ensure this slot stays alive and also report it in the GC info.
For interior pointers, the CLR Runtime doesn't require the base-pointer
to be additionally reported explicitly. Therefore, this change turns off
base-pointer tracking and reporting at a statepoint.
This change also solves an issue with alloca sequence, where we make a
unmanaged to managed pointer cast.
For example, for ldloca, we generate
%loc1 = alloca i8
%1 = addrspacecast i8* %loc1 to i8 addrspace(1)*
With Base-pointer tracking the set of live poionters after these instructions
would be {%1, %loc} which is clearly wrong because %loc1 is an
unmanaged pointer i8*.
Without base-pointer tracking, the live set is correctly computed as {%loc1}
This change implementats the insertion and lowering of GC-Statepoints
into the code generated by LLILC.
When not using Conservative GC (COMPLUS_GCCONSERVATICE != 1), the Jit
1)Runs PlaceSafePoints and RewriteStatepointsForGC passes before the
code generation phases
2) Annotates the generated functions with gc “statepoint example”
3) Emits the special @gc.safepoint_poll() helper function into the module
along with the function being Jitted. This helper is required by
the PlaceSafePoints phase.
Testing:
This is a work in progress, there are some failures in
RewriteStatepointsForGC due to incorrect live-sets.
LLILC Issue: #32
There's a JitConfig setting JitLockWrite that should force the jit to emit lock prefixed stores for volatiles, but RyuJit doesn't look at this. So we'll also ignore it for now. Issue #278 will remain open to track implementing the option, if we decide to do so.
Instead just allow volatile stores to lower normally (with IsVolatile true in LLVM IR).
When merging operand stacks the types of the corresponding values may be
different. The CLI spec allows merging of nativeint and int32 (resulting in nativeint),
float and double (resulting in double), and GC pointers (resulting in the closest
common supertype).
In order to be able to use JitInfo->mergeClasses (that handles finding closest common
supertype) we need to be able to map back from llvm types to class handles. I added
ReverseClassTypeMap for that.
Since our processing of basic blocks depends on the types of values on the stack we
need to complete stack merging and finalize PHI instructions before processing
join blocks. To do that I changes the order of flow graph processing from depth-first
preorder to reverse postorder.
Closes#373.
Delete the LLVM EE when we're done jitting a method. This gets back most of the memory we allocate and brings our leaking down to a much more tolerable level.
Type the result of ldvirtfn as native int so that subsequent processing handles it the same as other function addresses.
Trim type array in the varargs constructor call path so the LLVM function type builder is not confused.
Add extra paranoia around ldlen and strlen since we see cases where the referent type is not an array or string. For now bail out if we hit one of these.
if we see an endfinally and can't locate the enclosing EH region, bail out with an NYI rather than AVing in the jit.
Add a type that encapsulates the method signature and other relevant
details about the method being compiled. This lets us bring some logic
down into ReaderBase from GenIR and eliminates some code that would
otherwise need to be kept in sync between ReaderBase and its subclasses.
This is another step on the road to value type return values and parameters.
This addresses a couple of issues seen in the Roslyn bring-up.
In `readerPrePass`, split the current block after the parameter stores and local allocas and other
"run once on entry to the method" IR. The continuation block from this split is the block that corresponds
to MSIL offset 0 and is also the target of branches back to offset 0. Remember this block and
in `fgPrePhase` return it as the first block to use when expanding MSIL to IR.
Implement the just my code hook, which requires a conditional branch in this "entry IR" sequence.
Closes#272, closes#372.
- Move newobj canonicalization out of GenIR and into ReaderBase.
- Refactor rdrCall such that canonicalization occurs before genCall runs.
- Add ReaderCallSignature to encapsulate runtime call signatures.
Taken together, these changes allow ReaderBase to generate accurate
function types for call targets in rdrCall, thus enabling the removal of
a number of post-processing steps in genCall that impede value-type
returns and parameters.
There is also a small bugfix for createTemporary, which was attempting to
set the insertion point to an invalid location in the cast that the entry
block was entirely empty.
ICastable is a new test (to us) and is failing. Disable it until we can
investigate. This enables the lab with the current set of tests with
the up todate CoreCLR.
This changes allows people that haven't been 'sourcing' the file before
to operate in the same way. Just a convience until this script is
replaced in the near term.
Modified pointers to CoreCLR binaries and tests assets to point at a
live CoreCLR enlistment. Currently I can run 'runtest' with a CoreCLR
enlistment refered to by an environment variable 'CoreCLRSource' that
points at a 'coreclr' directory.