Files
revng-revng/include/revng/Model/ABI.h
Alessandro Di Federico d2d32b304e Model: improve documentation
2024-12-11 16:15:09 +01:00

359 lines
12 KiB
C++

#pragma once
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
#include "revng/Model/Architecture.h"
/* TUPLE-TREE-YAML
name: ABI
type: enum
members:
- name: SystemV_x86_64
doc: |
64-bit SystemV ABI for x86 processor architecture
([reference](https://gitlab.com/x86-psABIs/x86-64-ABI)).
- name: SystemV_x86
doc: |
32-bit SystemV ABI for x86 processor architecture ([reference][abi1]).
[abi1]: https://gitlab.com/x86-psABIs/i386-ABI/-/tree/hjl/x86/master
- name: SystemV_x86_regparm_3
doc: |
A GCC specific modification of the 32-bit SystemV ABI for x86 processor
architecture. It allows three first GPR-sized arguments to be passed
using the EAX, EDX, and ECX registers.
See the reference for `regparm` x86 function attribute.
- name: SystemV_x86_regparm_2
doc: |
A GCC specific modification of the 32-bit SystemV ABI for x86 processor
architecture. It allows two first GPR-sized arguments to be passed
using the EAX, and ECX registers.
See the GCC documentation for `regparm` x86 function attribute.
- name: SystemV_x86_regparm_1
doc: |
A GCC specific modification of the 32-bit SystemV ABI for x86 processor
architecture. It allows the first GPR-sized argument to be passed
using the EAX register.
See the GCC documentation for `regparm` x86 function attribute.
- name: Microsoft_x86_64
doc: >
64-bit Microsoft ABI for x86 processor architecture
([reference][abi2]).
[abi2]: https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention
- name: Microsoft_x86_64_vectorcall
doc: |
A modification of 64-bit Microsoft ABI for x86 processor architecture
([reference](https://docs.microsoft.com/en-us/cpp/cpp/vectorcall)).
It allows using extra vector registers for passing function arguments.
- name: Microsoft_x86_cdecl
doc: |
The default 32-bit Microsoft ABI for x86 processor architecture
([reference](https://docs.microsoft.com/en-us/cpp/cpp/cdecl)).
It was indented to be compatible with `SystemV_x86` but there are slight
differences.
- name: Microsoft_x86_cdecl_gcc
doc: |
32-bit Microsoft x86 `cdecl` abi as implemented in GCC (subtly different
from the original).
- name: Microsoft_x86_stdcall
doc: |
A modification of the 32-bit `__cdecl` Microsoft ABI for x86 processor
architecture
([reference](https://docs.microsoft.com/en-us/cpp/cpp/stdcall)).
The main difference is the fact that the callee is responsible for stack
cleanup instead of the caller.
- name: Microsoft_x86_stdcall_gcc
doc: |
32-bit Microsoft x86 `stdcall` abi as implemented in GCC (subtly different
from the original).
- name: Microsoft_x86_thiscall
doc: |
A modification of the 32-bit `__stdcall` Microsoft ABI for x86 processor
architecture
([reference](https://docs.microsoft.com/en-us/cpp/cpp/thiscall)).
The main difference is the fact that it allows to pass a
single (the first) function argument using a register. This ABI is only
used for member function call where the first argument is always a `this`
pointer.
- name: Microsoft_x86_fastcall
doc: |
A modification of the 32-bit `__stdcall` Microsoft ABI for x86 processor
architecture
([reference](https://docs.microsoft.com/en-us/cpp/cpp/fastcall)).
The main difference is the fact that it allows to pass two
first GPR-sized non-aggregate function arguments in registers.
- name: Microsoft_x86_fastcall_gcc
doc: |
32-bit Microsoft x86 `fastcall` abi as implemented in GCC (subtly
different from the original).
- name: Microsoft_x86_vectorcall
doc: |
A modification of the 32-bit `__fastcall` Microsoft ABI for x86 processor
architecture
([reference](https://docs.microsoft.com/en-us/cpp/cpp/vectorcall)).
It allows using extra vector registers for passing function arguments.
- name: AAPCS64
doc: |
Stands for `Arm Architecture Procedure Call Standard (64-bit)`
([reference](https://github.com/ARM-software/abi-aa/releases)).
The official ABI for AArch64 (ARM64) processor architecture.
- name: Microsoft_AAPCS64
doc: >
Stands for "Arm Architecture Procedure Call Standard (64-bit)".
This represents the version of the ABI used by windows-on-arm.
For differences from the original ABI see the [reference][ab3].
[ab3]: https://learn.microsoft.com/cpp/build/arm64-windows-abi-conventions
- name: Apple_AAPCS64
doc: "Stands for \"Arm Architecture Procedure Call Standard (64-bit)\".\n
This represents the version of the ABI used by the apple products.\n
For differences from the original ABI see the [reference](\
https://developer.apple.com/documentation/xcode/writing-arm64-
code-for-apple-platforms)."
- name: AAPCS
doc: |
Stands for "Arm Architecture Procedure Call Standard"
([reference](https://github.com/ARM-software/abi-aa/releases)).
The official ABI for ARM processor architecture.
- name: SystemV_MIPS_o32
doc: >
The ABI for MIPS RISC processor architecture
([reference][abi4]).
[abi4]: http://math-atlas.sourceforge.net/devel/assembly/mipsabi32.pdf
- name: SystemV_MIPSEL_o32
doc: >
The ABI for little-endian edition of the MIPS RISC processor architecture
([reference][abi5]).
[abi5]: http://math-atlas.sourceforge.net/devel/assembly/mipsabi32.pdf
- name: SystemZ_s390x
doc: |
The s390x ABI for SystemZ processor architecture
([reference](https://github.com/IBM/s390x-abi)).
TUPLE-TREE-YAML */
#include "revng/Model/Generated/Early/ABI.h"
namespace model::ABI {
inline constexpr model::Architecture::Values
getArchitecture(model::ABI::Values V) {
switch (V) {
case model::ABI::SystemV_x86_64:
case model::ABI::Microsoft_x86_64:
case model::ABI::Microsoft_x86_64_vectorcall:
return model::Architecture::x86_64;
case model::ABI::SystemV_x86:
case model::ABI::SystemV_x86_regparm_3:
case model::ABI::SystemV_x86_regparm_2:
case model::ABI::SystemV_x86_regparm_1:
case model::ABI::Microsoft_x86_vectorcall:
case model::ABI::Microsoft_x86_cdecl:
case model::ABI::Microsoft_x86_cdecl_gcc:
case model::ABI::Microsoft_x86_stdcall:
case model::ABI::Microsoft_x86_stdcall_gcc:
case model::ABI::Microsoft_x86_fastcall:
case model::ABI::Microsoft_x86_fastcall_gcc:
case model::ABI::Microsoft_x86_thiscall:
return model::Architecture::x86;
case model::ABI::AAPCS64:
case model::ABI::Microsoft_AAPCS64:
case model::ABI::Apple_AAPCS64:
return model::Architecture::aarch64;
case model::ABI::AAPCS:
return model::Architecture::arm;
case model::ABI::SystemV_MIPS_o32:
return model::Architecture::mips;
case model::ABI::SystemV_MIPSEL_o32:
return model::Architecture::mipsel;
case model::ABI::SystemZ_s390x:
return model::Architecture::systemz;
case model::ABI::Count:
case model::ABI::Invalid:
default:
revng_abort();
}
}
/// A workaround for the model not having dedicated `mipsel` registers.
///
/// The returned architecture is the one registers of which is used inside
/// the `abi::Definition`.
inline constexpr model::Architecture::Values
getRegisterArchitecture(model::ABI::Values V) {
if (V == model::ABI::SystemV_MIPSEL_o32)
return model::Architecture::mips;
else
return getArchitecture(V);
}
/// \return the size of the pointer under the specified ABI.
inline constexpr uint64_t getPointerSize(model::ABI::Values V) {
return model::Architecture::getPointerSize(getArchitecture(V));
}
// TODO: move binary specific information away from a major header
inline constexpr std::optional<model::ABI::Values>
getDefaultForELF(model::Architecture::Values V) {
switch (V) {
case model::Architecture::x86_64:
return model::ABI::SystemV_x86_64;
case model::Architecture::x86:
return model::ABI::SystemV_x86;
case model::Architecture::aarch64:
return model::ABI::AAPCS64;
case model::Architecture::arm:
return model::ABI::AAPCS;
case model::Architecture::mips:
return model::ABI::SystemV_MIPS_o32;
case model::Architecture::mipsel:
return model::ABI::SystemV_MIPSEL_o32;
case model::Architecture::systemz:
return model::ABI::SystemZ_s390x;
default:
return std::nullopt;
}
}
inline constexpr std::optional<model::ABI::Values>
getDefaultForPECOFF(model::Architecture::Values V) {
switch (V) {
case model::Architecture::x86_64:
return model::ABI::Microsoft_x86_64;
case model::Architecture::x86:
return model::ABI::Microsoft_x86_cdecl;
case model::Architecture::aarch64:
return model::ABI::Microsoft_AAPCS64;
default:
return std::nullopt;
}
}
inline constexpr std::optional<model::ABI::Values>
getDefaultForMachO(model::Architecture::Values V) {
switch (V) {
case model::Architecture::x86_64:
return model::ABI::SystemV_x86_64;
case model::Architecture::x86:
return model::ABI::SystemV_x86;
case model::Architecture::aarch64:
return model::ABI::Apple_AAPCS64;
default:
return std::nullopt;
}
}
inline constexpr llvm::StringRef getDescription(model::ABI::Values V) {
switch (V) {
case model::ABI::SystemV_x86_64:
return "64-bit SystemV x86 abi";
case model::ABI::Microsoft_x86_64:
return "64-bit Microsoft x86 abi";
case model::ABI::Microsoft_x86_64_vectorcall:
return "64-bit Microsoft x86 abi with extra vector "
"registers designited for passing function "
"arguments";
case model::ABI::SystemV_x86:
return "32-bit SystemV x86 abi";
case model::ABI::SystemV_x86_regparm_3:
return "32-bit SystemV x86 abi that allows the first three GPR-sized "
"scalar arguments to be passed using the registers";
case model::ABI::SystemV_x86_regparm_2:
return "32-bit SystemV x86 abi that allows the first two GPR-sized "
"scalar arguments to be passed using the registers";
case model::ABI::SystemV_x86_regparm_1:
return "32-bit SystemV x86 abi that allows the first "
"GPR-sized scalar argument to be passed using "
"the registers";
case model::ABI::Microsoft_x86_vectorcall:
return "64-bit Microsoft x86 abi, it extends `fastcall` "
"by allowing extra vector registers to be used for "
"function argument passing";
case model::ABI::Microsoft_x86_cdecl:
return "32-bit Microsoft x86 abi that was intended to "
"mimic 32-bit SystemV x86 abi but has minor "
"differences";
case model::ABI::Microsoft_x86_cdecl_gcc:
return "32-bit Microsoft x86 `cdecl` abi as implemented in GCC (subtly "
"different from the original).";
case model::ABI::Microsoft_x86_stdcall:
return "32-bit Microsoft x86 abi, it is a modification of "
"`cdecl` that's different in a sense that the "
"callee is responsible for stack cleanup instead "
"of the caller";
case model::ABI::Microsoft_x86_stdcall_gcc:
return "32-bit Microsoft x86 `stdcall` abi as implemented in GCC (subtly "
"different from the original).";
case model::ABI::Microsoft_x86_fastcall:
return "32-bit Microsoft x86 abi, it extends `stdcall` by "
"allowing two first GPR-sized function arguments "
"to be passed using the registers";
case model::ABI::Microsoft_x86_fastcall_gcc:
return "32-bit Microsoft x86 `fastcall` abi as implemented in GCC (subtly "
"different from the original).";
case model::ABI::Microsoft_x86_thiscall:
return "32-bit Microsoft x86 abi, it extends `stdcall` by "
"allowing `this` pointer in method-style calls to "
"be passed using a register. It is never used for "
"'free' functions";
case model::ABI::AAPCS64:
return "64-bit ARM abi";
case model::ABI::Microsoft_AAPCS64:
return "Microsoft version of 64-bit ARM abi";
case model::ABI::Apple_AAPCS64:
return "Apple version of 64-bit ARM abi";
case model::ABI::AAPCS:
return "32-bit ARM abi";
case model::ABI::SystemV_MIPS_o32:
return "The \"old\" 32-bit MIPS abi";
case model::ABI::SystemV_MIPSEL_o32:
return "The \"old\" 32-bit MIPS abi (little endian edition)";
case model::ABI::SystemZ_s390x:
return "The s390x SystemZ ABI";
case model::ABI::Count:
case model::ABI::Invalid:
default:
return "Unknown and/or unsupported ABI";
}
}
} // namespace model::ABI
#include "revng/Model/Generated/Late/ABI.h"