[C#/。NET] LLVMを使用してマシンコードを生成する

このトピックでは、生命、宇宙、その他すべての主要な質問に対する答えを計算する関数の例を使用して、 低レベル仮想マシンを使用してマシンコードを簡単に生成および実行する方法を示します。



そして仕事のために必要なこと

Windows DLLとしてプリコンパイルされたLLVMバージョン。 CodePlex

適切なシステムフォルダー、またはテストプロジェクトの実行可能ファイルがあるフォルダーにコピーする必要があります。



C#で記述されたソースコードのバインド。

Mercurial: https : //hg01.codeplex.com/codeblock

Codeplexソースコード



実際には、ソースコードから、LLVMフォルダーにあるLLVMプロジェクトのみが必要になります。 プロジェクトはVisual Studio 2010で作成され、.NET 4.0を対象としていますが、同じ.csファイルから古いバージョンの.NETのバインダーを収集できることに注意してください。



仕事を始める



新しいC#コンソールプロジェクトを作成し、LLVMプロジェクトをソリューションに追加します。 プロジェクトから、LLVMへのリンクを作成します。



Program.csヘッダーの対応するネームスペースへのリンクを追加します(これはデフォルトでソースコードファイルと呼ばれます)。

using LLVM;

using Type = LLVM.Type;






これで、LLVMの使用を開始できます。



ターゲットプラットフォームの初期化と共通要素の作成



Context型の静的コンテキスト変数、Module型のモジュール、ExecutionEngine型のエンジンを宣言します。

static Context context;

static Module module;

static ExecutionEngine engine;






この段階でコンテキストが必要な理由は重要ではないため、グローバルLLVMコンテキストを使用します。

LLVMのモジュールは、ライブラリの一種です。 関数と静的変数の説明が含まれる場合があります。 さらに、関数定義は同じモジュールにある必要はありません。 未解決のリンクがある場合があります。

実行エンジン-プログラムの実行中に生成されたコードを直接実行します。 インタープリターでもコンパイラーでもかまいません。



次に、LLVMが実行されているシステムに必要な構造の初期化と、指定されたオブジェクトの初期化があります。

Console .Write( "initializing native target..." );

Target.InitializeNative();

Console .WriteLine( "OK" );



Console .Write( "reading global context..." );

context = Context.Global;

Console .WriteLine( "OK" );



Console .Write( "creating module..." );

module = new Module( "test" , context);

Console .WriteLine( "OK" );



Console .Write( "creating execution engine..." );

engine = new ExecutionEngine(module);

Console .WriteLine( "OK" );






42を返す



delegate int IntFunc();



private static void Function42()

{

Console .Write( "creating ret42..." );

// ret42 int(void)

var rettype = IntegerType.GetInt32(context);

var intfunc = new FunctionType(rettype);

var ret42 = module.CreateFunction( "ret42" , intfunc);

// .NET, stdcall

ret42.CallingConvention = CallingConvention.StdCallX86;



// .

//

var block = new Block( "ret42root" , context, ret42);

// - 42

var c42 = rettype.Constant(42, true );

//

//

var instructions = new InstructionBuilder(context, block);

// ,

instructions.Return(c42);

Console .WriteLine( "OK" );



Console .Write( "compiling ret42..." );

// - ,

// , LLVM

// , - -

// - ( { i32 i32 } 32- int)

var wrapper = engine.CreateWrapper(ret42, context, module);

// .NET- . LLVM

var fun = engine.GetDelegate<IntFunc>(wrapper);

Console .WriteLine( "OK" );



Console .Write( "executing..." );

Console .WriteLine(func());

}




* This source code was highlighted with Source Code Highlighter .









All Articles