Introduction

Ce didacticiel est destiné aux utilisateurs maîtrisant la programmation en C ou C++, ainsi que l'architecture de la Simple Virtual Machine.

Dans ce didacticiel, vous allez découvrir l'outil de génération d'extension de la machine virtuelle.

Le temps de lecture de ce didacticiel est estimé à 15 minutes.

Mise en place

Pour commencer, créez le canevas de l'application dans le fichier exécutable generation.svm en utilisant ce code :

#!/usr/bin/env svm
DESCRIPTION
Plugin generation exploration
END
LOG
DEBUG "Plugin generation"
PROCESS "application"
	CODE "main" INLINE
		:debug BREAK
	END
END

Génération d'une extension

Ecriture de l'extension

L'écriture d'une extension de la Simple Virtual Machine peut très bien se faire sans outil particulier, mais cela n'est recommandé que pour ses vertus d'apprentissage profond.

Ici, nous allons plutôt employer un outil (fourni avec la machine virtuelle) permettant de faciliter et raccourcir l'écriture des extensions.

Dans le même répertoire que le fichier generation.svm, ouvrez un autre fichier generation.svm_plugin avec votre éditeur de texte préféré, puis ajoutez-y ce code :

PLUGIN generation

DEFINE

TYPE generation.counter
%{
	explicit type_counter(const size_t l)
	:_counter(0), _limit(l) {}
	type_counter(const type_counter& c)
	:_counter(c._counter), _limit(c._limit) {}
	operator std::string () const
	{
		std::ostringstream oss;
		oss << _counter << "/" << _limit;
		return oss.str();
	}
	size_t _counter;
	size_t _limit;
%}
delete default: %{}
copy default: %{}
print default: %{}

INSTRUCTION generation.new INT -> generation.counter
%{
	auto l = ARGV_VALUE(0,integer);
	if(l<0)
	{
		ERROR_INTERNAL(NUMERIC,"Invalid limit");
	}
	return NEW_PLUGIN(generation,counter,new type_counter(static_cast<size_t>(l)));
%}

INSTRUCTION generation.touch MUTABLE generation.counter
%{
	auto c = ARGV_PLUGIN(0,generation,counter);
	++c->_counter;
%}

INSTRUCTION generation.check generation.counter -> BLN
%{
	auto c = ARGV_PLUGIN(0,generation,counter);
	return ::svm_value_boolean_new__raw(svm,c->_counter<c->_limit);
%}

Et sauvegardez ce fichier.

Pour le moment, la syntaxe de ce fichier n'est pas importante. Elle sera détaillée dans plusieurs didacticiels à venir.

Génération du code C/C++

Lors de l'installation de la machine virtuelle, un binaire appellé svm_plugin est également installé sur le système. C'est ce binaire qui permet de transformer le fichier vu ci-dessus pour le transformer en code C/C++.

Invoquez le générateur d'extension :

svm_plugin -fi generation.svm_plugin | bash
Plugin generator for Simple Virtual Machine 2.1.20230101
Use -h option for help
Reading plugin definition from file generation.svm_plugin... OK
Parsing plugin definition... OK
Generating and parsing plugin configuration string... OK
Generating plugin files... OK
Generating plugin creation shell script to stdout... OK
Generating plugin generation in directory svmplugingeneration

Generated files:
AUTHORS
ChangeLog
Makefile.am
Makefile.inc
Makefile.local
NEWS
README
configure.ac
doc/Makefile.am
doc/svm_plugin_generation.man
plugin_configuration_string
plugin_install
src/Makefile.am
src/plugin.cpp
src/plugin.h
test/Makefile.am

For common installations of this plugin, you can use the provided install script.
For more details, execute:

./svmplugingeneration/plugin_install -h

Notez que la sortie du générateur est redirigée vers bash : en effet, le générateur produit un script shell qui doit être exécuté.

Vous pouvez entrer dans le répertoire contenant le code C/C++ de l'extension et regarder les fichiers générés. Les deux fichiers ayant le plus de contenu propre à l'extension sont :

Compilation et installation

Pour compiler l'extension, vous pouvez utiliser le script d'installation généré :

./svmplugingeneration/plugin_install -l
g++ -std=c++14 -o src/plugin.o -c src/plugin.cpp -fPIC -DPIC  -I.
g++ -std=c++14 -shared -o libsvmgeneration.so -fPIC -DPIC -Wl,-L/usr/local/lib/svm -lsvmplugininterface -Wl,-soname -Wl,libsvmgeneration.so   src/plugin.o

Le fichier résultat est un .so (le résultat de cette commande peut varier selon les systèmes d'exploitation) :

file ./svmplugingeneration/libsvmgeneration.so 
svmplugingeneration/libsvmgeneration.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, not stripped

Notez que le générateur d'extension fournit également un canevas minimal pour installer l'extension en utilisant les autotools. Référez vous à la documentation des autotools pour plus d'informations sur ce type d'installation.

Utilisation d'une extension générée

Ajout de l'extension

Pour inclure la nouvelle extension, modifiez le code :

#!/usr/bin/env svm
DESCRIPTION
Plugin generation exploration
END
LOG
DEBUG "Plugin generation"
LOCAL PLUGIN "svmplugingeneration/libsvmgeneration.so"
PROCESS "application"
	CODE "main" INLINE
		:debug BREAK
	END
END

Vous pouvez lancez l'application en mode débugueur, et regarder la fenêtre des extensions :

Plugin generation
Plugins
Definitions
TYPE generation.counter
INSTRUCTION generation.check generation.counter -> BLN
INSTRUCTION generation.new INT -> generation.counter
INSTRUCTION generation.touch MUTABLE generation.counter
in
Filter

Vous y trouvez les objets tels que définis dans le fichier d'extension proposé en exemple.

Modification du code

Modifiez le code pour utiliser l'extension :

#!/usr/bin/env svm
DESCRIPTION
Plugin generation exploration
END
LOG
DEBUG "Plugin generation"
LOCAL PLUGIN "svmplugingeneration/libsvmgeneration.so"
PLUGIN "svmcom.so"
PROCESS "application"
	CODE "main" INLINE
		:debug BREAK
		:memory generation.counter/c, BLN/b
		:generation.new 3 -> &c
	:label loop
		:com.message @&c
		:generation.touch @&c
		:generation.check @&c -> &b
		:goto loop :when @&b TRUE
		:com.message @&c
	END
END

Puis lancez l'application :

./generation.svm
0/3
1/3
2/3
3/3

L'extension présentée ici n'a rien de phénoménal, car elle définit un simple compteur avec une limite qui peut être utilisé comme compteur de boucle, entre autres utilisations.

Conclusion

Vous venez de voir comment générer une extension pour la machine virtuelle.

La capacité à pouvoir écrire ses propres extensions permet d'une part de répondre aux exigences de performance des applications : lorsque le langage de la machine s'avère trop lent pour réaliser un calcul, le transcrire en C/C++ permet de l'exécuter beaucoup plus rapidement sans toutefois être contraint de tout exprimer en C/C++.

Cela permet d'autre part de répondre à des besoins spécifiques en termes de stockage ou de comportement, que la machine ne peut pas supporter de part sa généricité.

Enfin, les extensions permettent d'isoler les différents aspects d'une application, de les tester séparément pour une plus grande robustesse d'exécution, et de pouvoir employer rapidement les contributions (libres ou propriétaires) des autres utilisateurs de la Simple Virtual Machine.