diff --git a/Xcode/LLVM.xcodeproj/project.pbxproj b/Xcode/LLVM.xcodeproj/project.pbxproj index a195dbda590..97f73286617 100644 --- a/Xcode/LLVM.xcodeproj/project.pbxproj +++ b/Xcode/LLVM.xcodeproj/project.pbxproj @@ -137,6 +137,11 @@ 9F7794870C73D51000551F9C /* LLVMBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLVMBuilder.h; sourceTree = ""; }; 9F7794880C73D51000551F9C /* MemoryBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryBuffer.h; sourceTree = ""; }; 9F7794890C73D51000551F9C /* Streams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Streams.h; sourceTree = ""; }; + 9F7C23E50CB81C2100498408 /* Analysis.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Analysis.h; sourceTree = ""; }; + 9F7C23E60CB81C2B00498408 /* Analysis.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Analysis.cpp; sourceTree = ""; }; + 9F7C240C0CB81ECD00498408 /* analysis_ocaml.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = analysis_ocaml.c; sourceTree = ""; }; + 9F7C240D0CB81ECD00498408 /* llvm_analysis.ml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = llvm_analysis.ml; sourceTree = ""; }; + 9F7C240E0CB81ECD00498408 /* llvm_analysis.mli */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = llvm_analysis.mli; sourceTree = ""; }; 9FA638D90C77B184007F12AE /* AutoUpgrade.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AutoUpgrade.h; sourceTree = ""; }; 9FA638DA0C77B184007F12AE /* GlobalAlias.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = GlobalAlias.h; sourceTree = ""; }; 9FA638DB0C77B1AB007F12AE /* APInt.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = APInt.h; sourceTree = ""; }; @@ -166,7 +171,6 @@ 9FE25D900CAB166D005383FC /* APFloat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APFloat.h; sourceTree = ""; }; 9FE25D910CAB166D005383FC /* SparseBitVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SparseBitVector.h; sourceTree = ""; }; 9FE25D920CAB169F005383FC /* RegisterCoalescer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterCoalescer.h; sourceTree = ""; }; - 9FE25D930CAB16D8005383FC /* PostDominatorCalculation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PostDominatorCalculation.h; sourceTree = ""; }; 9FE25D940CAB16FB005383FC /* RegisterCoalescer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterCoalescer.cpp; sourceTree = ""; }; 9FE25D950CAB1724005383FC /* APFloat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = APFloat.cpp; sourceTree = ""; }; 9FE25D960CAB1759005383FC /* TargetCallingConv.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TargetCallingConv.td; sourceTree = ""; }; @@ -1156,6 +1160,16 @@ path = MSIL; sourceTree = ""; }; + 9F7C240B0CB81ECD00498408 /* analysis */ = { + isa = PBXGroup; + children = ( + 9F7C240C0CB81ECD00498408 /* analysis_ocaml.c */, + 9F7C240D0CB81ECD00498408 /* llvm_analysis.ml */, + 9F7C240E0CB81ECD00498408 /* llvm_analysis.mli */, + ); + path = analysis; + sourceTree = ""; + }; 9FA638E90C77B252007F12AE /* IPO */ = { isa = PBXGroup; children = ( @@ -1176,6 +1190,7 @@ 9FD3E56F0CA0116100E54D15 /* ocaml */ = { isa = PBXGroup; children = ( + 9F7C240B0CB81ECD00498408 /* analysis */, 9FD3E5700CA0116100E54D15 /* bitwriter */, 9FD3E57A0CA0116100E54D15 /* llvm */, ); @@ -1217,6 +1232,7 @@ CF8F1B480B64F7AB00BB4199 /* include/llvm-c */ = { isa = PBXGroup; children = ( + 9F7C23E50CB81C2100498408 /* Analysis.h */, 9FD3E58D0CA0125F00E54D15 /* BitWriter.h */, 9FD3E58E0CA0125F00E54D15 /* Core.h */, CF8F1B490B64F7AB00BB4199 /* LinkTimeOptimizer.h */, @@ -1381,15 +1397,13 @@ DE66ECBD08ABEC0700323D32 /* lib/Analysis */ = { isa = PBXGroup; children = ( - 9FE25D930CAB16D8005383FC /* PostDominatorCalculation.h */, - 9F68EB010C77AD02004AA152 /* LoopPass.cpp */, - 9F68EB020C77AD02004AA152 /* MemoryDependenceAnalysis.cpp */, DE66ED1A08ABEC0800323D32 /* IPA */, DE66ECBE08ABEC0700323D32 /* AliasAnalysis.cpp */, DE66ECBF08ABEC0700323D32 /* AliasAnalysisCounter.cpp */, DE66ECC008ABEC0700323D32 /* AliasAnalysisEvaluator.cpp */, CF8F1B4D0B64F80700BB4199 /* AliasDebugger.cpp */, DE66ECC108ABEC0700323D32 /* AliasSetTracker.cpp */, + 9F7C23E60CB81C2B00498408 /* Analysis.cpp */, DE66ECC208ABEC0700323D32 /* BasicAliasAnalysis.cpp */, DE66ECC308ABEC0700323D32 /* CFGPrinter.cpp */, CF73C0B0098A523C00627152 /* ConstantFolding.cpp */, @@ -1398,6 +1412,8 @@ DE66ED1908ABEC0800323D32 /* IntervalPartition.cpp */, DE66ED3308ABEC0800323D32 /* LoadValueNumbering.cpp */, DE66ED3408ABEC0800323D32 /* LoopInfo.cpp */, + 9F68EB010C77AD02004AA152 /* LoopPass.cpp */, + 9F68EB020C77AD02004AA152 /* MemoryDependenceAnalysis.cpp */, DE66ED3608ABEC0800323D32 /* PostDominators.cpp */, DE66ED3708ABEC0800323D32 /* ProfileInfo.cpp */, DE66ED3808ABEC0800323D32 /* ProfileInfoLoader.cpp */, diff --git a/bindings/ocaml/Makefile b/bindings/ocaml/Makefile index 0fc6b1b6eef..a3bbae00940 100644 --- a/bindings/ocaml/Makefile +++ b/bindings/ocaml/Makefile @@ -8,6 +8,6 @@ ##===----------------------------------------------------------------------===## LEVEL := ../.. -DIRS = llvm bitwriter +DIRS = llvm bitwriter analysis include $(LEVEL)/Makefile.common diff --git a/bindings/ocaml/Makefile.ocaml b/bindings/ocaml/Makefile.ocaml index 278b31ea322..fb03b1a3e24 100644 --- a/bindings/ocaml/Makefile.ocaml +++ b/bindings/ocaml/Makefile.ocaml @@ -10,6 +10,11 @@ # An ocaml library is a unique project type in the context of LLVM, so rules are # here rather than in Makefile.rules. # +# Reference materials on installing ocaml libraries: +# +# https://fedoraproject.org/wiki/Packaging/OCaml +# http://pkg-ocaml-maint.alioth.debian.org/ocaml_packaging_policy.txt +# ##===----------------------------------------------------------------------===## include $(LEVEL)/Makefile.config @@ -188,7 +193,6 @@ install-cma:: $(OutputCMA) $(Verb) $(MKDIR) $(PROJ_libocamldir) $(Verb) $(DataInstall) $(OutputCMA) "$(DestCMA)" $(Verb) for i in $(UsedLibNames); do \ - $(EchoCmd) "Installing $(BuildMode) $(PROJ_libocamldir)/$$i"; \ ln -sf "$(PROJ_libdir)/$$i" "$(PROJ_libocamldir)/$$i"; \ done @@ -196,7 +200,6 @@ uninstall-cma:: $(Echo) "Uninstalling $(DestCMA)" -$(Verb) $(RM) -f $(DestCMA) $(Verb) for i in $(UsedLibNames); do \ - $(EchoCmd) "Uninstalling $(PROJ_libocamldir)/$$i"; \ $(RM) -f "$(PROJ_libocamldir)/$$i"; \ done diff --git a/bindings/ocaml/analysis/Makefile b/bindings/ocaml/analysis/Makefile new file mode 100644 index 00000000000..e910043f532 --- /dev/null +++ b/bindings/ocaml/analysis/Makefile @@ -0,0 +1,20 @@ +##===- bindings/ocaml/analysis/Makefile --------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file was developed by Gordon Henriksen and is distributed under the +# University of Illinois Open Source License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml Llvm_analysis interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +LIBRARYNAME := llvm_analysis +DONT_BUILD_RELINKED := 1 +UsedComponents := analysis +UsedOcamlInterfaces := llvm + +include ../Makefile.ocaml diff --git a/bindings/ocaml/analysis/analysis_ocaml.c b/bindings/ocaml/analysis/analysis_ocaml.c new file mode 100644 index 00000000000..cc1098a3749 --- /dev/null +++ b/bindings/ocaml/analysis/analysis_ocaml.c @@ -0,0 +1,60 @@ +/*===-- analysis_ocaml.c - LLVM Ocaml Glue ----------------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file was developed by Gordon Henriksen and 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/Analysis.h" +#include "caml/alloc.h" +#include "caml/mlvalues.h" +#include "caml/memory.h" + + +/* Llvm.llmodule -> string option */ +CAMLprim value llvm_verify_module(LLVMModuleRef M) { + CAMLparam0(); + CAMLlocal2(String, Option); + + char *Message; + int Result = LLVMVerifyModule(M, LLVMReturnStatusAction, &Message); + + if (0 == Result) { + Option = Val_int(0); + } else { + Option = alloc(1, 1); + String = copy_string(Message); + Store_field(Option, 0, String); + } + + LLVMDisposeVerifierMessage(Message); + + CAMLreturn(Option); +} + +/* Llvm.llvalue -> bool */ +CAMLprim value llvm_verify_function(LLVMValueRef Fn) { + return Val_bool(LLVMVerifyFunction(Fn, LLVMReturnStatusAction) == 0); +} + +/* Llvm.llmodule -> unit */ +CAMLprim value llvm_assert_valid_module(LLVMModuleRef M) { + LLVMVerifyModule(M, LLVMAbortProcessAction, 0); + return Val_unit; +} + +/* Llvm.llvalue -> unit */ +CAMLprim value llvm_assert_valid_function(LLVMValueRef Fn) { + LLVMVerifyFunction(Fn, LLVMAbortProcessAction); + return Val_unit; +} diff --git a/bindings/ocaml/analysis/llvm_analysis.ml b/bindings/ocaml/analysis/llvm_analysis.ml new file mode 100644 index 00000000000..a972aa0856e --- /dev/null +++ b/bindings/ocaml/analysis/llvm_analysis.ml @@ -0,0 +1,24 @@ +(*===-- llvm_analysis.ml - LLVM Ocaml Interface -----------------*- C++ -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file was developed by Gordon Henriksen and is distributed under the + * University of Illinois Open Source License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------=== + * + * This interface provides an ocaml API for LLVM IR analyses, the classes in + * the Analysis library. + * + *===----------------------------------------------------------------------===*) + + +external verify_module : Llvm.llmodule -> string option = "llvm_verify_module" + +external verify_function : Llvm.llvalue -> bool = "llvm_verify_function" + +external assert_valid_module : Llvm.llmodule -> unit + = "llvm_assert_valid_module" + +external assert_valid_function : Llvm.llvalue -> unit + = "llvm_assert_valid_function" diff --git a/bindings/ocaml/analysis/llvm_analysis.mli b/bindings/ocaml/analysis/llvm_analysis.mli new file mode 100644 index 00000000000..59ff6c661ca --- /dev/null +++ b/bindings/ocaml/analysis/llvm_analysis.mli @@ -0,0 +1,24 @@ +(*===-- llvm_analysis.mli - LLVM Ocaml Interface ----------------*- C++ -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file was developed by Gordon Henriksen and is distributed under the + * University of Illinois Open Source License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------=== + * + * This interface provides an ocaml API for LLVM IR analyses, the classes in + * the Analysis library. + * + *===----------------------------------------------------------------------===*) + + +external verify_module : Llvm.llmodule -> string option = "llvm_verify_module" + +external verify_function : Llvm.llvalue -> bool = "llvm_verify_function" + +external assert_valid_module : Llvm.llmodule -> unit + = "llvm_assert_valid_module" + +external assert_valid_function : Llvm.llvalue -> unit + = "llvm_assert_valid_function" diff --git a/bindings/ocaml/bitwriter/Makefile b/bindings/ocaml/bitwriter/Makefile index 953ab4c082b..e7d2f7fcf56 100644 --- a/bindings/ocaml/bitwriter/Makefile +++ b/bindings/ocaml/bitwriter/Makefile @@ -1,17 +1,13 @@ -##===- bindings/ocaml/llvm/Makefile ------------------------*- Makefile -*-===## +##===- bindings/ocaml/bitwriter/Makefile -------------------*- Makefile -*-===## # # The LLVM Compiler Infrastructure # -# This file was developed by the LLVM research group and is distributed under -# the University of Illinois Open Source License. See LICENSE.TXT for details. +# This file was developed by Gordon Henriksen and is distributed under the +# University of Illinois Open Source License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## # -# This is the makefile for the llvm-ml interface. Reference materials on -# installing ocaml libraries: -# -# https://fedoraproject.org/wiki/Packaging/OCaml -# http://pkg-ocaml-maint.alioth.debian.org/ocaml_packaging_policy.txt +# This is the makefile for the Objective Caml Llvm_bitwriter interface. # ##===----------------------------------------------------------------------===## diff --git a/bindings/ocaml/llvm/Makefile b/bindings/ocaml/llvm/Makefile index cbfb75ca157..24374680847 100644 --- a/bindings/ocaml/llvm/Makefile +++ b/bindings/ocaml/llvm/Makefile @@ -2,16 +2,12 @@ # # The LLVM Compiler Infrastructure # -# This file was developed by the LLVM research group and is distributed under -# the University of Illinois Open Source License. See LICENSE.TXT for details. +# This file was developed by Gordon Henriksen and is distributed under the +# University of Illinois Open Source License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## # -# This is the makefile for the llvm-ml interface. Reference materials on -# installing ocaml libraries: -# -# https://fedoraproject.org/wiki/Packaging/OCaml -# http://pkg-ocaml-maint.alioth.debian.org/ocaml_packaging_policy.txt +# This is the makefile for the Objective Caml Llvm interface. # ##===----------------------------------------------------------------------===## diff --git a/include/llvm-c/Analysis.h b/include/llvm-c/Analysis.h new file mode 100644 index 00000000000..b57577b0588 --- /dev/null +++ b/include/llvm-c/Analysis.h @@ -0,0 +1,53 @@ +/*===-- llvm-c/Analysis.h - Analysis Library C Interface --------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file was developed by Gordon Henriksen and is distributed under the *| +|* University of Illinois Open Source License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMAnalysis.a, which *| +|* implements various analyses of the LLVM IR. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_ANALYSIS_H +#define LLVM_C_ANALYSIS_H + +#include "llvm-c/Core.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef enum { + LLVMAbortProcessAction, /* verifier will print to stderr and abort() */ + LLVMPrintMessageAction, /* verifier will print to stderr and return 1 */ + LLVMReturnStatusAction /* verifier will just return 1 */ +} LLVMVerifierFailureAction; + + +/* Verifies that a module is valid, taking the specified action if not. + Optionally returns a human-readable description of any invalid constructs. */ +int LLVMVerifyModule(LLVMModuleRef M, LLVMVerifierFailureAction Action, + char **OutMessage); + +/* Disposes of the message allocated by the verifier, if any. */ +void LLVMDisposeVerifierMessage(char *Message); + +/* Verifies that a single function is valid, taking the specified action. Useful + for debugging. */ +int LLVMVerifyFunction(LLVMValueRef Fn, LLVMVerifierFailureAction Action); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/Analysis/Analysis.cpp b/lib/Analysis/Analysis.cpp new file mode 100644 index 00000000000..6403f2d7faf --- /dev/null +++ b/lib/Analysis/Analysis.cpp @@ -0,0 +1,38 @@ +//===-- Analysis.cpp ------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Gordon Henriksen and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm-c/Analysis.h" +#include "llvm/Analysis/Verifier.h" +#include + +using namespace llvm; + +int LLVMVerifyModule(LLVMModuleRef M, LLVMVerifierFailureAction Action, + char **OutMessages) { + std::string Messages; + + int Result = verifyModule(*unwrap(M), + static_cast(Action), + OutMessages? &Messages : 0); + + if (OutMessages) + *OutMessages = strdup(Messages.c_str()); + + return Result; +} + +void LLVMDisposeVerifierMessage(char *Message) { + free(Message); +} + +int LLVMVerifyFunction(LLVMValueRef Fn, LLVMVerifierFailureAction Action) { + return verifyFunction(*unwrap(Fn), + static_cast(Action)); +} + diff --git a/lib/Bitcode/Writer/BitWriter.cpp b/lib/Bitcode/Writer/BitWriter.cpp index 8f562e98d9f..aadd878e153 100644 --- a/lib/Bitcode/Writer/BitWriter.cpp +++ b/lib/Bitcode/Writer/BitWriter.cpp @@ -2,8 +2,8 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. +// This file was developed by Gordon Henriksen and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// diff --git a/test/Bindings/Ocaml/analysis.ml b/test/Bindings/Ocaml/analysis.ml new file mode 100644 index 00000000000..bf756169f48 --- /dev/null +++ b/test/Bindings/Ocaml/analysis.ml @@ -0,0 +1,46 @@ +(* RUN: %ocamlc llvm.cma llvm_analysis.cma %s -o %t + * RUN: ./%t %t.bc + *) + +open Llvm +open Llvm_analysis + +(* Note that this takes a moment to link, so it's best to keep the number of + individual tests low. *) + +let test x = if not x then exit 1 else () + +let bomb msg = + prerr_endline msg; + exit 2 + +let _ = + let fty = function_type void_type [| |] in + let m = create_module "valid_m" in + let fn = define_function "valid_fn" fty m in + let at_entry = builder_at_end (entry_block fn) in + ignore (build_ret_void at_entry); + + + (* Test that valid constructs verify. *) + match verify_module m with + Some msg -> bomb "valid module failed verification!" + | None -> (); + + if not (verify_function fn) then bomb "valid function failed verification!"; + + + (* Test that invalid constructs do not verify. + A basic block can contain only one terminator instruction. *) + ignore (build_ret_void at_entry); + + match verify_module m with + Some msg -> () + | None -> bomb "invalid module passed verification!"; + + if verify_function fn then bomb "invalid function passed verification!"; + + + dispose_module m + + (* Don't bother to test assert_valid_{module,function}. *)