LLVM C API Extensions: added utility conversion/data extraction routines
authorJan Vrany <jan.vrany@fit.cvut.cz>
Mon, 17 Aug 2015 09:14:38 +0100
changeset 31 5280c546bd37
parent 30 c789c1390911
child 32 1378060fadd6
LLVM C API Extensions: added utility conversion/data extraction routines * to convert metadata to values and vice-versa. * to extract bit-width from integer types. These comes handy when generating debug information.
llvm_c_ext/include/llvm-c-ext/CoreExt.h
llvm_c_ext/lib/CoreExt.cpp
--- a/llvm_c_ext/include/llvm-c-ext/CoreExt.h	Mon Aug 17 09:08:47 2015 +0100
+++ b/llvm_c_ext/include/llvm-c-ext/CoreExt.h	Mon Aug 17 09:14:38 2015 +0100
@@ -19,6 +19,8 @@
 #ifndef LLVM_BINDINGS_GO_LLVM_IRBINDINGS_H
 #define LLVM_BINDINGS_GO_LLVM_IRBINDINGS_H
 
+struct LLVMOpaqueMetadata;
+
 #if defined(__cplusplus) && !defined(__GCCXML__)
 #include "llvm-c/Core.h"
 #include "llvm/IR/Metadata.h"
@@ -58,10 +60,193 @@
 
 void LLVMMetadataReplaceAllUsesWith(LLVMMetadataRef MD, LLVMMetadataRef New);
 
+
+/**
+ * Set the current source location in the original source. This information
+ * is used to attach debug information to each instruction generated
+ * from now onwards (until a new location is set)
+ *
+ * \param Bref the IR builder in which to set the location
+ * \param Line source line of upcoming instructions
+ * \param Col source column of upcoming instructions
+ * \param Scope a scope in which the location belongs, i.e.,
+ *   a DISubroutine, a DILexicalBlock end so on.
+ * \param InlinedAt if the code is inlined, the scope in which
+ *   it is inlined
+ */
 void LLVMSetCurrentDebugLocation2(LLVMBuilderRef Bref, unsigned Line,
                                   unsigned Col, LLVMMetadataRef Scope,
                                   LLVMMetadataRef InlinedAt);
 
+/**
+ * Returns current source location as LLVM metadata (instance of DILocation).
+ * Reference to the location may be then passed to LLVMDiBuilderInsertDeclare()
+ * and LLVMDiBuilderInsertValue().
+ *
+ * \param Bref a builder from which to obtain the location
+ * \return DILocation as LLVMMetadataRef
+ *
+ * \see LLVMDiBuilderInsertDeclare()
+ * \see LLVMDiBuilderInsertValue()
+ */
+LLVMMetadataRef LLVMGetCurrentDebugLocation2(LLVMBuilderRef Bref);
+
+
+/**
+ * This enumeration defines the supported behaviors of module flags.
+ *
+ * \see llvm::Module::ModFlagBehavior
+ * \see llbm::Module::addModuleFlag()
+ * \see LLVMAddModuleFlag()
+ */
+enum LLVMModuleFlagBehavior {
+	/**
+	 * Emits an error if two values disagree, otherwise the resulting value is
+	 * that of the operands.
+	 */
+	LLVMModuleFlagBehaviorError = 1,
+
+	/**
+	 * Emits a warning if two values disagree. The result value will be the
+	 * operand for the flag from the first module being linked.
+	 */
+	LLVMModuleFlagBehaviorWarning = 2,
+
+	/**
+	 * Adds a requirement that another module flag be present and have a
+	 * specified value after linking is performed. The value must be a metadata
+	 * pair, where the first element of the pair is the ID of the module flag
+	 * to be restricted, and the second element of the pair is the value the
+	 * module flag should be restricted to. This behavior can be used to
+	 * restrict the allowable results (via triggering of an error) of linking
+	 * IDs with the **Override** behavior.
+	 */
+	LLVMModuleFlagBehaviorRequire = 3,
+
+	/**
+	 * Uses the specified value, regardless of the behavior or value of the
+	 * other module. If both modules specify **Override**, but the values
+	 * differ, an error will be emitted.
+	 */
+	LLVMModuleFlagBehaviorOverride = 4,
+
+	/**
+	 * Appends the two values, which are required to be metadata nodes.
+	 */
+	LLVMModuleFlagBehaviorAppend = 5,
+
+	/**
+	 * Appends the two values, which are required to be metadata
+	 * nodes. However, duplicate entries in the second list are dropped
+	 * during the append operation.
+	 */
+	LLVMModuleFlagBehaviorAppendUnique = 6,
+};
+
+/**
+ * Adds a flag to the module.
+ *
+ * \see llvm::Module::addModuleFlag()
+ */
+void LLVMModuleAddModuleFlag(LLVMModuleRef M, LLVMModuleFlagBehavior Behavior, const char *Key, LLVMMetadataRef Val);
+
+/**
+ * @defgroup metadataconv Metadata - Value Conversions
+ *
+ * Set of functions to convert metadata to values and back.
+ * These are useful in cases when to "call" an intrinsic function with
+ * metadata as parameters, such as @llvm.dbg.declare.
+ */
+
+/**
+ * Convert metadata node to it's value representation.
+ *
+ * \param MD metadata to convert
+ * \return metadata represented as LLVM value
+ *
+ * \see LLVMMetadataAsValueInContext()
+ */
+LLVMValueRef LLVMMetadataAsValue(LLVMMetadataRef MD);
+
+/**
+ * Convert metadata node to it's value representation in given context.
+ *
+ * \param C context in which the conversion takes place
+ * \param MD metadata to convert
+ * \return metadata represented as LLVM value
+ *
+ * \see LLVMMetadataAsValue()
+ */
+LLVMValueRef LLVMMetadataAsValueInContext(LLVMContextRef C, LLVMMetadataRef MD);
+
+
+/**
+ * Converts value to metadata.
+ *
+ * \param Value value to convert
+ * \return metadata representation of the talue
+ */
+LLVMMetadataRef LLVMValueAsMetadata(LLVMValueRef Value);
+
+/**
+ * }
+ */ // end of @defgroup metadataconv Metadata - Value Conversions
+
+
+/**
+ * @defgroup constvalconv Constant value conversions
+ *
+ * A set of functions to convert constant values represented
+ * as LLVMValueRef to numeric values.
+ *
+ * If the LLVMValueRef is not a constant value of requested type,
+ * 0 is returned. Since 0 is also a valid value, caller should
+ * first check whether the value is actually a constant value using
+ * LLVMIsConstant() and check whether the type matches:
+ *
+ * @code{.c}
+ * ...
+ * LLVMValueRef valueRef = ...;
+ * int32_t value;
+ * if( LLVMIsConstant(valueRef) &&
+ *     LLVMGetTypeKind(LLVMTypeOf(valueRef)) == LLVMIntegerTypeKind &&
+ *     LLVMGetIntTypeWidth(LLVMTypeOf(valueRef)) <= 64) {
+ *     value = LLVMValueAsSInt64();
+ * } else {
+ *     ...valurRef is not a constant value of type int64_t...
+ * }
+ *
+ * @endcode
+ *
+ * @{
+ */
+
+/**
+ * Returns a signed 64-bit integer value of given LLVMValueRef.
+ *
+ * \param Value a (constant) value of type i64 (or narrower)
+ * \return signed 64-bit integer value that passed Value encapsulates
+ *
+ * \see constvalconv
+ */
+int64_t LLVMValueAsSInt64(LLVMValueRef Value);
+
+/**
+ * Returns a unsigned 64-bit integer value of given LLVMValueRef.
+ *
+ * \param Value a (constant) value of type i64 (or narrower)
+ * \return unsigned 64-bit integer value that passed Value encapsulates
+ *
+ * \see constvalconv
+ */
+uint64_t LLVMValueAsUInt64(LLVMValueRef Value);
+
+/* TODO: Add functions for FP types and perhaps for strings.   */
+
+/**
+ * }
+ */ // end of @defgroup constvalconv Constant value conversions
+
 #ifdef __cplusplus
 }
 #endif
--- a/llvm_c_ext/lib/CoreExt.cpp	Mon Aug 17 09:08:47 2015 +0100
+++ b/llvm_c_ext/lib/CoreExt.cpp	Mon Aug 17 09:14:38 2015 +0100
@@ -22,6 +22,7 @@
 #include "llvm/IR/Function.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/Module.h"
 
 using namespace llvm;
@@ -103,3 +104,43 @@
       DebugLoc::get(Line, Col, Scope ? unwrap<MDNode>(Scope) : nullptr,
                     InlinedAt ? unwrap<MDNode>(InlinedAt) : nullptr));
 }
+
+LLVMMetadataRef LLVMGetCurrentDebugLocation2(LLVMBuilderRef Bref) {
+	return wrap(unwrap(Bref)->getCurrentDebugLocation());
+}
+
+void LLVMModuleAddModuleFlag(LLVMModuleRef M, LLVMModuleFlagBehavior Behavior, const char *Key, LLVMMetadataRef Val) {
+	unwrap(M)->addModuleFlag((Module::ModFlagBehavior)Behavior, StringRef(Key), unwrap(Val));
+}
+
+LLVMValueRef LLVMMetadataAsValue(LLVMMetadataRef MD) {
+	return LLVMMetadataAsValueInContext(LLVMGetGlobalContext(), MD);
+}
+
+LLVMValueRef LLVMMetadataAsValueInContext(LLVMContextRef C, LLVMMetadataRef MD) {
+	return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
+}
+
+LLVMMetadataRef LLVMValueAsMetadata(LLVMValueRef Value) {
+	return wrap(ValueAsMetadata::get(unwrap(Value)));
+}
+
+int64_t LLVMValueAsSInt64(LLVMValueRef Value) {
+	if (ConstantInt* CI = dyn_cast<ConstantInt>(unwrap(Value))) {
+		if (CI->getBitWidth() <= 64) {
+			return CI->getSExtValue();
+		}
+	}
+	// Not a constant integer value,
+	return 0;
+}
+
+uint64_t LLVMValueAsUInt64(LLVMValueRef Value) {
+	if (ConstantInt* CI = dyn_cast<ConstantInt>(unwrap(Value))) {
+		if (CI->getBitWidth() <= 64) {
+			return CI->getZExtValue();
+		}
+	}
+	// Not a constant integer value,
+	return 0;
+}