[OCaml] Implement Llvm_linker, bindings for the IR linker

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@193951 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Peter Zotov 2013-11-03 08:27:32 +00:00
parent 1185582dfd
commit 9d33bf70c2
7 changed files with 194 additions and 1 deletions

View File

@ -8,7 +8,7 @@
##===----------------------------------------------------------------------===## ##===----------------------------------------------------------------------===##
LEVEL := ../.. LEVEL := ../..
DIRS = llvm bitreader bitwriter analysis target executionengine transforms DIRS = llvm bitreader bitwriter analysis target executionengine transforms linker
ExtraMakefiles = $(PROJ_OBJ_DIR)/Makefile.ocaml ExtraMakefiles = $(PROJ_OBJ_DIR)/Makefile.ocaml
ocamldoc: ocamldoc:

View File

@ -0,0 +1,19 @@
##===- bindings/ocaml/linker/Makefile ----------------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
#
# This is the makefile for the Objective Caml Llvm_target interface.
#
##===----------------------------------------------------------------------===##
LEVEL := ../../..
LIBRARYNAME := llvm_linker
UsedComponents := linker
UsedOcamlInterfaces := llvm
include ../Makefile.ocaml

View File

@ -0,0 +1,54 @@
/*===-- linker_ocaml.c - LLVM Ocaml Glue ------------------------*- C++ -*-===*\
|* *|
|* The LLVM Compiler Infrastructure *|
|* *|
|* This file is distributed under the University of Illinois Open Source *|
|* License. See LICENSE.TXT for details. *|
|* *|
|*===----------------------------------------------------------------------===*|
|* *|
|* This file glues LLVM's OCaml interface to its C interface. These functions *|
|* are by and large transparent wrappers to the corresponding C functions. *|
|* *|
|* Note that these functions intentionally take liberties with the CAMLparamX *|
|* macros, since most of the parameters are not GC heap objects. *|
|* *|
\*===----------------------------------------------------------------------===*/
#include "llvm-c/Linker.h"
#include "caml/alloc.h"
#include "caml/memory.h"
#include "caml/fail.h"
static value llvm_linker_error_exn;
CAMLprim value llvm_register_linker_exns(value Error) {
llvm_linker_error_exn = Field(Error, 0);
register_global_root(&llvm_linker_error_exn);
return Val_unit;
}
static void llvm_raise(value Prototype, char *Message) {
CAMLparam1(Prototype);
CAMLlocal1(CamlMessage);
CamlMessage = copy_string(Message);
LLVMDisposeMessage(Message);
raise_with_arg(Prototype, CamlMessage);
abort(); /* NOTREACHED */
#ifdef CAMLnoreturn
CAMLnoreturn; /* Silences warnings, but is missing in some versions. */
#endif
}
/* llmodule -> llmodule -> Mode.t -> unit
raises Error msg on error */
CAMLprim value llvm_link_modules(LLVMModuleRef Dst, LLVMModuleRef Src, value Mode) {
char* Message;
if (LLVMLinkModules(Dst, Src, Int_val(Mode), &Message))
llvm_raise(llvm_linker_error_exn, Message);
return Val_unit;
}

View File

@ -0,0 +1,22 @@
(*===-- llvm_linker.ml - LLVM OCaml Interface ------------------*- OCaml -*-===*
*
* The LLVM Compiler Infrastructure
*
* This file is distributed under the University of Illinois Open Source
* License. See LICENSE.TXT for details.
*
*===----------------------------------------------------------------------===*)
exception Error of string
external register_exns : exn -> unit = "llvm_register_linker_exns"
let _ = register_exns (Error "")
module Mode = struct
type t =
| DestroySource
| PreserveSource
end
external link_modules : Llvm.llmodule -> Llvm.llmodule -> Mode.t -> unit
= "llvm_link_modules"

View File

@ -0,0 +1,27 @@
(*===-- llvm_linker.mli - LLVM OCaml Interface -----------------*- OCaml -*-===*
*
* The LLVM Compiler Infrastructure
*
* This file is distributed under the University of Illinois Open Source
* License. See LICENSE.TXT for details.
*
*===----------------------------------------------------------------------===*)
(** Linker.
This interface provides an OCaml API for LLVM bitcode linker,
the classes in the Linker library. *)
exception Error of string
(** Linking mode. *)
module Mode : sig
type t =
| DestroySource
| PreserveSource
end
(** [link_modules dst src mode] links [src] into [dst], raising [Error]
if the linking fails. *)
external link_modules : Llvm.llmodule -> Llvm.llmodule -> Mode.t -> unit
= "llvm_link_modules"

View File

@ -69,3 +69,11 @@ package "target" (
archive(byte) = "llvm_target.cma" archive(byte) = "llvm_target.cma"
archive(native) = "llvm_target.cmxa" archive(native) = "llvm_target.cmxa"
) )
package "linker" (
requires = "llvm"
version = "@PACKAGE_VERSION@"
description = "Intermediate Representation Linker for LLVM"
archive(byte) = "llvm_linker.cma"
archive(native) = "llvm_linker.cmxa"
)

View File

@ -0,0 +1,63 @@
(* RUN: rm -rf %t.builddir
* RUN: mkdir -p %t.builddir
* RUN: cp %s %t.builddir
* RUN: %ocamlopt -warn-error A llvm.cmxa llvm_linker.cmxa %t.builddir/linker.ml -o %t
* RUN: %t
* XFAIL: vg_leak
*)
(* Note: It takes several seconds for ocamlopt to link an executable with
libLLVMCore.a, so it's better to write a big test than a bunch of
little ones. *)
open Llvm
open Llvm_linker
let context = global_context ()
let void_type = Llvm.void_type context
(* Tiny unit test framework - really just to help find which line is busted *)
let print_checkpoints = false
let suite name f =
if print_checkpoints then
prerr_endline (name ^ ":");
f ()
(*===-- Linker -----------------------------------------------------------===*)
let test_linker () =
let fty = function_type void_type [| |] in
let make_module name =
let m = create_module context name in
let fn = define_function ("fn_" ^ name) fty m in
ignore (build_ret_void (builder_at_end context (entry_block fn)));
m
in
let m1 = make_module "one"
and m2 = make_module "two" in
link_modules m1 m2 Mode.PreserveSource;
dispose_module m1;
dispose_module m2;
let m1 = make_module "one"
and m2 = make_module "two" in
link_modules m1 m2 Mode.DestroySource;
dispose_module m1;
let m1 = make_module "one"
and m2 = make_module "one" in
try
link_modules m1 m2 Mode.PreserveSource;
failwith "must raise"
with Error _ ->
dispose_module m1;
dispose_module m2
(*===-- Driver ------------------------------------------------------------===*)
let _ =
suite "linker" test_linker