<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/135592>135592</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[MC] Should MCFixup store MCValue instead of MCExpr?
</td>
</tr>
<tr>
<th>Labels</th>
<td>
mc
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
MaskRay
</td>
</tr>
</table>
<pre>
GNU Assembler utilizes `struct fixup` to represent both the fixup and the relocatable expression.
(Some writeup will be copied back to https://maskray.me/blog/2025-03-16-relocation-generation-in-assemblers )
```
struct fix {
...
/* NULL or Symbol whose value we add in. */
symbolS *fx_addsy;
/* NULL or Symbol whose value we subtract. */
symbolS *fx_subsy;
/* Absolute number we add in. */
valueT fx_offset;
};
```
The relocation specifier is part of the instruction instead of part of struct fix. Targets have different internal representations of instructions.
In contrast, LLVM integrated assembler encodes fixups and relocatable expressions separately.
```cpp
class MCFixup {
/// The value to put into the fixup location. The exact interpretation of the
/// expression is target dependent, usually it will be one of the operands to
/// an instruction or an assembler directive.
const MCExpr *Value = nullptr; /// In GNU Assembler, this would be addsy/subsy/offset
/// The byte index of start of the relocation inside the MCFragment.
uint32_t Offset = 0;
/// The target dependent kind of fixup item this is. The kind is used to
/// determine how the operand value should be encoded into the instruction.
MCFixupKind Kind = FK_NONE;
/// The source location which gave rise to the fixup, if any.
SMLoc Loc;
};
```
LLVM encodes relocatable expressions as `MCValue`,
```
class MCValue {
const MCSymbol *SymA = nullptr, *SymB = nullptr;
int64_t Cst = 0;
uint32_t Specifier = 0;
};
```
The const `MCExpr *MCFixup::getValue()` method feels inconvenient and less elegant compared to GNU Assembler's approach for these reasons:
* Relocation specifier can be encoded by every sub-expression in the `MCExpr` tree, rather than the fixup itself (or the instruction, as in GNU Assembler). Supporting all of `a+4@got, a@got+4, (a+4)@got` requires extensive hacks in LLVM MCParser.
* `evaluateAsRelocatable` converts an MCExpr to an MCValue without updating the MCExpr itself. This leads to redundant evaluations, as `MCAssembler::evaluateFixup` is called multiple times, such as in `MCAssembler::fixupNeedsRelaxation` and `MCAssembler::layout`.
Storing a MCValue directly in MCFixup, or adding a relocation specifier member, could eliminate the need for many target-specific `MCTargetFixup` classes that manage relocation specifiers.
However, target-specific evaluation hooks would still be needed for specifiers like PowerPC `@l` or RISC-V `%lo()`.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJyMl1tz4joSgH-NeOmCMuKS8MADIYfdqRNypsKceU3JVhtrI0tetcxlf_2WJBsIm5naFBWMLfX1625ZEKm9QVyy2RObPQ9E6yvrlltBH2_iPMitPC__8fo3rIiwzjU6aL3S6j9IwOYZedcWHkp1ahs2z8BbcNg4JDQecusr8BWmxyCMjL8calsIL3KNgKewmJQ1I5atwoc_7myNcHTKY9vAUWkNOUJhG4USclF8BCWV9w2xyYrxDeObWtCHE-dRjYxvcm33jG94xmfDbDIcz4edQmXNcI8GXbpUZih6nwgYXwTt86z7ZKura8Aenli2AhiNRvE7al3B698vL2Ad7M51bjUcK0sIB6FbhCOCkBKUGYXV0cxsBRQX7sKd8vQupKQzmzwlx_9PqdTm3onC_0YutflXclc5Wd16BNPWObpfmJg0_YDy9G7LktB3gh6eu4ubCLFs9eOaT2UNUIOFKhU6UASNcB5sGXOuTApnWBSuUcjwqF9yjfUIfgi3R09QiQOCVGWJLsCkjEdnhL7yFVVS2H4jnTqOvhkorPFOkGd8DS8vP7dRxN4JjxIumQc0hZVIiVGKkH4NKAFhI8J2fe5h7YNRNA3LVoUWRLBdbyLuPTQJUcY3EIKVEuktNG30yd4USB_GUVyJJ1F0bjcOk7ddOO_kXm0MYfcxfiCxQSPRRPdbaoXWZ1D-UlDWYJ8c26ATRhJ4eydZmE-Zsy7cucZOKoeFVweMZVFYQx626z9OjQtE_YyusskzmFbrxjs2eYL4d1XwzcCn5hKM9ZUiONpWy2BnqhK-SVTzTUflLduX4OZnH1CTeEpQ3QB4A6kypCTGu9v1xol9jcanwm6V8RP-7uGvqCUan92X0kXdfaThQ5mIdUqn8lgnZxSllMbniqAllP8bbIkeXa0MQmWPt4npoKGqj0liVl75uUlScqSD8M-gMP4Lnmz-fH_96_WPX_pDtnUFXjCEY6WKCvahDp2iSO0F1pAoVYIwsRZgt32xBbzY4vftIpZhX3G_KjMRJ8t2HfkJW_n6TlJfaB1hXaH1_HWNk_HV7lyvPgHI193tpzsuowBl_Hz67mFNnzJ_g8Xu0t9uyfhNb0w2RXf6suhSE4bXZLVHn9zkj2ECzTOo0VdWQomoCZQprDmgUYGuQIJGIkCNe2E8FLZuhIso3VfRA4FoGmdFUUFpXcgbhSIQZE2cm92wXcHbV927EOaWs_wMeEB3DtNneNttTATi4l48ATjEEGcnfIVBsTA3LU55Ql0C44_JqFtywy4RfL53ZjGCXds01nll9iC0DjXG5plg_GnKptnexiYn-sunaUr0Y1rAF92DeQYO_90qhwR48mhIHRAqUXxErRHO7fq7cIRu1IWHzTMM5Sc8rujtSmwQFnPjfBgafdvzNv1IZB6Vr2zroW2kiLannhNXpkiEvqAINIrYfsGhbI0Mye20horoAhPDfA1L5Ke3bdMfwBRBIbRGCXWrvWo0glc1RhnUFlUX4a9kxQy9IsrgpzhF3UFk4O6r9VqcbRui2k3DnbcuJujif5oPYe6YviMFO8IYkTIt_fLwUGM4oYSlRWx5qFWtjPCpaRtEGaGuhTl3TXjYbS6SpekMcQlK7BdIAUYfdon916eWeHj4pz0G2OMkupN9zQlU1n70U4p8N1ODZZ1tV5mg1QfCd3tE930dzGPTTAerrIO3b7v18Ge8yWfaXrpAsGMglxO5mCzEAJfjh-l0Pp6Op3xQLYvFXMzGuZzNeMYzIaeYZwu-QP44nuSyLAdqGQ6_2XQ8zR4yzvnoIZtJLoqHuXjkEz4u2TTDWig90vpQj6zbDxRRi8vxZDZb8IEWOWqKLwSc1wXjPLwYuGVYPczbPQUPFHm67vfK6_gKsV2z2TPs0qjqj0LkrcMLFTfnv65tTDaD1unl50P9XvmqzUeFrRnfBEXd17Bx9l9YeMY30WpifNMZfljy_wYAAP__lU4vHw">