[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