summary refs log tree commit diff
path: root/amd64
AgeCommit message (Collapse)Author
2022-03-08flag types defined as unionsQuentin Carbonneaux
The risc-v abi needs to know if a type is defined as a union or not. We cannot use nunion to obtain this information because the risc-v abi made the unfortunate decision of treating union { int i; } differently from int i; So, instead, I introduce a single bit flag 'isunion'.
2022-03-08cosmeticsQuentin Carbonneaux
2022-02-02shared linkage logic for func/dataQuentin Carbonneaux
2022-01-28amd64/isel: nitsQuentin Carbonneaux
2022-01-28implement float -> unsigned castsBor Grošelj Simić
amd64 lacks instruction for this so it has to be implemented with float -> signed casts. The approach is borrowed from llvm.
2022-01-28implement unsigned -> float castsBor Grošelj Simić
amd64 lacks an instruction for this so it has to be implemented with signed -> float casts: - Word casting is done by zero-extending the word to a long and then doing a regular signed cast. - Long casting is done by dividing by two with correct rounding if the highest bit is set and casting that to float, then adding 1 to mantissa with integer addition
2022-01-23Add a negation instructionEyal Sawady
Necessary for floating-point negation, because `%result = sub 0, %operand` doesn't give the correct sign for 0/-0.
2021-11-22reuse previous address constants in fold()Michael Forney
parseref() has code to reuse address constants, but this is not done in other passes such as fold or isel. Introduce a new function newcon() which takes a Con and returns a Ref for that constant, and use this whenever creating address constants. This is necessary to fix folding of address constants when one operand is already folded. For example, in %a =l add $x, 1 %b =l add %a, 2 %c =w loadw %b %a and %b were folded to $x+1 and $x+3 respectively, but then the second add is visited again since it uses %a. This gets folded to $x+3 as well, but as a new distinct constant. This results in %b getting labeled as bottom instead of either constant, disabling the replacement of %b by a constant in subsequent instructions (such as the loadw).
2021-11-08amd64: avoid reading past end of passed structMichael Forney
If the size of the struct is not a multiple of 8, the actual struct size may be different from the size reserved on the stack. This fixes the case where the struct is passed in memory, but we still may over-read a struct passed in registers. A TODO is added for now.
2021-10-22make variadic args explicitQuentin Carbonneaux
Some abis, like the riscv one, treat arguments differently depending on whether they are variadic or not. To prepare for the upcomming riscv target, we change the variadic call syntax and give meaning to the location of the '...' marker. # new syntax %ret =w call $f(w %regular, ..., w %variadic) By nature of their abis, the change is backwards compatible for existing targets.
2021-10-17amd64/sysv: unbreak env callsQuentin Carbonneaux
Env calls were disfunctional from the start. This fixes them on amd64, but they remain to do on arm64. A new test shows how to use them.
2021-10-13add size suffix to frame setup.Andrew Chambers
2021-08-29amd64/isel: fix floating point == and != result with NaNMichael Forney
On x86_64, ucomis[sd] sets ZF=1, PF=0, CF=0 for equal arguments. However, if the arguments are unordered it sets ZF=1, PF=1, CF=1, and there is no jump/flag instruction for ZF=1 & PF=0 or ZF=1 & CF=0. So, in order to correctly implement ceq[sd] on x86_64, we need to be a bit more creative. There are several options available, depending on whether the result of ceq[sd] is used with jnz, or with other instructions, or both. If the result is used for a conditional jump, both gcc and clang use a combination of jp and jnz: ucomisd %xmm1, %xmm0 jp .Lfalse jnz .Lfalse ... .Lfalse: If the result is used in other instructions or return, gcc does the following for x == y: ucomisd %xmm1, %xmm0 setnp %al movzbl %al, %eax movl $0, %edx cmovne %edx, %eax This sets EAX to PF=0, then uses cmovne to clear it if ZF=0. It also takes care to avoid clobbering the flags register in case the result is also used for a conditional jump. Implementing this approach in QBE would require adding an architecture-specific instruction for cmovne. In contrast, clang does an additional compare, this time using cmpeqsd instead of ucomisd: cmpeqsd %xmm1, %xmm0 movq %xmm0, %rax andl $1, %rax The cmpeqsd instruction doas a floating point equality test, setting XMM0 to all 1s if they are equal and all 0s if they are not. However, we need the result in a non-XMM register, so it moves the result back then masks off all but the first bit. Both of these approaches are a bit awkward to implement in QBE, so instead, this commit does the following: ucomisd %xmm1, %xmm0 setz %al movzbl %al, %eax setnp %cl movzbl %cl, %ecx andl %ecx, %eax This sets the result by anding the two flags, but has a side effect of clobbering the flags register. This was a problem in one of my earlier patches to fix this issue[0], in addition to being more complex than I'd hoped. Instead, this commit always leaves the ceq[sd] instruction in the block, even if the result is only used to control a jump, so that the above instruction sequence is always used. Then, since we now have ZF=!(ZF=1 & PF=0) for x == y, or ZF=!(ZF=0 | PF=1) for x != y, we can use jnz for the jump instruction. [0] https://git.sr.ht/~sircmpwn/qbe/commit/64833841b18c074a23b4a1254625315e05b86658
2021-08-27amd64/isel: fix floating < and <= result with NaNMichael Forney
When the two operands are Unordered (for instance if one of them is NaN), ucomisd sets ZF=1, PF=1, and CF=1. When the result is LessThan, it sets ZF=0, PF=0, and CF=1. However, jb[e]/setb[e] only checks that CF=1 [or ZF=1] which causes the result to be true for unordered operands. To fix this, change the operand swap condition for these two floating point comparison types: always rewrite x < y as y > x, and never rewrite x > y as y < x. Add a test to check the result of cltd, cled, cgtd, cged, ceqd, and cned with arguments that are LessThan, Equal, GreaterThan, and Unordered. Additionally, check three different implementations for equality testing: one that uses the result of ceqd directly, one that uses the result to control a conditional jump, and one that uses the result both as a value and for a conditional jump. For now, unordered equality tests are still broken so they are disabled.
2021-08-23amd64/emit.c: fix %x =k sub %x, %xEyal Sawady
The negate trick is unnecessary and broken when the first arg is the result.
2021-07-30err when an address contains a sum $a+$b (afl)Quentin Carbonneaux
Reported by Alessandro Mantovani. These addresses are likely bogus, but they triggered an unwarranted assertion failure. We now raise a civilized error.
2021-07-28handle fast locals in amd64 shifts (afl)Quentin Carbonneaux
Reported by Alessandro Mantovani. Although unlikely in real programs it was found that using the address of a fast local in amd64 shifts triggers assertion failures. We now err when the shift count is given by an address; but we allow shifting an address.
2021-07-28fix amd64 addressing selection bug (afl)Quentin Carbonneaux
Reported by Alessandro Mantovani. Unlikely to be hit in practice because we don't add addresses to addresses. type :biggie = { l, l, l } function $repro(:biggie %p) { @start %x =l add %p, $a storew 42, %x ret }
2021-06-17amd64: fix conditional jump when compare is swapped and used elsewhereMichael Forney
selcmp may potentially swap the arguments and return 1 indicating that the opposite operation should be used. However, if the compare result is used for a conditional jump as well as elsewhere, the original compare op is used instead of the opposite. To fix this, add a check to see whether the opposite compare should be used, regardless of whether selcmp() is done now, or later on during sel(). Bug report and test case from Charlie Stanton.
2021-03-18spill: use stronger assertion for registers in use at start of functionMichael Forney
2020-08-06amd64: Use member class for aggregate parameter temporaryMichael Forney
Otherwise, we may end up using an integer and floating class for the same register, triggering an assertion failure: qbe: rega.c:215: pmrec: Assertion `KBASE(pm[i].cls) == KBASE(*k)' failed. Test case: type :T = { s } export function $d(:T %.1, s %.2) { @start call $c(s %.2) ret }
2020-08-06Use a dynamic array for phi argumentsMichael Forney
2019-05-15Allow specifying literal global namesMichael Forney
2019-05-05revert last commitQuentin Carbonneaux
The same functionality can be implemented naturally in the cfg simplification pass.
2019-05-04emit only one epilog per functionQuentin Carbonneaux
Previously, each ret would lead to an epilog. This caused bloat for large functions with multiple return points.
2019-04-30isel fix for amd64 memory storesQuentin Carbonneaux
The value argument of store instructions was handled incorrectly.
2019-04-29amd64: Use unordered compare for floating pointsMichael Forney
This prevents an FE_INVALID exception when comparing with NaN.
2019-04-26amd64/isel: Error if alloc size doesn't fit in Tmp slot typeMichael Forney
2019-04-26restore some code from b4a98cQuentin Carbonneaux
I had forgotten that %rip can only be used as base when there is no index. I also added a test which stresses addressing selection with and without constants.
2019-04-25cleanup amd64 constant addressingQuentin Carbonneaux
We now emit correct code when the user refers to a specific constant address. I also made some comments clearer in the instruction selection pass and got rid of some apparently useless code.
2019-04-17avoid some gcc warningsQuentin Carbonneaux
In this case, the potential truncations flagged by gcc are only affecting debug information.
2019-04-15handle big constants moves to slotsQuentin Carbonneaux
There is no flavor of mov which can set 8 bytes of memory to a constant not representable as an int32. The solution is simply to emit two movs of 4 bytes each.
2019-03-14Rearrange the fields in Ins so the bit-fields get packed togetherMichael Forney
2019-03-12emit valid code for mem->mem copiesQuentin Carbonneaux
2019-02-25prefer bigger amd64 addressingQuentin Carbonneaux
Before, amatch() would prefer matching "o + b" to "o + s*i" and "b + s*i".
2019-02-21fix amd64 addressing mode matcherQuentin Carbonneaux
The numberer made some arranging choices when numbering arguments of an instruction, but these decisions were ignored when matching. The fix is to reconcile numbering and matching.
2019-02-21amd64: Fix typo in truncd instructionMichael Forney
2018-04-26more compiler warnings...Quentin Carbonneaux
2018-04-26Fix compiler warnings.Emil Skoeldberg
Compiler warned about comparison between signed and unsigned values.
2017-07-30fix dynamic stack allocs for amd64Quentin Carbonneaux
The arm64 might have the same problem but it is currently unable to handle them even in instruction selection. Thanks to Jean Dao for reporting the bug.
2017-06-06fix fp subtractions on amd64Quentin Carbonneaux
The stashing of constants in gas.c was also changed to support 16-bytes constants.
2017-06-06fix floating-point divisionQuentin Carbonneaux
It never worked until today.
2017-05-17intern symbol namesQuentin Carbonneaux
Symbols in the source file are still limited in length because the rest of the code assumes that strings always fit in NString bytes. Regardless, there is already a benefit because comparing/copying symbol names does not require using strcmp()/strcpy() anymore.
2017-04-11simplify amd64 aggregates classificationQuentin Carbonneaux
2017-04-08misc fixes for osxQuentin Carbonneaux
With the default toolchain, it looks like we have to make sure all symbols are loaded using rip-relative addressing.
2017-04-08rework storage of typesQuentin Carbonneaux
The arm64 ABI needs to know precisely what floating point types are being used, so we need to store that information. I also made typ[] a dynamic array.
2017-04-08prepare for multi-targetQuentin Carbonneaux
This big diff does multiple changes to allow the addition of new targets to qbe. The changes are listed below in decreasing order of impact. 1. Add a new Target structure. To add support for a given target, one has to implement all the members of the Target structure. All the source files where changed to use this interface where needed. 2. Single out amd64-specific code. In this commit, the amd64 target T_amd64_sysv is the only target available, it is implemented in the amd64/ directory. All the non-static items in this directory are prefixed with either amd64_ or amd64_sysv (for items that are specific to the System V ABI). 3. Centralize Ops information. There is now a file 'ops.h' that must be used to store all the available operations together with their metadata. The various targets will only select what they need; but it is beneficial that there is only *one* place to change to add a new instruction. One good side effect of this change is that any operation 'xyz' in the IL now as a corresponding 'Oxyz' in the code. 4. Misc fixes. One notable change is that instruction selection now generates generic comparison operations and the lowering to the target's comparisons is done in the emitter. GAS directives for data are the same for many targets, so data emission was extracted in a file 'gas.c'. 5. Modularize the Makefile. The Makefile now has a list of C files that are target-independent (SRC), and one list of C files per target. Each target can also use its own 'all.h' header (for example to define registers).