[llvm-commits] [PATCH] Add helper functions to ConstantInt and ConstantFP to accept strings.
Erick Tryzelaar
idadesub at users.sourceforge.net
Tue Aug 11 20:42:01 PDT 2009
This patch adds some simple wrappers functions to convert strings
into constants, and exposes these functions to llvm-c and ocaml. It
also removes some redundant code from Core.cpp.
I do have an question though. I was able to do vector splatting with
the ConstantFP/string, but I couldn't figure out how to do it with
the ConstantInt/string. Does anyone know how to do this, or is it not
necessary?
---
bindings/ocaml/llvm/llvm.ml | 4 ++++
bindings/ocaml/llvm/llvm.mli | 10 ++++++++++
bindings/ocaml/llvm/llvm_ocaml.c | 12 ++++++++++++
include/llvm-c/Core.h | 4 ++++
include/llvm/Constants.h | 6 ++++++
lib/VMCore/Constants.cpp | 21 +++++++++++++++++++++
lib/VMCore/Core.cpp | 29 ++++++++---------------------
test/Bindings/Ocaml/vmcore.ml | 14 +++++++++++++-
8 files changed, 78 insertions(+), 22 deletions(-)
diff --git a/bindings/ocaml/llvm/llvm.ml b/bindings/ocaml/llvm/llvm.ml
index 5bc8bca..275f167 100644
--- a/bindings/ocaml/llvm/llvm.ml
+++ b/bindings/ocaml/llvm/llvm.ml
@@ -238,7 +238,11 @@ external is_undef : llvalue -> bool = "llvm_is_undef"
external const_int : lltype -> int -> llvalue = "llvm_const_int"
external const_of_int64 : lltype -> Int64.t -> bool -> llvalue
= "llvm_const_of_int64"
+external const_int_of_string : lltype -> string -> int -> llvalue
+ = "llvm_const_int_of_string"
external const_float : lltype -> float -> llvalue = "llvm_const_float"
+external const_float_of_string : lltype -> string -> llvalue
+ = "llvm_const_float_of_string"
(*--... Operations on composite constants ..................................--*)
external const_string : string -> llvalue = "llvm_const_string"
diff --git a/bindings/ocaml/llvm/llvm.mli b/bindings/ocaml/llvm/llvm.mli
index e8ca0f9..269d878 100644
--- a/bindings/ocaml/llvm/llvm.mli
+++ b/bindings/ocaml/llvm/llvm.mli
@@ -469,10 +469,20 @@ external const_int : lltype -> int -> llvalue = "llvm_const_int"
external const_of_int64 : lltype -> Int64.t -> bool -> llvalue
= "llvm_const_of_int64"
+(** [const_int_of_string ty s r] returns the integer constant of type [ty] and
+ * value [s], with the radix [r]. See the method [llvm::ConstantInt::get]. *)
+external const_int_of_string : lltype -> string -> int -> llvalue
+ = "llvm_const_int_of_string"
+
(** [const_float ty n] returns the floating point constant of type [ty] and
value [n]. See the method [llvm::ConstantFP::get]. *)
external const_float : lltype -> float -> llvalue = "llvm_const_float"
+(** [const_float_of_string ty s] returns the floating point constant of type
+ [ty] and value [n]. See the method [llvm::ConstantFP::get]. *)
+external const_float_of_string : lltype -> string -> llvalue
+ = "llvm_const_float_of_string"
+
(** {7 Operations on composite constants} *)
diff --git a/bindings/ocaml/llvm/llvm_ocaml.c b/bindings/ocaml/llvm/llvm_ocaml.c
index c4eba13..a49d31c 100644
--- a/bindings/ocaml/llvm/llvm_ocaml.c
+++ b/bindings/ocaml/llvm/llvm_ocaml.c
@@ -388,11 +388,23 @@ CAMLprim LLVMValueRef llvm_const_of_int64(LLVMTypeRef IntTy, value N,
return LLVMConstInt(IntTy, Int64_val(N), Bool_val(SExt));
}
+/* lltype -> string -> int -> llvalue */
+CAMLprim LLVMValueRef llvm_const_int_of_string(LLVMTypeRef IntTy, value S,
+ value Radix) {
+ return LLVMConstIntOfString(IntTy, String_val(S), caml_string_length(S),
+ Int_val(Radix));
+}
+
/* lltype -> float -> llvalue */
CAMLprim LLVMValueRef llvm_const_float(LLVMTypeRef RealTy, value N) {
return LLVMConstReal(RealTy, Double_val(N));
}
+/* lltype -> string -> llvalue */
+CAMLprim LLVMValueRef llvm_const_float_of_string(LLVMTypeRef RealTy, value S) {
+ return LLVMConstRealOfString(RealTy, String_val(S), caml_string_length(S));
+}
+
/*--... Operations on composite constants ..................................--*/
/* string -> llvalue */
diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h
index 0d6e248..12e9d8a 100644
--- a/include/llvm-c/Core.h
+++ b/include/llvm-c/Core.h
@@ -33,6 +33,8 @@
#ifndef LLVM_C_CORE_H
#define LLVM_C_CORE_H
+#include "llvm/Support/DataTypes.h"
+
#ifdef __cplusplus
/* Need these includes to support the LLVM 'cast' template for the C++ 'wrap'
@@ -413,6 +415,8 @@ LLVMValueRef LLVMConstPointerNull(LLVMTypeRef Ty);
/* Operations on scalar constants */
LLVMValueRef LLVMConstInt(LLVMTypeRef IntTy, unsigned long long N,
int SignExtend);
+LLVMValueRef LLVMConstIntOfString(LLVMTypeRef IntTy, const char *Text,
+ unsigned SLen, uint8_t Radix);
LLVMValueRef LLVMConstReal(LLVMTypeRef RealTy, double N);
LLVMValueRef LLVMConstRealOfString(LLVMTypeRef RealTy, const char *Text);
diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h
index 30b48be..11f16c4 100644
--- a/include/llvm/Constants.h
+++ b/include/llvm/Constants.h
@@ -83,6 +83,11 @@ public:
/// Return a ConstantInt with the specified value and an implied Type. The
/// type is the integer type that corresponds to the bit width of the value.
static ConstantInt* get(LLVMContext &Context, const APInt& V);
+
+ /// Return a ConstantInt constructed from the string strStart with the given
+ /// radix.
+ static ConstantInt* get(const IntegerType* Ty, const StringRef& Str,
+ uint8_t radix);
/// If Ty is a vector type, return a Constant with a splat of the given
/// value. Otherwise return a ConstantInt for the given value.
@@ -250,6 +255,7 @@ public:
/// only be used for simple constant values like 2.0/1.0 etc, that are
/// known-valid both as host double and as the target format.
static Constant* get(const Type* Ty, double V);
+ static Constant* get(const Type* Ty, const StringRef& Str);
static ConstantFP* get(LLVMContext &Context, const APFloat& V);
static ConstantFP* getNegativeZero(const Type* Ty);
diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp
index 0bff578..42213c4 100644
--- a/lib/VMCore/Constants.cpp
+++ b/lib/VMCore/Constants.cpp
@@ -312,6 +312,11 @@ Constant* ConstantInt::get(const Type* Ty, const APInt& V) {
return C;
}
+ConstantInt* ConstantInt::get(const IntegerType* Ty, const StringRef& Str,
+ uint8_t radix) {
+ return get(Ty->getContext(), APInt(Ty->getBitWidth(), Str, radix));
+}
+
//===----------------------------------------------------------------------===//
// ConstantFP
//===----------------------------------------------------------------------===//
@@ -350,6 +355,22 @@ Constant* ConstantFP::get(const Type* Ty, double V) {
return C;
}
+
+Constant* ConstantFP::get(const Type* Ty, const StringRef& Str) {
+ LLVMContext &Context = Ty->getContext();
+
+ APFloat FV(*TypeToFloatSemantics(Ty->getScalarType()), Str);
+ Constant *C = get(Context, FV);
+
+ // For vectors, broadcast the value.
+ if (const VectorType *VTy = dyn_cast<VectorType>(Ty))
+ return ConstantVector::get(
+ std::vector<Constant *>(VTy->getNumElements(), C));
+
+ return C;
+}
+
+
ConstantFP* ConstantFP::getNegativeZero(const Type* Ty) {
LLVMContext &Context = Ty->getContext();
APFloat apf = cast <ConstantFP>(Constant::getNullValue(Ty))->getValueAPF();
diff --git a/lib/VMCore/Core.cpp b/lib/VMCore/Core.cpp
index 88160e1..9aaaee2 100644
--- a/lib/VMCore/Core.cpp
+++ b/lib/VMCore/Core.cpp
@@ -362,32 +362,19 @@ LLVMValueRef LLVMConstInt(LLVMTypeRef IntTy, unsigned long long N,
return wrap(ConstantInt::get(unwrap<IntegerType>(IntTy), N, SignExtend != 0));
}
-static const fltSemantics &SemanticsForType(Type *Ty) {
- assert(Ty->isFloatingPoint() && "Type is not floating point!");
- if (Ty == Type::FloatTy)
- return APFloat::IEEEsingle;
- if (Ty == Type::DoubleTy)
- return APFloat::IEEEdouble;
- if (Ty == Type::X86_FP80Ty)
- return APFloat::x87DoubleExtended;
- if (Ty == Type::FP128Ty)
- return APFloat::IEEEquad;
- if (Ty == Type::PPC_FP128Ty)
- return APFloat::PPCDoubleDouble;
- return APFloat::Bogus;
+LLVMValueRef LLVMConstIntOfString(LLVMTypeRef IntTy, const char Str[],
+ unsigned SLen, uint8_t Radix) {
+ return wrap(ConstantInt::get(unwrap<IntegerType>(IntTy), StringRef(Str, SLen),
+ Radix));
}
LLVMValueRef LLVMConstReal(LLVMTypeRef RealTy, double N) {
- APFloat APN(N);
- bool ignored;
- APN.convert(SemanticsForType(unwrap(RealTy)), APFloat::rmNearestTiesToEven,
- &ignored);
- return wrap(ConstantFP::get(getGlobalContext(), APN));
+ return wrap(ConstantFP::get(unwrap(RealTy), N));
}
-LLVMValueRef LLVMConstRealOfString(LLVMTypeRef RealTy, const char *Text) {
- return wrap(ConstantFP::get(getGlobalContext(),
- APFloat(SemanticsForType(unwrap(RealTy)), Text)));
+LLVMValueRef LLVMConstRealOfString(LLVMTypeRef RealTy, const char Str[],
+ unsigned SLen) {
+ return wrap(ConstantFP::get(unwrap(RealTy), StringRef(Str, SLen)));
}
/*--.. Operations on composite constants ...................................--*/
diff --git a/test/Bindings/Ocaml/vmcore.ml b/test/Bindings/Ocaml/vmcore.ml
index 9016d39..af714a0 100644
--- a/test/Bindings/Ocaml/vmcore.ml
+++ b/test/Bindings/Ocaml/vmcore.ml
@@ -212,11 +212,18 @@ let test_constants () =
ignore (define_global "Const03" c m);
insist (i64_type = type_of c);
+ (* RUN: grep {ConstIntString.*i32.*-1} < %t.ll
+ *)
+ group "int string";
+ let c = const_int_of_string i32_type "-1" 10 in
+ ignore (define_global "ConstIntString" c m);
+ insist (i32_type = type_of c);
+
(* RUN: grep {Const04.*"cruel\\\\00world"} < %t.ll
*)
group "string";
let c = const_string "cruel\000world" in
- ignore (define_global "Const04" c m);
+ ignore (define_global "Const05" c m);
insist ((array_type i8_type 11) = type_of c);
(* RUN: grep {Const05.*"hi\\\\00again\\\\00"} < %t.ll
@@ -228,6 +235,7 @@ let test_constants () =
(* RUN: grep {ConstSingle.*2.75} < %t.ll
* RUN: grep {ConstDouble.*3.1459} < %t.ll
+ * RUN: grep {ConstDoubleString.*1.25} < %t.ll
*)
begin group "real";
let cs = const_float float_type 2.75 in
@@ -236,6 +244,10 @@ let test_constants () =
let cd = const_float double_type 3.1459 in
ignore (define_global "ConstDouble" cd m);
+ insist (double_type = type_of cd);
+
+ let cd = const_float_of_string double_type "1.25" in
+ ignore (define_global "ConstDoubleDouble" cd m);
insist (double_type = type_of cd)
end;
--
1.6.4
More information about the llvm-commits
mailing list