* Make pointer values work better by treating them uniformly as 64 bit values.
authorChris Lattner <sabre@nondot.org>
Sat, 27 Oct 2001 08:28:11 +0000 (08:28 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 27 Oct 2001 08:28:11 +0000 (08:28 +0000)
  This causes code that is generated by gcc to work better.
* Implement mul & div
* Export malloc, free, and pow
* add strtol, atoi, and atol to the runtime library

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@988 91177308-0d34-0410-b5e6-96231b3b80d8

lib/ExecutionEngine/Interpreter/Execution.cpp
lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
lib/ExecutionEngine/Interpreter/Interpreter.h
lib/ExecutionEngine/Interpreter/UserInput.cpp
lib/ExecutionEngine/Makefile
tools/lli/Makefile
tools/lli/RuntimeLib.lc

index 1f2d6f132d8f9ac4a30635b0979252438c1ee52d..a7ded5b705b6f1dd840540a3f5f74d39def042ec 100644 (file)
@@ -51,7 +51,7 @@ static GenericValue getOperandValue(Value *V, ExecutionContext &SF) {
       GET_CONST_VAL(Double , ConstPoolFP);
     case Type::PointerTyID:
       if (isa<ConstPoolPointerNull>(CPV)) {
-        Result.PointerVal = 0;
+        Result.ULongVal = 0;
       } else if (ConstPoolPointerRef *CPR =dyn_cast<ConstPoolPointerRef>(CPV)) {
         assert(0 && "Not implemented!");
       } else {
@@ -66,7 +66,7 @@ static GenericValue getOperandValue(Value *V, ExecutionContext &SF) {
     GlobalAddress *Address = 
       (GlobalAddress*)GV->getOrCreateAnnotation(GlobalAddressAID);
     GenericValue Result;
-    Result.PointerVal = (GenericValue*)Address->Ptr;
+    Result.ULongVal = (uint64_t)(GenericValue*)Address->Ptr;
     return Result;
   } else {
     unsigned TyP = V->getType()->getUniqueID();   // TypePlane for value
@@ -218,9 +218,6 @@ Annotation *GlobalAddress::Create(AnnotationID AID, const Annotable *O, void *){
 
 #define IMPLEMENT_BINARY_OPERATOR(OP, TY) \
    case Type::TY##TyID: Dest.TY##Val = Src1.TY##Val OP Src2.TY##Val; break
-#define IMPLEMENT_BINARY_PTR_OPERATOR(OP) \
-   case Type::PointerTyID: Dest.PointerVal = \
-     (GenericValue*)((unsigned long)Src1.PointerVal OP (unsigned long)Src2.PointerVal); break
 
 static GenericValue executeAddInst(GenericValue Src1, GenericValue Src2, 
                                   const Type *Ty, ExecutionContext &SF) {
@@ -236,7 +233,7 @@ static GenericValue executeAddInst(GenericValue Src1, GenericValue Src2,
     IMPLEMENT_BINARY_OPERATOR(+, Long);
     IMPLEMENT_BINARY_OPERATOR(+, Float);
     IMPLEMENT_BINARY_OPERATOR(+, Double);
-    IMPLEMENT_BINARY_PTR_OPERATOR(+);
+    IMPLEMENT_BINARY_OPERATOR(+, Pointer);
   default:
     cout << "Unhandled type for Add instruction: " << Ty << endl;
   }
@@ -257,13 +254,55 @@ static GenericValue executeSubInst(GenericValue Src1, GenericValue Src2,
     IMPLEMENT_BINARY_OPERATOR(-, Long);
     IMPLEMENT_BINARY_OPERATOR(-, Float);
     IMPLEMENT_BINARY_OPERATOR(-, Double);
-    IMPLEMENT_BINARY_PTR_OPERATOR(-);
+    IMPLEMENT_BINARY_OPERATOR(-, Pointer);
   default:
     cout << "Unhandled type for Sub instruction: " << Ty << endl;
   }
   return Dest;
 }
 
+static GenericValue executeMulInst(GenericValue Src1, GenericValue Src2, 
+                                  const Type *Ty, ExecutionContext &SF) {
+  GenericValue Dest;
+  switch (Ty->getPrimitiveID()) {
+    IMPLEMENT_BINARY_OPERATOR(*, UByte);
+    IMPLEMENT_BINARY_OPERATOR(*, SByte);
+    IMPLEMENT_BINARY_OPERATOR(*, UShort);
+    IMPLEMENT_BINARY_OPERATOR(*, Short);
+    IMPLEMENT_BINARY_OPERATOR(*, UInt);
+    IMPLEMENT_BINARY_OPERATOR(*, Int);
+    IMPLEMENT_BINARY_OPERATOR(*, ULong);
+    IMPLEMENT_BINARY_OPERATOR(*, Long);
+    IMPLEMENT_BINARY_OPERATOR(*, Float);
+    IMPLEMENT_BINARY_OPERATOR(*, Double);
+    IMPLEMENT_BINARY_OPERATOR(*, Pointer);
+  default:
+    cout << "Unhandled type for Mul instruction: " << Ty << endl;
+  }
+  return Dest;
+}
+
+static GenericValue executeDivInst(GenericValue Src1, GenericValue Src2, 
+                                  const Type *Ty, ExecutionContext &SF) {
+  GenericValue Dest;
+  switch (Ty->getPrimitiveID()) {
+    IMPLEMENT_BINARY_OPERATOR(/, UByte);
+    IMPLEMENT_BINARY_OPERATOR(/, SByte);
+    IMPLEMENT_BINARY_OPERATOR(/, UShort);
+    IMPLEMENT_BINARY_OPERATOR(/, Short);
+    IMPLEMENT_BINARY_OPERATOR(/, UInt);
+    IMPLEMENT_BINARY_OPERATOR(/, Int);
+    IMPLEMENT_BINARY_OPERATOR(/, ULong);
+    IMPLEMENT_BINARY_OPERATOR(/, Long);
+    IMPLEMENT_BINARY_OPERATOR(/, Float);
+    IMPLEMENT_BINARY_OPERATOR(/, Double);
+    IMPLEMENT_BINARY_OPERATOR(/, Pointer);
+  default:
+    cout << "Unhandled type for Mul instruction: " << Ty << endl;
+  }
+  return Dest;
+}
+
 #define IMPLEMENT_SETCC(OP, TY) \
    case Type::TY##TyID: Dest.BoolVal = Src1.TY##Val OP Src2.TY##Val; break
 
@@ -402,6 +441,8 @@ static void executeBinaryInst(BinaryOperator *I, ExecutionContext &SF) {
   switch (I->getOpcode()) {
   case Instruction::Add: R = executeAddInst(Src1, Src2, Ty, SF); break;
   case Instruction::Sub: R = executeSubInst(Src1, Src2, Ty, SF); break;
+  case Instruction::Mul: R = executeMulInst(Src1, Src2, Ty, SF); break;
+  case Instruction::Div: R = executeDivInst(Src1, Src2, Ty, SF); break;
   case Instruction::SetEQ: R = executeSetEQInst(Src1, Src2, Ty, SF); break;
   case Instruction::SetNE: R = executeSetNEInst(Src1, Src2, Ty, SF); break;
   case Instruction::SetLE: R = executeSetLEInst(Src1, Src2, Ty, SF); break;
@@ -511,8 +552,8 @@ void Interpreter::executeAllocInst(AllocationInst *I, ExecutionContext &SF) {
 
   // Allocate enough memory to hold the type...
   GenericValue Result;
-  Result.PointerVal = (GenericValue*)malloc(NumElements * TD.getTypeSize(Ty));
-  assert(Result.PointerVal != 0 && "Null pointer returned by malloc!");
+  Result.ULongVal = (uint64_t)malloc(NumElements * TD.getTypeSize(Ty));
+  assert(Result.ULongVal != 0 && "Null pointer returned by malloc!");
   SetValue(I, Result, SF);
 
   if (I->getOpcode() == Instruction::Alloca) {
@@ -524,12 +565,13 @@ static void executeFreeInst(FreeInst *I, ExecutionContext &SF) {
   assert(I->getOperand(0)->getType()->isPointerType() && "Freeing nonptr?");
   GenericValue Value = getOperandValue(I->getOperand(0), SF);
   // TODO: Check to make sure memory is allocated
-  free(Value.PointerVal);   // Free memory
+  free((void*)Value.ULongVal);   // Free memory
 }
 
 static void executeLoadInst(LoadInst *I, ExecutionContext &SF) {
   assert(I->getNumOperands() == 1 && "NI!");
-  GenericValue *Ptr = getOperandValue(I->getPtrOperand(), SF).PointerVal;
+  GenericValue *Ptr =
+    (GenericValue*)getOperandValue(I->getPtrOperand(), SF).ULongVal;
   GenericValue Result;
 
   switch (I->getType()->getPrimitiveID()) {
@@ -541,10 +583,10 @@ static void executeLoadInst(LoadInst *I, ExecutionContext &SF) {
   case Type::UIntTyID:
   case Type::IntTyID:     Result.IntVal = Ptr->IntVal; break;
   case Type::ULongTyID:
-  case Type::LongTyID:    Result.LongVal = Ptr->LongVal; break;
+  case Type::LongTyID:
+  case Type::PointerTyID: Result.ULongVal = Ptr->ULongVal; break;
   case Type::FloatTyID:   Result.FloatVal = Ptr->FloatVal; break;
   case Type::DoubleTyID:  Result.DoubleVal = Ptr->DoubleVal; break;
-  case Type::PointerTyID: Result.PointerVal =(GenericValue*)Ptr->LongVal; break;
   default:
     cout << "Cannot load value of type " << I->getType() << "!\n";
   }
@@ -553,7 +595,8 @@ static void executeLoadInst(LoadInst *I, ExecutionContext &SF) {
 }
 
 static void executeStoreInst(StoreInst *I, ExecutionContext &SF) {
-  GenericValue *Ptr = getOperandValue(I->getPtrOperand(), SF).PointerVal;
+  GenericValue *Ptr =
+    (GenericValue *)getOperandValue(I->getPtrOperand(), SF).ULongVal;
   GenericValue Val = getOperandValue(I->getOperand(0), SF);
   assert(I->getNumOperands() == 2 && "NI!");
 
@@ -566,10 +609,10 @@ static void executeStoreInst(StoreInst *I, ExecutionContext &SF) {
   case Type::UIntTyID:
   case Type::IntTyID:     Ptr->IntVal = Val.IntVal; break;
   case Type::ULongTyID:
-  case Type::LongTyID:    Ptr->LongVal = Val.LongVal; break;
+  case Type::LongTyID:
+  case Type::PointerTyID: Ptr->LongVal = Val.LongVal; break;
   case Type::FloatTyID:   Ptr->FloatVal = Val.FloatVal; break;
   case Type::DoubleTyID:  Ptr->DoubleVal = Val.DoubleVal; break;
-  case Type::PointerTyID: Ptr->PointerVal = Val.PointerVal; break;
   default:
     cout << "Cannot store value of type " << I->getType() << "!\n";
   }
@@ -665,10 +708,8 @@ static void executeShrInst(ShiftInst *I, ExecutionContext &SF) {
       IMPLEMENT_CAST(DESTTY, DESTCTY, UInt);    \
       IMPLEMENT_CAST(DESTTY, DESTCTY, Int);     \
       IMPLEMENT_CAST(DESTTY, DESTCTY, ULong);   \
-      IMPLEMENT_CAST(DESTTY, DESTCTY, Long);
-
-#define IMPLEMENT_CAST_CASE_PTR_IMP(DESTTY, DESTCTY) \
-      IMPLEMENT_CAST(DESTTY, DESTCTY, Pointer)
+      IMPLEMENT_CAST(DESTTY, DESTCTY, Long);    \
+      IMPLEMENT_CAST(DESTTY, DESTCTY, Pointer);
 
 #define IMPLEMENT_CAST_CASE_FP_IMP(DESTTY, DESTCTY) \
       IMPLEMENT_CAST(DESTTY, DESTCTY, Float);   \
@@ -683,17 +724,6 @@ static void executeShrInst(ShiftInst *I, ExecutionContext &SF) {
 #define IMPLEMENT_CAST_CASE(DESTTY, DESTCTY) \
    IMPLEMENT_CAST_CASE_START(DESTTY, DESTCTY);   \
    IMPLEMENT_CAST_CASE_FP_IMP(DESTTY, DESTCTY); \
-   IMPLEMENT_CAST_CASE_PTR_IMP(DESTTY, DESTCTY); \
-   IMPLEMENT_CAST_CASE_END()
-
-#define IMPLEMENT_CAST_CASE_FP(DESTTY, DESTCTY) \
-   IMPLEMENT_CAST_CASE_START(DESTTY, DESTCTY);   \
-   IMPLEMENT_CAST_CASE_FP_IMP(DESTTY, DESTCTY); \
-   IMPLEMENT_CAST_CASE_END()
-
-#define IMPLEMENT_CAST_CASE_PTR(DESTTY, DESTCTY) \
-   IMPLEMENT_CAST_CASE_START(DESTTY, DESTCTY);   \
-   IMPLEMENT_CAST_CASE_PTR_IMP(DESTTY, DESTCTY); \
    IMPLEMENT_CAST_CASE_END()
 
 static void executeCastInst(CastInst *I, ExecutionContext &SF) {
@@ -711,9 +741,9 @@ static void executeCastInst(CastInst *I, ExecutionContext &SF) {
     IMPLEMENT_CAST_CASE(Int   ,   signed int );
     IMPLEMENT_CAST_CASE(ULong , uint64_t );
     IMPLEMENT_CAST_CASE(Long  ,  int64_t );
-    IMPLEMENT_CAST_CASE_FP(Float ,          float);
-    IMPLEMENT_CAST_CASE_FP(Double,          double);
-    IMPLEMENT_CAST_CASE_PTR(Pointer, GenericValue *);
+    IMPLEMENT_CAST_CASE(Pointer, uint64_t);
+    IMPLEMENT_CAST_CASE(Float ,          float);
+    IMPLEMENT_CAST_CASE(Double,          double);
   default:
     cout << "Unhandled dest type for cast instruction: " << Ty << endl;
   }
@@ -944,7 +974,7 @@ void Interpreter::printValue(const Type *Ty, GenericValue V) {
   case Type::ULongTyID:  cout << V.ULongVal;  break;
   case Type::FloatTyID:  cout << V.FloatVal;  break;
   case Type::DoubleTyID: cout << V.DoubleVal; break;
-  case Type::PointerTyID:cout << V.PointerVal; break;
+  case Type::PointerTyID:cout << (void*)V.ULongVal; break;
   default:
     cout << "- Don't know how to print value of this type!";
     break;
index 973cca68422b5f693fc3c844f51d515c1bf81ad0..662abc22919ebed4a8d73664478c13f1ff9ff32e 100644 (file)
@@ -14,6 +14,7 @@
 #include <map>
 #include <dlfcn.h>
 #include <link.h>
+#include <math.h>
 
 typedef GenericValue (*ExFunc)(MethodType *, const vector<GenericValue> &);
 static map<const Method *, ExFunc> Functions;
@@ -170,4 +171,25 @@ GenericValue lle_Vi_exit(MethodType *M, const vector<GenericValue> &Args) {
   return GenericValue();
 }
 
+// void *malloc(uint)
+GenericValue lle_PI_malloc(MethodType *M, const vector<GenericValue> &Args) {
+  GenericValue GV;
+  GV.LongVal = (uint64_t)malloc(Args[0].UIntVal);
+  return GV;
+}
+
+// void free(void *)
+GenericValue lle_VP_free(MethodType *M, const vector<GenericValue> &Args) {
+  free((void*)Args[0].LongVal);
+  return GenericValue();
+}
+
+// double pow(double, double)
+GenericValue lle_DDD_pow(MethodType *M, const vector<GenericValue> &Args) {
+  GenericValue GV;
+  GV.DoubleVal = pow(GV.DoubleVal, GV.DoubleVal);
+  return GV;
+}
+
+
 } // End extern "C"
index 5b123466aa6eebff34121cb131c7110a4d6bc1fd..16cc569ad0ffa53a30801287d785e2e6884ed261 100644 (file)
@@ -29,7 +29,7 @@ union GenericValue {
   int64_t         LongVal;
   double          DoubleVal;
   float           FloatVal;
-  GenericValue *PointerVal;
+  uint64_t      PointerVal;
 };
 
 typedef vector<GenericValue> ValuePlaneTy;
index efe7150c137ecaaebc308dd291374c0d81268271..a24b31175063d149ca1b0694e2035c585db7cd70 100644 (file)
@@ -263,7 +263,7 @@ bool Interpreter::callMainMethod(const string &Name,
       return true;
     }
 
-    GenericValue GV; GV.PointerVal = (GenericValue*)CreateArgv(InputArgv);
+    GenericValue GV; GV.PointerVal = (uint64_t)CreateArgv(InputArgv);
     Args.push_back(GV);
   }
     // fallthrough
index 3e70896c291cd56116817e92d7bb8c715ec7e86f..0fdcf8b5ddb89c4f112b711b6e45aca4ed86e1a1 100644 (file)
@@ -12,6 +12,7 @@ Debug/RuntimeLib.c: RuntimeLib.lc
        cp -f $< $@
 
 Debug/RuntimeLib.o: Debug/RuntimeLib.c
+       @-rm $@
        /home/vadve/lattner/cvs/gcc_install/bin/gcc $< -c -o $@
 
 $(LEVEL)/tools/Debug/RuntimeLib.bc: Debug/RuntimeLib.o
index 3e70896c291cd56116817e92d7bb8c715ec7e86f..0fdcf8b5ddb89c4f112b711b6e45aca4ed86e1a1 100644 (file)
@@ -12,6 +12,7 @@ Debug/RuntimeLib.c: RuntimeLib.lc
        cp -f $< $@
 
 Debug/RuntimeLib.o: Debug/RuntimeLib.c
+       @-rm $@
        /home/vadve/lattner/cvs/gcc_install/bin/gcc $< -c -o $@
 
 $(LEVEL)/tools/Debug/RuntimeLib.bc: Debug/RuntimeLib.o
index 38b28bfab19676a1c09b74530f3902864e14dbfd..f2611a85152445d43f36bcc4285bcaf1c2329b04 100644 (file)
@@ -6,11 +6,22 @@
 //
 // This file is compiled by the LLVM port of GCC to get LLVM code.
 //
+// A lot of this code is ripped gratuitously from glibc and libiberty.
+//
 //===----------------------------------------------------------------------===//
 
+
 // Prototypes for functions exported by LLI directly.
 void exit(int Code);
 int putchar(int);
+void *malloc(unsigned);
+void free(void *);
+
+#define isspace(x) ((x) == ' ' || (x) == '\t' || (x) == '\n')
+#define isdigit(x) ((x) >= '0' || (x) <= '9')
+#define isupper(x) ((x) >= 'A' || (x) <= 'Z')
+#define islower(x) ((x) >= 'a' || (x) <= 'z')
+#define isalpha(x) (isupper(x) || islower(x))
 
 // The puts() function writes the string pointed to by s, followed by a 
 // NEWLINE character, to the standard output stream stdout. On success the 
@@ -23,3 +34,117 @@ int puts(const char *S) {
   return Str+1-S;
 }
 
+
+#ifndef ULONG_MAX
+#define ULONG_MAX       ((unsigned long)(~0L))          /* 0xFFFFFFFF */
+#endif
+
+#ifndef LONG_MAX
+#define LONG_MAX        ((long)(ULONG_MAX >> 1))        /* 0x7FFFFFFF */
+#endif
+
+#ifndef LONG_MIN
+#define LONG_MIN        ((long)(~LONG_MAX))             /* 0x80000000 */
+#endif
+
+/*
+ * Convert a string to a long integer.
+ *
+ * Ignores `locale' stuff.  Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+long strtol(const char *nptr, char **endptr, int base) {
+        register const char *s = nptr;
+        register unsigned long acc;
+        register int c;
+        register unsigned long cutoff;
+        register int neg = 0, any, cutlim;
+
+        /*
+         * Skip white space and pick up leading +/- sign if any.
+         * If base is 0, allow 0x for hex and 0 for octal, else
+         * assume decimal; if base is already 16, allow 0x.
+         */
+        do {
+                c = *s++;
+        } while (isspace(c));
+        if (c == '-') {
+                neg = 1;
+                c = *s++;
+        } else if (c == '+')
+                c = *s++;
+        if ((base == 0 || base == 16) &&
+            c == '0' && (*s == 'x' || *s == 'X')) {
+                c = s[1];
+                s += 2;
+                base = 16;
+        }
+        if (base == 0)
+                base = c == '0' ? 8 : 10;
+
+        /*
+         * Compute the cutoff value between legal numbers and illegal
+         * numbers.  That is the largest legal value, divided by the
+         * base.  An input number that is greater than this value, if
+         * followed by a legal input character, is too big.  One that
+         * is equal to this value may be valid or not; the limit
+         * between valid and invalid numbers is then based on the last
+         * digit.  For instance, if the range for longs is
+         * [-2147483648..2147483647] and the input base is 10,
+         * cutoff will be set to 214748364 and cutlim to either
+         * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+         * a value > 214748364, or equal but the next digit is > 7 (or 8),
+         * the number is too big, and we will return a range error.
+         *
+         * Set any if any `digits' consumed; make it negative to indicate
+         * overflow.
+         */
+        cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
+        cutlim = cutoff % (unsigned long)base;
+        cutoff /= (unsigned long)base;
+        for (acc = 0, any = 0;; c = *s++) {
+                if (isdigit(c))
+                        c -= '0';
+                else if (isalpha(c))
+                        c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+                else
+                        break;
+                if (c >= base)
+                        break;
+                if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
+                        any = -1;
+                else {
+                        any = 1;
+                        acc *= base;
+                        acc += c;
+                }
+        }
+        if (any < 0) {
+                acc = neg ? LONG_MIN : LONG_MAX;
+        } else if (neg)
+                acc = -acc;
+        if (endptr != 0)
+                *endptr = (char *) (any ? s - 1 : nptr);
+        return (acc);
+}
+
+
+/* Convert a string to an int.  */
+int atoi(const char *nptr) {
+  return (int)strtol(nptr, 0, 10);
+}
+
+/* Convert a string to a long int.  */
+long int atol(const char *nptr) {
+  return strtol(nptr, 0, 10);
+}
+
+
+
+
+
+
+//===----------------------------------------------------------------------===//
+// libm stuff...
+//===----------------------------------------------------------------------===//
+