mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 20:23:11 +01:00
[OCaml] Implement Llvm_linker, bindings for the IR linker
llvm-svn: 193951
This commit is contained in:
parent
2aba543196
commit
aa2a604cf0
@ -8,7 +8,7 @@
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
LEVEL := ../..
|
||||
DIRS = llvm bitreader bitwriter analysis target executionengine transforms
|
||||
DIRS = llvm bitreader bitwriter analysis target executionengine transforms linker
|
||||
ExtraMakefiles = $(PROJ_OBJ_DIR)/Makefile.ocaml
|
||||
|
||||
ocamldoc:
|
||||
|
19
bindings/ocaml/linker/Makefile
Normal file
19
bindings/ocaml/linker/Makefile
Normal 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
|
54
bindings/ocaml/linker/linker_ocaml.c
Normal file
54
bindings/ocaml/linker/linker_ocaml.c
Normal 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;
|
||||
}
|
22
bindings/ocaml/linker/llvm_linker.ml
Normal file
22
bindings/ocaml/linker/llvm_linker.ml
Normal 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"
|
27
bindings/ocaml/linker/llvm_linker.mli
Normal file
27
bindings/ocaml/linker/llvm_linker.mli
Normal 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"
|
@ -69,3 +69,11 @@ package "target" (
|
||||
archive(byte) = "llvm_target.cma"
|
||||
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"
|
||||
)
|
||||
|
63
test/Bindings/Ocaml/linker.ml
Normal file
63
test/Bindings/Ocaml/linker.ml
Normal 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
|
Loading…
Reference in New Issue
Block a user