Skip to content

Commit

Permalink
[OCaml] Impement Llvm_irreader, bindings to LLVM assembly parser
Browse files Browse the repository at this point in the history
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@194138 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
whitequark committed Nov 6, 2013
1 parent c6099db commit ec7270c
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 1 deletion.
3 changes: 2 additions & 1 deletion bindings/ocaml/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
##===----------------------------------------------------------------------===##

LEVEL := ../..
DIRS = llvm bitreader bitwriter analysis target executionengine transforms linker
DIRS = llvm bitreader bitwriter irreader analysis target executionengine \
transforms linker
ExtraMakefiles = $(PROJ_OBJ_DIR)/Makefile.ocaml

ocamldoc:
Expand Down
19 changes: 19 additions & 0 deletions bindings/ocaml/irreader/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
##===- bindings/ocaml/irreader/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_irreader interface.
#
##===----------------------------------------------------------------------===##

LEVEL := ../../..
LIBRARYNAME := llvm_irreader
UsedComponents := irreader
UsedOcamlInterfaces := llvm

include ../Makefile.ocaml
59 changes: 59 additions & 0 deletions bindings/ocaml/irreader/irreader_ocaml.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*===-- irreader_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. *|
|* *|
\*===----------------------------------------------------------------------===*/

#include "llvm-c/IRReader.h"
#include "caml/alloc.h"
#include "caml/fail.h"
#include "caml/memory.h"

/* Can't use the recommended caml_named_value mechanism for backwards
compatibility reasons. This is largely equivalent. */
static value llvm_irreader_error_exn;

CAMLprim value llvm_register_irreader_exns(value Error) {
llvm_irreader_error_exn = Field(Error, 0);
register_global_root(&llvm_irreader_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
}


/*===-- Modules -----------------------------------------------------------===*/

/* Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule */
CAMLprim value llvm_parse_ir(LLVMContextRef C,
LLVMMemoryBufferRef MemBuf) {
CAMLparam0();
CAMLlocal2(Variant, MessageVal);
LLVMModuleRef M;
char *Message;

if (LLVMParseIRInContext(C, MemBuf, &M, &Message))
llvm_raise(llvm_irreader_error_exn, Message);

CAMLreturn((value) M);
}
17 changes: 17 additions & 0 deletions bindings/ocaml/irreader/llvm_irreader.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
(*===-- llvm_irreader.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_irreader_exns"
let _ = register_exns (Error "")

external parse_ir : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule
= "llvm_parse_ir"
21 changes: 21 additions & 0 deletions bindings/ocaml/irreader/llvm_irreader.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
(*===-- llvm_irreader.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.
*
*===----------------------------------------------------------------------===*)

(** IR reader.
This interface provides an OCaml API for the LLVM assembly reader, the
classes in the IRReader library. *)

exception Error of string

(** [parse_ir context mb] parses the IR for a new module [m] from the
memory buffer [mb] in the context [context]. Returns [m] if successful, or
raises [Error msg] otherwise, where [msg] is a description of the error
encountered. See the function [llvm::ParseIR]. *)
val parse_ir : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule
8 changes: 8 additions & 0 deletions bindings/ocaml/llvm/META.llvm.in
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ package "ipo" (
archive(native) = "llvm_ipo.cmxa"
)

package "irreader" (
requires = "llvm"
version = "@PACKAGE_VERSION@"
description = "IR assembly reader for LLVM"
archive(byte) = "llvm_irreader.cma"
archive(native) = "llvm_irreader.cmxa"
)

package "scalar_opts" (
requires = "llvm"
version = "@PACKAGE_VERSION@"
Expand Down
59 changes: 59 additions & 0 deletions test/Bindings/Ocaml/irreader.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
(* RUN: rm -rf %t.builddir
* RUN: mkdir -p %t.builddir
* RUN: cp %s %t.builddir
* RUN: %ocamlopt -g -warn-error A llvm.cmxa llvm_irreader.cmxa %t.builddir/irreader.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_irreader

let context = global_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 ()

let _ =
Printexc.record_backtrace true

let insist cond =
if not cond then failwith "insist"


(*===-- IR Reader ---------------------------------------------------------===*)

let test_irreader () =
begin
let buf = MemoryBuffer.of_string "@foo = global i32 42" in
let m = parse_ir context buf in
match lookup_global "foo" m with
| Some foo ->
insist ((global_initializer foo) = (const_int (i32_type context) 42))
| None ->
failwith "global"
end;

begin
let buf = MemoryBuffer.of_string "@foo = global garble" in
try
ignore (parse_ir context buf);
failwith "parsed"
with Llvm_irreader.Error _ ->
()
end


(*===-- Driver ------------------------------------------------------------===*)

let _ =
suite "irreader" test_irreader

0 comments on commit ec7270c

Please sign in to comment.