mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
[StackSafety,NFC] Update documentation
It's follow up for D80908 Reviewed By: tejohnson Differential Revision: https://reviews.llvm.org/D82941
This commit is contained in:
parent
ce4cb5a65c
commit
b4bde7a6b6
@ -6843,7 +6843,9 @@ function and looks like:
|
|||||||
param: 4, offset: [0, 5][, calls: ((Callee)[, (Callee)]*)]?
|
param: 4, offset: [0, 5][, calls: ((Callee)[, (Callee)]*)]?
|
||||||
|
|
||||||
where the first ``param`` is the number of the parameter it describes,
|
where the first ``param`` is the number of the parameter it describes,
|
||||||
``offset`` is the known access range of the paramenter inside of the function.
|
``offset`` is the inclusive range of offsets from the pointer parameter to bytes
|
||||||
|
which can be accessed by the function. This range does not include accesses by
|
||||||
|
function calls from ``calls`` list.
|
||||||
|
|
||||||
where each ``Callee`` decribes how parameter is forwared into other
|
where each ``Callee`` decribes how parameter is forwared into other
|
||||||
functions and looks like:
|
functions and looks like:
|
||||||
@ -6854,7 +6856,44 @@ functions and looks like:
|
|||||||
|
|
||||||
The ``callee`` refers to the summary entry id of the callee, ``param`` is
|
The ``callee`` refers to the summary entry id of the callee, ``param`` is
|
||||||
the number of the callee parameter which points into the callers parameter
|
the number of the callee parameter which points into the callers parameter
|
||||||
with offset known to be inside of the ``offset`` range.
|
with offset known to be inside of the ``offset`` range. ``calls`` will be
|
||||||
|
consumed and removed by thin link stage to update ``Param::offset`` so it
|
||||||
|
covers all accesses possible by ``calls``.
|
||||||
|
|
||||||
|
Pointer parameter without corresponding ``Param`` is considered unsafe and we
|
||||||
|
assume that access with any offset is possible.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
If we have the following function:
|
||||||
|
|
||||||
|
.. code-block:: text
|
||||||
|
|
||||||
|
define i64 @foo(i64* %0, i32* %1, i8* %2, i8 %3) {
|
||||||
|
store i32* %1, i32** @x
|
||||||
|
%5 = getelementptr inbounds i8, i8* %2, i64 5
|
||||||
|
%6 = load i8, i8* %5
|
||||||
|
%7 = getelementptr inbounds i8, i8* %2, i8 %3
|
||||||
|
tail call void @bar(i8 %3, i8* %7)
|
||||||
|
%8 = load i64, i64* %0
|
||||||
|
ret i64 %8
|
||||||
|
}
|
||||||
|
|
||||||
|
We can expect the record like this:
|
||||||
|
|
||||||
|
.. code-block:: text
|
||||||
|
|
||||||
|
params: ((param: 0, offset: [0, 7]),(param: 2, offset: [5, 5], calls: ((callee: ^3, param: 1, offset: [-128, 127]))))
|
||||||
|
|
||||||
|
The function may access just 8 bytes of the paramenter %0 . ``calls`` is empty,
|
||||||
|
so the parameter is either not used for function calls or ``offset`` already
|
||||||
|
covers all accesses from nested function calls.
|
||||||
|
Parameter %1 escapes, so access is unknown.
|
||||||
|
The function itself can access just a single byte of the parameter %2. Additional
|
||||||
|
access is possible inside of the ``@bar`` or ``^3``. The function adds signed
|
||||||
|
offset to the pointer and passes the result as the argument %1 into ``^3``.
|
||||||
|
This record itself does not tell us how ``^3`` will access the parameter.
|
||||||
|
Parameter %3 is not a pointer.
|
||||||
|
|
||||||
.. _refs_summary:
|
.. _refs_summary:
|
||||||
|
|
||||||
|
@ -45,6 +45,12 @@ public:
|
|||||||
void print(raw_ostream &O) const;
|
void print(raw_ostream &O) const;
|
||||||
|
|
||||||
/// Parameters use for a FunctionSummary.
|
/// Parameters use for a FunctionSummary.
|
||||||
|
/// Function collects access information of all pointer parameters.
|
||||||
|
/// Information includes a range of direct access of parameters by the
|
||||||
|
/// functions and all call sites accepting the parameter.
|
||||||
|
/// StackSafety assumes that missing parameter information means possibility
|
||||||
|
/// of access to the parameter with any offset, so we can correctly link
|
||||||
|
/// code without StackSafety information, e.g. non-ThinLTO.
|
||||||
std::vector<FunctionSummary::ParamAccess> getParamAccesses() const;
|
std::vector<FunctionSummary::ParamAccess> getParamAccesses() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -553,8 +553,7 @@ public:
|
|||||||
unsigned AlwaysInline : 1;
|
unsigned AlwaysInline : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Describes the uses of a parameter by the range of offsets accessed in the
|
/// Describes the uses of a parameter by the function.
|
||||||
/// function and all of the call targets it is passed to.
|
|
||||||
struct ParamAccess {
|
struct ParamAccess {
|
||||||
static constexpr uint32_t RangeWidth = 64;
|
static constexpr uint32_t RangeWidth = 64;
|
||||||
|
|
||||||
@ -564,7 +563,7 @@ public:
|
|||||||
struct Call {
|
struct Call {
|
||||||
uint64_t ParamNo = 0;
|
uint64_t ParamNo = 0;
|
||||||
GlobalValue::GUID Callee = 0;
|
GlobalValue::GUID Callee = 0;
|
||||||
ConstantRange Offsets{RangeWidth, true};
|
ConstantRange Offsets{/*BitWidth=*/RangeWidth, /*isFullSet=*/true};
|
||||||
|
|
||||||
Call() = default;
|
Call() = default;
|
||||||
Call(uint64_t ParamNo, GlobalValue::GUID Callee,
|
Call(uint64_t ParamNo, GlobalValue::GUID Callee,
|
||||||
@ -573,7 +572,15 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
uint64_t ParamNo = 0;
|
uint64_t ParamNo = 0;
|
||||||
ConstantRange Use{RangeWidth, true};
|
/// The range contains byte offsets from the parameter pointer which
|
||||||
|
/// accessed by the function. In the per-module summary, it only includes
|
||||||
|
/// accesses made by the function instructions. In the combined summary, it
|
||||||
|
/// also includes accesses by nested function calls.
|
||||||
|
ConstantRange Use{/*BitWidth=*/RangeWidth, /*isFullSet=*/true};
|
||||||
|
/// In the per-module summary, it summarizes the byte offset applied to each
|
||||||
|
/// pointer parameter before passing to each corresponding callee.
|
||||||
|
/// In the combined summary, it's empty and information is propagated by
|
||||||
|
/// inter-procedural analysis and applied to the Use field.
|
||||||
std::vector<Call> Calls;
|
std::vector<Call> Calls;
|
||||||
|
|
||||||
ParamAccess() = default;
|
ParamAccess() = default;
|
||||||
|
@ -748,13 +748,16 @@ const StackSafetyGlobalInfo::InfoTy &StackSafetyGlobalInfo::getInfo() const {
|
|||||||
return *Info;
|
return *Info;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts a StackSafetyFunctionInfo to the relevant FunctionSummary
|
|
||||||
// constructor fields
|
|
||||||
std::vector<FunctionSummary::ParamAccess>
|
std::vector<FunctionSummary::ParamAccess>
|
||||||
StackSafetyInfo::getParamAccesses() const {
|
StackSafetyInfo::getParamAccesses() const {
|
||||||
|
// Implementation transforms internal representation of parameter information
|
||||||
|
// into FunctionSummary format.
|
||||||
std::vector<FunctionSummary::ParamAccess> ParamAccesses;
|
std::vector<FunctionSummary::ParamAccess> ParamAccesses;
|
||||||
for (const auto &KV : getInfo().Info.Params) {
|
for (const auto &KV : getInfo().Info.Params) {
|
||||||
auto &PS = KV.second;
|
auto &PS = KV.second;
|
||||||
|
// Parameter accessed by any or unknown offset, represented as FullSet by
|
||||||
|
// StackSafety, is handled as the parameter for which we have no
|
||||||
|
// StackSafety info at all. So drop it to reduce summary size.
|
||||||
if (PS.Range.isFullSet())
|
if (PS.Range.isFullSet())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -763,6 +766,10 @@ StackSafetyInfo::getParamAccesses() const {
|
|||||||
|
|
||||||
Param.Calls.reserve(PS.Calls.size());
|
Param.Calls.reserve(PS.Calls.size());
|
||||||
for (auto &C : PS.Calls) {
|
for (auto &C : PS.Calls) {
|
||||||
|
// Parameter forwarded into another function by any or unknown offset
|
||||||
|
// will make ParamAccess::Range as FullSet anyway. So we can drop the
|
||||||
|
// entire parameter like we did above.
|
||||||
|
// TODO(vitalybuka): Return already filtered parameters from getInfo().
|
||||||
if (C.Offset.isFullSet()) {
|
if (C.Offset.isFullSet()) {
|
||||||
ParamAccesses.pop_back();
|
ParamAccesses.pop_back();
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user