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.
--- 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;
+}