-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
JIT: Add a uniform representation for parameter ABI information (#100138
) This adds a uniform representation that can represent the ABI information for all of our targets without needing to fall back to handling ABI specific details in all places that need to handle calling conventions. Currently nothing is using this information. I want to incrementally migrate our ABI handling to use this representation. Also, there are several potential future improvements: - Split out ABI classification per ABI instead of keeping them all within the same function - Unify `InitVarDscInfo::stackArgSize` and `InitVarDscInfo::argSize`. I am unsure why the latter is needed - Remove `LclVarDsc::GetArgReg()`, `LclVarDscInfo::GetOtherArgReg()`, HFA related members - Reuse the representation in `CallArgABIInformation` and unify the classifiers The end goal here is rewriting `genFnPrologCalleeRegArgs` to handle float and integer registers simultaneously, and to support some of the registers that the Swift calling convention is using.
- Loading branch information
1 parent
1fecfbc
commit 13a9036
Showing
8 changed files
with
385 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
#include "jitpch.h" | ||
#include "abi.h" | ||
|
||
//----------------------------------------------------------------------------- | ||
// IsPassedInRegister: | ||
// Check if this segment is passed in a register. | ||
// | ||
// Return Value: | ||
// True if this is passed in a register. | ||
// | ||
bool ABIPassingSegment::IsPassedInRegister() const | ||
{ | ||
return m_register != REG_NA; | ||
} | ||
|
||
//----------------------------------------------------------------------------- | ||
// IsPassedOnStack: | ||
// Check if this segment is passed on the stack. | ||
// | ||
// Return Value: | ||
// True if this is passed on the stack. | ||
// | ||
bool ABIPassingSegment::IsPassedOnStack() const | ||
{ | ||
return m_register == REG_NA; | ||
} | ||
|
||
//----------------------------------------------------------------------------- | ||
// GetRegister: | ||
// Get the register that this segment is passed in. | ||
// | ||
// Return Value: | ||
// The register. | ||
// | ||
regNumber ABIPassingSegment::GetRegister() const | ||
{ | ||
assert(IsPassedInRegister()); | ||
return m_register; | ||
} | ||
|
||
//----------------------------------------------------------------------------- | ||
// GetStackOffset: | ||
// Get the stack offset where this segment is passed. | ||
// | ||
// Return Value: | ||
// Offset relative to the first stack argument. | ||
// | ||
unsigned ABIPassingSegment::GetStackOffset() const | ||
{ | ||
assert(IsPassedOnStack()); | ||
return m_stackOffset; | ||
} | ||
|
||
//----------------------------------------------------------------------------- | ||
// InRegister: | ||
// Create an ABIPassingSegment representing that a segment is passed in a | ||
// register. | ||
// | ||
// Parameters: | ||
// reg - The register the segment is passed in | ||
// offset - The offset of the segment that is passed in the register | ||
// size - The size of the segment passed in the register | ||
// | ||
// Return Value: | ||
// New instance of ABIPassingSegment. | ||
// | ||
ABIPassingSegment ABIPassingSegment::InRegister(regNumber reg, unsigned offset, unsigned size) | ||
{ | ||
assert(reg != REG_NA); | ||
ABIPassingSegment segment; | ||
segment.m_register = reg; | ||
segment.m_stackOffset = 0; | ||
segment.Offset = offset; | ||
segment.Size = size; | ||
return segment; | ||
} | ||
|
||
//----------------------------------------------------------------------------- | ||
// OnStack: | ||
// Create an ABIPassingSegment representing that a segment is passed on the | ||
// stack. | ||
// | ||
// Parameters: | ||
// stackOffset - Offset relative to the first stack parameter/argument | ||
// offset - The offset of the segment that is passed in the register | ||
// size - The size of the segment passed in the register | ||
// | ||
// Return Value: | ||
// New instance of ABIPassingSegment. | ||
// | ||
ABIPassingSegment ABIPassingSegment::OnStack(unsigned stackOffset, unsigned offset, unsigned size) | ||
{ | ||
ABIPassingSegment segment; | ||
segment.m_register = REG_NA; | ||
segment.m_stackOffset = stackOffset; | ||
segment.Offset = offset; | ||
segment.Size = size; | ||
return segment; | ||
} | ||
|
||
//----------------------------------------------------------------------------- | ||
// IsSplitAcrossRegistersAndStack: | ||
// Check if this ABIPassingInformation represents passing a value in both | ||
// registers and on stack. | ||
// | ||
// Return Value: | ||
// True if the value is passed in both registers and on stack. | ||
// | ||
bool ABIPassingInformation::IsSplitAcrossRegistersAndStack() const | ||
{ | ||
bool anyReg = false; | ||
bool anyStack = false; | ||
for (unsigned i = 0; i < NumSegments; i++) | ||
{ | ||
anyReg |= Segments[i].IsPassedInRegister(); | ||
anyStack |= Segments[i].IsPassedOnStack(); | ||
} | ||
return anyReg && anyStack; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
#pragma once | ||
|
||
class ABIPassingSegment | ||
{ | ||
regNumber m_register = REG_NA; | ||
unsigned m_stackOffset = 0; | ||
|
||
public: | ||
bool IsPassedInRegister() const; | ||
bool IsPassedOnStack() const; | ||
|
||
// Start offset of the segment within the parameter/argument. For example, a struct like { int32_t x; uint64_t y } | ||
// may have two segments | ||
// 1. Register(Offset=0, Type=TYP_INT, Size=4, Register=REG_ESI) | ||
// 2. Register(Offset=8, Type=TYP_LONG, Size=8, Register=REG_EDI) | ||
// on some ABIs, where the size of the first segment is not sufficient to | ||
// compute the offset of the second. | ||
unsigned Offset = 0; | ||
// Size of the segment being passed. | ||
unsigned Size = 0; | ||
|
||
// If this segment is passed in a register, return the particular register. | ||
regNumber GetRegister() const; | ||
|
||
// If this segment is passed on the stack then return the particular stack | ||
// offset, relative to the first stack argument's offset. | ||
unsigned GetStackOffset() const; | ||
|
||
static ABIPassingSegment InRegister(regNumber reg, unsigned offset, unsigned size); | ||
static ABIPassingSegment OnStack(unsigned stackOffset, unsigned offset, unsigned size); | ||
}; | ||
|
||
struct ABIPassingInformation | ||
{ | ||
// The number of segments used to pass the value. Examples: | ||
// - On x86, TYP_LONG can be passed in two registers, resulting in two | ||
// register segments | ||
// - On SysV x64, structs can be passed in two registers, resulting in two | ||
// register segments | ||
// - On arm64/arm32, HFAs can be passed in up to four registers, giving | ||
// four register segments | ||
// - On arm32, structs can be split out over register and stack, giving | ||
// multiple register segments and a struct segment. | ||
// - On Windows x64, all parameters always belong into one stack slot or register, | ||
// and thus always have NumSegments == 1 | ||
unsigned NumSegments = 0; | ||
ABIPassingSegment* Segments = nullptr; | ||
|
||
bool IsSplitAcrossRegistersAndStack() const; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.