Section courante

A propos

Section administrative du site

 Langage  Installation  Elément  Tutoriel  Programmation  Bibliothèque  Cadre d'application  API  GUI  Projet  Composante  IDE  Outils  Annexe  Aide 
ABAP/4
Ada
Assembleur
Assembly & bytecode
ASP (Active Server Pages)
Basic
C
C++
C# (C Sharp)
Cobol
ColdFusion
Fortran
HTML
Java
JavaScript
LISP
Logo
LotusScript
Oberon
Pascal
Perl
PHP
PL/1
Prolog
Python
Rebol
REXX
Ruby
SAS
NoSQL
SQL
Swift
X++ (Axapta)
GNAT
SMALLAda
VHDL
Assembleur 370
Assembleur 1802
Assembleur 4004
Assembleur 6502
Assembleur 6800
Assembleur 68000
Assembleur 8080 et 8085
Assembleur 8089
Assembleur 80x86
Assembleur AGC4
Assembleur ARM
Assembleur DPS 8000
Assembleur i860
Assembleur Itanium
Assembleur MIPS
Assembleur PDP-11
Assembleur PowerPC
Assembleur RISC-V
Assembleur SPARC
Assembleur SuperH
Assembleur UNIVAC I
Assembleur VAX
Assembleur Z80
Assembleur Z8000
Assembleur z/Architecture
ASSEMBLER/MONITOR 64
Micol Assembler
GFA Assembler
A86
MASM (Macro Assembler)
TASM (Turbo Assembler)
CIL
Jasmin
LLVM
MSIL
Parrot
P-Code (PCode)
SWEET16
G-Pascal
ASP 1.0
ASP 2.0
ASP 3.0
ASP.NET
ASP.NET Core
ABasiC (Amiga)
Adam SmartBASIC
Altair BASIC
AmigaBASIC (Amiga)
AMOS Basic (Amiga)
Atari Basic (Atari 400, 600 XL, 800, 800XL)
Basic Apple II (Integer BASIC/APPLESOFT)
Basic Commodore 64 (CBM-BASIC)
Basic Commodore 128 (BASIC 7.0)
Basic Commodore VIC-20 (CBM-BASIC 2.0)
Basic Coco 1 (Color Basic)
Basic Coco 2 (Extended Color Basic)
Basic Coco 3 (Extended Color Basic 2.0)
BASICA (PC DOS)
Basic Pro
BBC BASIC
Blitz BASIC (Amiga)
DarkBASIC
Dartmouth BASIC
GFA-Basic (Atari ST/Amiga)
GWBASIC (MS-DOS)
Liberty BASIC
Locomotive BASIC (Amstrad CPC)
MSX-Basic
Omikron Basic (Atari ST)
Oric Extended Basic
Power Basic
Quick Basic/QBasic (MS-DOS)
Sinclair BASIC (ZX80, ZX81, ZX Spectrum)
ST BASIC (Atari ST)
Turbo Basic
Vintage BASIC
VBScript
Visual Basic (VB)
Visual Basic .NET (VB .NET)
Visual Basic pour DOS
Yabasic
BeckerBASIC
SIMONS' BASIC
Basic09 d'OS-9
Disk Extended Color Basic
Basic09 d'OS-9
Disk Extended Color Basic
Access
Excel
Visual Basic pour Windows
Visual Basic .NET pour Windows
C Shell Unix (csh)
C pour Amiga
C pour Atari ST
C pour DOS
C pour Falcon030
C pour GEMDOS (Atari ST)
C pour Linux
C pour PowerTV OS
C pour OS/2
C pour Unix
C pour Windows
Aztec C
CoCo-C
GNU C
HiSoft C
IBM C/2
Introl-C
Lattice C
Microsoft C
MinGW C
MSX-C
Open Watcom C
OS-9 C Compiler
Pure C
Quick C
Turbo C
HiSoft C for Atari ST
HiSoft C for CP/M (Amstrad CPC)
C++ pour OS/2
C++ pour Windows
Borland C++
C++Builder
IBM VisualAge C++
Intel C++
MinGW C++
Open Watcom C++
Symantec C++
Turbo C++
Visual C++
Visual C++ .NET
Watcom C++
Zortech C++
C# (C Sharp) pour Windows
Apple III Cobol
Microsoft Cobol
BlueDragon
Lucee
OpenBD
Railo
Smith Project
Microsoft Fortran
WATFOR-77
CSS
FBML
Open Graph
SVG
XML
XSL/XSLT
LESS
SASS
GCJ (GNU)
JSP
Jython
Visual J++
Node.js
TypeScript
AutoLISP
ACSLogo
LotusScript pour Windows
Amiga Oberon
Oberon .NET
Apple Pascal
Delphi/Kylix/Lazarus
Free Pascal
GNU Pascal
HighSpeed Pascal
IBM Personal Computer Pascal
Lisa Pascal
Maxon Pascal
MPW Pascal
OS-9 Pascal
OSS Personal Pascal
Pascal-86
Pascal du Cray Research
Pascal/VS
Pascal-XT
PURE Pascal
QuickPascal
RemObjets Chrome
Sun Pascal
THINK Pascal
Tiny Pascal (TRS-80)
Turbo Pascal
UCSD Pascal
VAX Pascal
Virtual Pascal
Turbo Pascal for CP/M-80
Turbo Pascal for DOS
Turbo Pascal for Macintosh
Turbo Pascal for Windows
CodeIgniter (Cadre d'application)
Drupal (Projet)
Joomla! (Projet)
Phalanger (PHP .NET)
phpBB (Projet)
Smarty (balise)
Twig (balise)
Symfony (Cadre d'application)
WordPress (Projet)
Zend (Cadre d'application)
PL360
PL/M-80
PL/M-86
Turbo Prolog
CPython
IronPython
Jython
PyPy
AREXX
Regina REXX
JMP
Btrieve
Cassandra
Clipper
CouchDB
dBASE
Hbase
Hypertable
MongoDB
Redis
Access
BigQuery
DB2
H2
Interbase
MySQL
Oracle
PostgreSQL
SAP HANA
SQL Server
Sybase
U-SQL
Installation de Free Pascal
Installation de CodeTyphon Studio
Installation de Lazarus
Installation de Pascal XE
Introduction
Les remarques
Les opérateurs
Les instructions conditionnelles
Les instructions de boucles
Les instructions d'exceptions
Type de données élémentaires
Référence des unités
Référence de mots réservés (mots clefs)
Référence de procédures et fonctions
Référence des directives de compilation
Référence de classes
BASEUNIX
CLASSES
CMEM
CRT
CTHREADS
CWSTRING
GRAPH
MATH
SYSTEM
Référence de procédures et fonctions avec prototype
Les jetons
Les constantes
Directives du compilateur
Utiliser des conditions, des messages et des macros
Utilisation du langage de programmation assembleur
Code généré
Prise en charge d'Intel MMX
Problèmes de code
Problèmes de liaison
Problèmes de mémoire
Chaînes de caractères de ressources
Programmation de processus léger
Optimisations
Programmation de bibliothèques partagées
Utiliser les ressources Windows
Bonjour
Affichage
Astronomie
Biochimie
Électricité
Fichiers
Finance
Géographie
Géométrie
Histoire
Jeux & stratégies
Mathématique
Médicale
Météorologie
Océanographie
Sport
Temps
Tri
Trigonométrie
Validation
«DRAW» du BASIC
Phase lunaire
Calcul du calcium corrigé
Calcul le taux d'alcoolémie
Comparaison de séquence de polypeptides
Tarif d'une piscine pour 1 mois
Texte séquentiel
Liste des fichiers
IPaymt/Interet
NPer
PPaymt/Principal
Distance en Km entre deux longitudes et latitudes
Aire d'un cercle
Aire d'une surface de prisme rectangulaire
Aire d'un triangle
Distance entre deux points
Treillis
Chiffre romain
Pac-Man
Tetris
Tours d'Hanois
Ackermann
Exp
Factoriel
Fibonacci
Log
Nombre premier
Odd
Random
Sqrt
Triangle Pascal
Hauteur utérine
Unité de mesure
Fréquence des vagues
Hockey
Année bissextile
Calendrier
Date de la Pâque
Heure courante
Horloge à aiguille
FirstDayOfMonth
Tri à bulle (Bubble Sort)
Tri Shell Sort
ArcCos
ArcSin
Atn/ATan/ArcTan
Cos
Sin
Courriel
Extension de nom de domaine
Ararat Synapse
CryptoLib4Pascal
FBLib (Firebird Pascal Library)
FCL (Free Component Library)
GraphiX
HashLib4Pascal
INDY (Internet Direct)
LCL (Lazarus Component Library)
QuickLib
QuickLogger
WinGraph
ZeosLib
Daraja (cadre d'application pour Web)
Fano Framework
Free Spider
Horse
Synopse mORMot
tiOPF
CAI NEURAL API
tensorflowforpascal
fpGUI
MOS
Corail
Double Commander
LDAP Admin for Linux
MSDOS-0
Transmission Remote GUI
UNIX-0
Python for Delphi (P4D)
CodeTyphon Studio
Free Pascal IDE
Lazarus
Pascal XE
GNU Debugger (GDB)
Delp
FPCMake
H2Pas
PPDep
PPUDump
PPUMove
PtoP
Références des codes d'erreur
Anatomie d'un fichier unité
Structure de l'arborescence des sources du compilateur et RTL
Limites du compilateur
Modes du compilateur
Utiliser fpcmake
Compilation du compilateur
Compilateur définit lors de la compilation
Préface
Notes légal
Dictionnaire
Recherche

Optimisations

Non spécifique au microprocesseur

Les sections suivantes décrivent les optimisations générales effectuées par le compilateur, elles ne sont pas spécifiques au microprocesseur. Certains d'entre eux nécessitent un remplacement de commutateur du compilateur tandis que d'autres sont effectués automatiquement (ceux nécessitant un commutateur seront notés comme tels).

Simplification de sous-expressions constant

En Free Pascal, si le ou les opérandes d'un opérateur sont des constantes, ils seront évalués au moment de la compilation.

Exemple :

  1. X:=1+2+3+6+5;

générera le même code que :

  1. X:=17;

De plus, si un index de tableau est une constante, le déplacement sera évalué au moment de la compilation. Cela signifie que l'accès à MyData[5] est aussi efficace que l'accès à une variable normale.

Enfin, l'appel des fonctions Chr, Hi, Lo, Ord, Pred ou Succ avec des paramètres constants ne génère aucun appel à la bibliothèque d'exécution ; les valeurs sont évaluées au moment de la compilation.

Fusion de constante

L'utilisation de la même chaîne constante, de la même valeur à virgule flottante ou du même ensemble de constantes deux fois ou plus génère une seule copie de cette constante.

Évaluation de raccourcie

L'évaluation de l'expression booléenne s'arrête dès que le résultat est connu, ce qui accélère l'exécution du code par rapport à si tous les opérandes booléens étaient évalués.

Constante d'ensemble

L'utilisation de l'opérateur in est toujours plus efficace que l'utilisation des opérateurs équivalents <>, =, <=, >=, < et >. En effet, les comparaisons de l'intervalle peuvent être effectuées plus facilement avec l'opérateur in qu'avec les opérateurs de comparaison normaux.

Petits ensembles

Les ensembles contenant moins de 33 éléments peuvent être directement codés en utilisant une valeur de 32 bits, donc aucun appel à la bibliothèque d'exécution pour évaluer les opérandes sur ces ensembles n'est requis ; ils sont directement codés par le générateur de code.

Vérification de la portée

Les affectations de constantes aux variables sont vérifiées au moment de la compilation, ce qui élimine le besoin de générer un code de vérification de l'intervalle d'exécution.

Et au lieu de modulo

Lorsque le deuxième opérande d'un mod sur une valeur non signée est une puissance constante de 2, une instruction de Et binaire est utilisée à la place d'une division entière. Cela génère un code plus efficace.

Décalage au lieu de multiplier ou de diviser

Lorsque l'un des opérandes d'une multiplication est une puissance de deux, ils sont codés à l'aide d'instructions de décalage arithmétique, ce qui génère un code plus efficace (utilise moins de cycle d'horloge d'un microprocesseur).

De même, si le diviseur dans une opération div est une puissance de deux, il est codé à l'aide d'instructions de décalage arithmétique.

Il en va de même lors de l'accès à des index de tableau étant des puissances de deux, l'adresse est calculée à l'aide de décalages arithmétiques au lieu de l'instruction de multiplication.

Alignement automatique

Par défaut, toutes les variables supérieures à un octet sont garanties d'être alignées au moins sur une limite de mot. L'alignement sur la pile et dans la section de données dépend du microprocesseur.

Liaison intelligente

Cette fonctionnalité supprime tout le code non référencé dans le fichier exécutable final, ce qui rend le fichier exécutable beaucoup plus petit.

La liaison intelligente est activée avec le commutateur de ligne de commande -CX ou à l'aide de la directive globale {$SMARTLINK ON}.

Routines en ligne

Les routines de bibliothèque d'exécution suivantes sont codées directement dans l'exécutable final : Lo, Hi, High, SizeOf, TypeOf, Length, Pred, Succ, Inc, Dec et Assigned.

Omission du cadre de pile

Dans des conditions spécifiques, le cadre de pile sera omis et la variable sera directement accessible via le pointeur de pile.

Conditions d'omission d'un cadre de pile :

Enregistrer les variables

Lors de l'utilisation du commutateur -Or, les variables ou paramètres locaux étant très souvent utilisés seront déplacés vers les registres pour un accès plus rapide.

Spécifique au microprocesseur

Ceci répertorie les optimisations de bas niveau effectuées, microprocesseur par microprocesseur.

Spécifique au Intel 80x86

Voici une liste des techniques d'optimisation utilisées dans le compilateur :

Remarque : Si des optimisations incertaines sont activées, l'algorithme CSE suppose que :

Le résultat pratique est que vous ne pouvez pas utiliser les optimisations incertaines si vous écrivez et lisez des variables locales ou globales directement et via des pointeurs (cela inclut les paramètres Var, car ce sont également des pointeurs).

L'exemple suivant produira du mauvais code lorsque vous activerez des optimisations incertaines :

  1. Var 
  2.  Temp:LongInt;
  3.  
  4. Procedure MaProc(Var _Bar:LongInt);Begin
  5.  If(_Bar=Temp)Then Begin
  6.   Inc(_Bar);
  7.   If(_Bar<>Temp)Then Writeln('Bogue!')
  8.  End;
  9. End;
  10.  
  11. BEGIN
  12.  MaProc(Temp);
  13. END.

La raison pour laquelle il produit du mauvais code est que vous accédez à la variable globale Temp à la fois via son nom Temp et via un pointeur, dans ce cas en utilisant le paramètre de variable _Bar, n'étant rien d'autre qu'un pointeur vers Temp dans le code ci-dessus.

D'un autre côté, vous pouvez utiliser les optimisations incertaines si vous accédez à des variables ou paramètres globaux/locaux via des pointeurs, et y accédez uniquement via ce pointeur.

Par exemple :

  1. Type 
  2.  TMyRec=Record
  3.   a,b:LongInt;
  4.  End;
  5.  PMyRec=^TMyRec;
  6.  TMyRecArray=Array[1..100000]of TMyRec;
  7.  PMyRecArray=^TMyRecArray;
  8.  
  9. Var 
  10.  MyRecArrayPtr:PMyRecArray;
  11.  MyRecPtr:PMyRec;
  12.  Counter:LongInt;
  13.  
  14. BEGIN
  15.  New(MyRecArrayPtr);
  16.  For Counter:=1 to 100000 do Begin
  17.   MyRecPtr:=@MyRecArrayPtr^[Counter];
  18.   MyRecPtr^.a:=Counter;
  19.   MyRecPtr^.b:=Counter div 2;
  20.  End;
  21. END.

Produira un code correct, car la variable globale MyRecArrayPtr n'est pas accessible directement, mais uniquement via un pointeur (MyRecPtr dans ce cas).

En conclusion, on pourrait dire que l'on ne peut utiliser des optimisations incertaines que lorsqu'on sait ce que l'on fait.

Spécifique au Motorola 680x0

L'utilisation du commutateur -O2 (par défaut) effectue plusieurs optimisations dans le code produit, la plus notable étant :

Commutateurs d'optimisation

C'est ici que sont décrits les différents interrupteurs d'optimisation et leurs actions, regroupés par interrupteur :

Commutateur Description
-On: Avec n = 1..4 : ces interrupteurs activent l'optimiseur. Un niveau supérieur inclut automatiquement tous les niveaux inférieurs.
  • Le niveau 1 (-O1) active l'optimiseur de judas (les séquences d'instructions courantes sont remplacées par des équivalents plus rapides).
  • Le niveau 2 (-O2) active l'analyseur de flux de données assembleur, permettant à la procédure commune d'élimination des sous-expressions de supprimer les rechargements inutiles des registres avec les valeurs qu'ils contiennent déjà.
  • Le niveau 3 (-O3) équivaut aux optimisations de niveau 2 plus quelques optimisations fastidieuses.
  • Le niveau 4 (-O4) équivaut aux optimisations de niveau 3 plus quelques optimisations pouvant avoir des effets secondaires.
-OaX=Y Définissez l'alignement de X sur Y.
-Oo[NO XXX Activer ou désactiver des optimisations spécifiques.
-OpXXX Définissez le processeur cible pour l'optimisation sur XXX ; voir fpc -i ou fpc -ic pour les valeurs possibles.
-OWXXX Générez des commentaires d'optimisation de l'ensemble du programme pour l'optimisation XXX, voir fpc -i ou fpc -iw pour les valeurs possibles.
-OwXXX Effectuer l'optimisation de l'ensemble du programme XXX ; voir fpc -i ou fpc -iw pour les valeurs possibles.
-Os Optimisez pour la taille plutôt que pour la vitesse.

Conseils pour obtenir du code plus rapidement

Ici, quelques conseils généraux pour obtenir un meilleur code sont présentés. Ils concernent principalement le style de codage.

Conseils pour obtenir un code plus petit

Voici quelques conseils donnés pour obtenir le plus petit code possible.

Optimisation de l'ensemble du programme

Aperçu

Traditionnellement, les compilateurs optimisent un programme procédure par procédure, ou au mieux unité de compilation par unité de compilation. L'optimisation du programme complet (WPO) signifie que le compilateur prend en compte toutes les unités de compilation composant un programme ou une bibliothèque et les optimise en utilisant la connaissance combinée de la façon dont elles sont utilisées ensemble dans ce cas particulier.

La manière dont WPO fonctionne généralement est la suivante :

C'est le schéma suivi par Free Pascal.

La mise en oeuvre de ce schéma dépend fortement du compilateur. Une autre implémentation pourrait être que le compilateur génère une sorte de code intermédiaire (par exemple, du code d'octet) et que l'éditeur de liens effectue tous les WPO ainsi que la traduction vers le code machine cible.

Principes généraux

Quelques principes généraux ont été suivis lors de la conception de la mise en ouvre FPC de WPO :

Comment l'utiliser

Étape 1 : Générer un fichier de commentaires WPO

La première étape dans WPO consiste à compiler le programme (ou la bibliothèque) et toutes ses unités comme cela se ferait normalement, mais en spécifiant en plus les 2 options suivantes sur la ligne de commande :

-FW/path/to/feedbackfile.wpo -OWselected_wpo_options

La première option indique au compilateur où le fichier de commentaires WPO doit être écrit, la deuxième option indique au compilateur d'activer les optimisations WPO.

Le compilateur collectera alors, juste après que le programme ou la bibliothèque ait été lié, toutes les informations nécessaires pour exécuter les options WPO demandées lors d'une compilation ultérieure, et stockera ces informations dans le fichier indiqué.

Étape 2 : Utilisez le fichier de commentaires WPO généré

Pour appliquer réellement les options WPO, le programme (ou la bibliothèque) et tout ou partie des unités qu'il utilise, doivent être recompilés à l'aide de l'option :

-Fw/path/to/feedbackfile.wpo -Owselected_wpo_options

(Notez les petites majuscules dans le w). Cela indiquera au compilateur d'utiliser le fichier de commentaires généré à l'étape précédente. Le compilateur lira ensuite les informations collectées sur le programme lors de l'exécution précédente du compilateur et les utilisera lors de la compilation en cours des unités et/ou du programme/bibliothèque.

Les unités non recompilées lors de la deuxième passe ne seront évidemment pas optimisées, mais elles fonctionneront toujours correctement lorsqu'elles seront utilisées avec les unités et le programme/bibliothèque optimisés.

Remarque : Notez que les options doivent toujours être spécifiées sur la ligne de commande : il n'y a pas de directive source pour activer WPO, car il n'a de sens que d'utiliser WPO lors de la compilation d'un programme complet.

Optimisations WPO disponibles

Les options de ligne de commande -OW et -Ow nécessitent une liste d'options d'optimisation de l'ensemble du programme, séparées par des virgules. Ce sont des chaînes de caractères, chaque chaîne de caractères désigne une option. Voici une liste des options disponibles :

Option Description
all Cela permet toutes les optimisations disponibles du programme entier.
devirtcalls Transforme les appels de méthode virtuelle en appels de méthode normaux (statiques) lorsque le compilateur peut déterminer qu'un appel de méthode virtuelle ira toujours à la même méthode statique. Cela rend ce code à la fois plus petit et plus rapide. En général, il s'agit principalement d'une optimisation permettant d'autres optimisations, car elle rend le programme plus facile à analyser du fait qu'elle réduit le flux de contrôle indirect.

Il y a 2 limitations à cette option :
  1. La mise en oeuvre actuelle est insensible au contexte. Cela signifie que le compilateur examine uniquement le programme dans son ensemble et détermine pour chaque type de classe quelles méthodes peuvent être dévirtualisées, plutôt que d'examiner chaque instruction d'appel et le code environnant pour déterminer si cet appel peut ou non être dévirtualisé ;
  2. L'implémentation actuelle ne dévirtualise pas encore les appels de méthodes d'interface. Pas lors de leur appel via une instance d'interface, ni lors de leur appel via une instance de classe.
optvmts Cette optimisation examine quels types de classes peuvent être instanciés et quelles méthodes virtuelles peuvent être appelées dans un programme, et sur la base de ces informations, elle remplace les entrées de la table de méthodes virtuelles (VMT) ne pouvant jamais être appelées par des références à FPC_ABSTRACTERROR. Cela signifie que de telles méthodes, à moins qu'elles ne soient appelées directement via un appel hérité d'une classe/objet enfant, peuvent être supprimées par l'éditeur de liens. Cela a peu ou pas d'effet sur la vitesse, mais peut aider à réduire la taille du code.

Cette option présente 2 limitations :
  1. Les méthodes publiées, ou les getters/setters de propriétés publiées, ne peuvent jamais être optimisées de cette manière, car elles peuvent toujours être référencées et appelées via le RTTI (ce que le compilateur ne peut pas détecter).
  2. De telles optimisations ne sont pas encore effectuées pour les méthodes de classe virtuelle.
wsymbolliveness Ce paramètre n'effectue aucune optimisation à lui seul. Il indique simplement au compilateur d'enregistrer quelles fonctions/procédures ont été conservées par l'éditeur de liens dans le programme final. Lors d'une passe wpo ultérieure, le compilateur peut alors ignorer les fonctions/procédures supprimées en ce qui concerne WPO (par exemple, si un type de classe particulier n'est construit que dans une procédure inutilisée, alors ignorer cette procédure peut améliorer l'efficacité des deux précédentes optimisations).

Encore une fois, il existe certaines limites :
  1. Cette optimisation nécessite que l'utilitaire nm soit installé sur le système. Pour les binaires Linux, objdump fonctionnera également. À l'avenir, ces informations pourraient également être extraites de l'éditeur de liens interne des plateformes qu'il prend en charge.
  2. La collecte d'informations pour cette optimisation (à l'aide de -OWsymbolliveness) nécessite que la liaison intelligente soit activée (-XX) et que la suppression des symboles soit désactivée (-Xs-). Lorsque vous utilisez uniquement des informations collectées précédemment, ces limitations ne s'appliquent pas.

Format du fichier WPO

Ces informations sont particulièrement intéressantes si des données externes doivent être ajoutées au fichier de feedback WPO, par exemple à partir d'un outil de profilage. Pour une utilisation régulière de la fonctionnalité WPO, les informations suivantes ne sont pas nécessaires et peuvent être ignorées.

Le fichier est composé de commentaires et d'un certain nombre de sections. Les commentaires sont des lignes commençant par un #. Chaque section commence par "%" suivi du nom de la section (par exemple,% contextinsensitive_devirtualization).

Après cela, jusqu'à la fin du fichier ou jusqu'à la ligne suivante commençant par "%", suit d'abord une description lisible par l'homme du format de cette section (dans les commentaires), puis du contenu de la section elle-même.

Il n'y a pas de règles sur l'apparence du contenu d'une section, sauf que les lignes commençant par # sont réservées aux commentaires et les lignes commençant par % sont réservées aux marqueurs de section.



PARTAGER CETTE PAGE SUR
Dernière mise à jour : Dimanche, le 27 août 2023