Whenever more rigorous optimizations are attempted (or even basic ones),
it's usually helpful to know what overall kind of instruction is being
dealt with, in the event certain classes of instructions may be eligible
for optimization.
Moves functions out of the main CMakeLists file into module files that
can just be included whenever necessary. This also uses the CMake
provided variables for enforcing compiler requirements.
In the case when RD === RN, RD was updated before AddOverflow was called
to check for an overflow, resulting in an incorrect state of the Q flag.
This is reapplying a patch from f12578b9ab
that was lost during the 20e253ece2 update
Currently basic block kind of acts like a 'dumb struct' which makes things
a little more verbose to write (as opposed to keeping it all in one place,
I guess). It's also a little wonky conceptually, considering a block is
composed of instructions (i.e. 'contains' them).
So providing accessors that make it act more like a container can make working
with algorithms a little nicer. It also makes the API a little more
defined.
Ideally, the list would be only available through a function, but
currently, the pool allocator is exposed, which seems somewhat odd,
considering the block itself should manage its overall allocations
(with placement new, and regular new), rather than putting that
sanitizing directly on the IR emitter (it should just care about emission,
not block state). However, recontaining that can be followed up with,
as it's very trivial to do.
Makes the name match the standard library equivalents.
C++17 introduces non-member empty() which allows for nicer handling
in generic contexts. May as well make the data structure compatible with
it.
This necessated handling literal versions of the instructions separately
as they had different requirements. The rationale for detecting
unpredictable instructions is because:
a. they are unlikely to be outputted by a well-behaved compiler
b. their behaviour may change between different processors
I would rather unpredictable instructions fail loudly than silently do
approximately the right thing.
The only valid objects to add to the list are those that inherit from
IntrusiveListNode. Therefore anything being added to the list that isn't
inheriting from it will cause compilation to fail.
This generalizes the regular iterator to be compatible with both use
cases. Passing in the list instance directly isn't needed, because the
only way you'd ever get a valid instantiation of an iterator is from a
list instance itself.
GetReturnFromRunCodeAddress is const qualified, so this can accept a const
pointer. This also allows for making the constructor accept a const
pointer as well.
Generalizes MemFnInfo to be compatible with all function types.
Also adds type introspection for arguments, as well as helper templates for the common types supported by all partial specializations.
Considering a HostLocInfo instance houses a std::vector, every time this
function is called can cause a potential heap allocation.
This can be somewhat unnecessary because this function is only used to query
for information we already have.
Considering this is used by several other internal query functions such as
IsRegisterOccupied, IsRegisterAllocated, and IsLastUse, this will result
in better codegen (returning an address is just 3 instructions excluding
the ret instruction for returning, meanwhile heap alloc can be 60+).
This also renames the function to have the same name as its non-const
counterpart, since overloading will just select the correct function
instead of putting that onus on the developer.