- Fix LLI so that it simulates the endianness of the target machine
[oota-llvm.git] / lib / ExecutionEngine / Interpreter / Execution.cpp
index 7bf276a7606318d624c93783248373f23fe5795b..4c8be259835b0c570d13688ee0409bef6bd7955f 100644 (file)
 #include "llvm/Constants.h"
 #include "llvm/Assembly/Writer.h"
 #include "llvm/Target/TargetData.h"
-#include "llvm/GlobalVariable.h"
 #include "Support/CommandLine.h"
 #include <math.h>  // For fmod
 #include <signal.h>
 #include <setjmp.h>
-#include <iostream>
 using std::vector;
 using std::cout;
 using std::cerr;
@@ -40,7 +38,7 @@ AbortOnExceptions("abort-on-exception",
 // Create a TargetData structure to handle memory addressing and size/alignment
 // computations
 //
-static TargetData TD("lli Interpreter");
+TargetData TD("lli Interpreter");
 CachedWriter CW;     // Object to accelerate printing of LLVM
 
 
@@ -85,36 +83,67 @@ static unsigned getOperandSlot(Value *V) {
 }
 
 #define GET_CONST_VAL(TY, CLASS) \
-  case Type::TY##TyID: Result.TY##Val = cast<CLASS>(CPV)->getValue(); break
+  case Type::TY##TyID: Result.TY##Val = cast<CLASS>(C)->getValue(); break
+
+// Operations used by constant expr implementations...
+static GenericValue executeCastOperation(Value *Src, const Type *DestTy,
+                                         ExecutionContext &SF);
+static GenericValue executeGEPOperation(Value *Src, User::op_iterator IdxBegin,
+                                        User::op_iterator IdxEnd,
+                                        ExecutionContext &SF);
+static GenericValue executeAddInst(GenericValue Src1, GenericValue Src2, 
+                                  const Type *Ty, ExecutionContext &SF);
+
+static GenericValue getConstantValue(const Constant *C) {
+  GenericValue Result;
+  switch (C->getType()->getPrimitiveID()) {
+    GET_CONST_VAL(Bool   , ConstantBool);
+    GET_CONST_VAL(UByte  , ConstantUInt);
+    GET_CONST_VAL(SByte  , ConstantSInt);
+    GET_CONST_VAL(UShort , ConstantUInt);
+    GET_CONST_VAL(Short  , ConstantSInt);
+    GET_CONST_VAL(UInt   , ConstantUInt);
+    GET_CONST_VAL(Int    , ConstantSInt);
+    GET_CONST_VAL(ULong  , ConstantUInt);
+    GET_CONST_VAL(Long   , ConstantSInt);
+    GET_CONST_VAL(Float  , ConstantFP);
+    GET_CONST_VAL(Double , ConstantFP);
+  case Type::PointerTyID:
+    if (isa<ConstantPointerNull>(C)) {
+      Result.PointerVal = 0;
+    } else if (const ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(C)){
+      GlobalAddress *Address = 
+       (GlobalAddress*)CPR->getValue()->getOrCreateAnnotation(GlobalAddressAID);
+      Result.PointerVal = (PointerTy)Address->Ptr;
+    } else {
+      assert(0 && "Unknown constant pointer type!");
+    }
+    break;
+  default:
+    cout << "ERROR: Constant unimp for type: " << C->getType() << "\n";
+  }
+  return Result;
+}
 
 static GenericValue getOperandValue(Value *V, ExecutionContext &SF) {
-  if (Constant *CPV = dyn_cast<Constant>(V)) {
-    GenericValue Result;
-    switch (CPV->getType()->getPrimitiveID()) {
-      GET_CONST_VAL(Bool   , ConstantBool);
-      GET_CONST_VAL(UByte  , ConstantUInt);
-      GET_CONST_VAL(SByte  , ConstantSInt);
-      GET_CONST_VAL(UShort , ConstantUInt);
-      GET_CONST_VAL(Short  , ConstantSInt);
-      GET_CONST_VAL(UInt   , ConstantUInt);
-      GET_CONST_VAL(Int    , ConstantSInt);
-      GET_CONST_VAL(ULong  , ConstantUInt);
-      GET_CONST_VAL(Long   , ConstantSInt);
-      GET_CONST_VAL(Float  , ConstantFP);
-      GET_CONST_VAL(Double , ConstantFP);
-    case Type::PointerTyID:
-      if (isa<ConstantPointerNull>(CPV)) {
-        Result.PointerVal = 0;
-      } else if (isa<ConstantPointerRef>(CPV)) {
-        assert(0 && "Not implemented!");
-      } else {
-        assert(0 && "Unknown constant pointer type!");
-      }
-      break;
+  if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
+    switch (CE->getOpcode()) {
+    case Instruction::Cast:
+      return executeCastOperation(CE->getOperand(0), CE->getType(), SF);
+    case Instruction::GetElementPtr:
+      return executeGEPOperation(CE->getOperand(0), CE->op_begin()+1,
+                                 CE->op_end(), SF);
+    case Instruction::Add:
+      return executeAddInst(getOperandValue(CE->getOperand(0), SF),
+                            getOperandValue(CE->getOperand(1), SF),
+                            CE->getType(), SF);
     default:
-      cout << "ERROR: Constant unimp for type: " << CPV->getType() << "\n";
+      cerr << "Unhandled ConstantExpr: " << CE << "\n";
+      abort();
+      { GenericValue V; return V; }
     }
-    return Result;
+  } else if (Constant *CPV = dyn_cast<Constant>(V)) {
+    return getConstantValue(CPV);
   } else if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
     GlobalAddress *Address = 
       (GlobalAddress*)GV->getOrCreateAnnotation(GlobalAddressAID);
@@ -174,30 +203,21 @@ void Interpreter::initializeExecutionEngine() {
   initializeSignalHandlers();
 }
 
+static void StoreValueToMemory(GenericValue Val, GenericValue *Ptr,
+                               const Type *Ty);
+
 // InitializeMemory - Recursive function to apply a Constant value into the
 // specified memory location...
 //
 static void InitializeMemory(const Constant *Init, char *Addr) {
-#define INITIALIZE_MEMORY(TYID, CLASS, TY)  \
-  case Type::TYID##TyID: {                  \
-    TY Tmp = cast<CLASS>(Init)->getValue(); \
-    memcpy(Addr, &Tmp, sizeof(TY));         \
-  } return
 
-  switch (Init->getType()->getPrimitiveID()) {
-    INITIALIZE_MEMORY(Bool   , ConstantBool, bool);
-    INITIALIZE_MEMORY(UByte  , ConstantUInt, unsigned char);
-    INITIALIZE_MEMORY(SByte  , ConstantSInt, signed   char);
-    INITIALIZE_MEMORY(UShort , ConstantUInt, unsigned short);
-    INITIALIZE_MEMORY(Short  , ConstantSInt, signed   short);
-    INITIALIZE_MEMORY(UInt   , ConstantUInt, unsigned int);
-    INITIALIZE_MEMORY(Int    , ConstantSInt, signed   int);
-    INITIALIZE_MEMORY(ULong  , ConstantUInt, uint64_t);
-    INITIALIZE_MEMORY(Long   , ConstantSInt,  int64_t);
-    INITIALIZE_MEMORY(Float  , ConstantFP  , float);
-    INITIALIZE_MEMORY(Double , ConstantFP  , double);
-#undef INITIALIZE_MEMORY
+  if (Init->getType()->isFirstClassType()) {
+    GenericValue Val = getConstantValue(Init);
+    StoreValueToMemory(Val, (GenericValue*)Addr, Init->getType());
+    return;
+  }
 
+  switch (Init->getType()->getPrimitiveID()) {
   case Type::ArrayTyID: {
     const ConstantArray *CPA = cast<ConstantArray>(Init);
     const vector<Use> &Val = CPA->getValues();
@@ -218,19 +238,6 @@ static void InitializeMemory(const Constant *Init, char *Addr) {
     return;
   }
 
-  case Type::PointerTyID:
-    if (isa<ConstantPointerNull>(Init)) {
-      *(void**)Addr = 0;
-    } else if (const ConstantPointerRef *CPR =
-               dyn_cast<ConstantPointerRef>(Init)) {
-      GlobalAddress *Address = 
-       (GlobalAddress*)CPR->getValue()->getOrCreateAnnotation(GlobalAddressAID);
-      *(void**)Addr = (GenericValue*)Address->Ptr;
-    } else {
-      assert(0 && "Unknown Constant pointer type!");
-    }
-    return;
-
   default:
     CW << "Bad Type: " << Init->getType() << "\n";
     assert(0 && "Unknown constant type to initialize memory with!");
@@ -765,24 +772,23 @@ static void executeFreeInst(FreeInst &I, ExecutionContext &SF) {
 }
 
 
-// getElementOffset - The workhorse for getelementptr, load and store.  This 
-// function returns the offset that arguments ArgOff+1 -> NumArgs specify for
-// the pointer type specified by argument Arg.
+// getElementOffset - The workhorse for getelementptr.
 //
-static PointerTy getElementOffset(MemAccessInst &I, ExecutionContext &SF) {
-  assert(isa<PointerType>(I.getPointerOperand()->getType()) &&
+static GenericValue executeGEPOperation(Value *Ptr, User::op_iterator I,
+                                        User::op_iterator E,
+                                        ExecutionContext &SF) {
+  assert(isa<PointerType>(Ptr->getType()) &&
          "Cannot getElementOffset of a nonpointer type!");
 
   PointerTy Total = 0;
-  const Type *Ty = I.getPointerOperand()->getType();
-  
-  unsigned ArgOff = I.getFirstIndexOperandNumber();
-  while (ArgOff < I.getNumOperands()) {
+  const Type *Ty = Ptr->getType();
+
+  for (; I != E; ++I) {
     if (const StructType *STy = dyn_cast<StructType>(Ty)) {
       const StructLayout *SLO = TD.getStructLayout(STy);
       
       // Indicies must be ubyte constants...
-      const ConstantUInt *CPU = cast<ConstantUInt>(I.getOperand(ArgOff++));
+      const ConstantUInt *CPU = cast<ConstantUInt>(*I);
       assert(CPU->getType() == Type::UByteTy);
       unsigned Index = CPU->getValue();
       
@@ -800,14 +806,13 @@ static PointerTy getElementOffset(MemAccessInst &I, ExecutionContext &SF) {
     } else if (const SequentialType *ST = cast<SequentialType>(Ty)) {
 
       // Get the index number for the array... which must be uint type...
-      assert(I.getOperand(ArgOff)->getType() == Type::UIntTy);
-      unsigned Idx = getOperandValue(I.getOperand(ArgOff++), SF).UIntVal;
+      assert((*I)->getType() == Type::LongTy);
+      unsigned Idx = getOperandValue(*I, SF).LongVal;
       if (const ArrayType *AT = dyn_cast<ArrayType>(ST))
         if (Idx >= AT->getNumElements() && ArrayChecksEnabled) {
           cerr << "Out of range memory access to element #" << Idx
                << " of a " << AT->getNumElements() << " element array."
-               << " Subscript #" << (ArgOff-I.getFirstIndexOperandNumber())
-               << "\n";
+               << " Subscript #" << *I << "\n";
           // Get outta here!!!
           siglongjmp(SignalRecoverBuffer, SIGTRAP);
         }
@@ -818,71 +823,159 @@ static PointerTy getElementOffset(MemAccessInst &I, ExecutionContext &SF) {
     }  
   }
 
-  return Total;
+  GenericValue Result;
+  Result.PointerVal = getOperandValue(Ptr, SF).PointerVal + Total;
+  return Result;
 }
 
 static void executeGEPInst(GetElementPtrInst &I, ExecutionContext &SF) {
-  GenericValue SRC = getOperandValue(I.getPointerOperand(), SF);
-  PointerTy SrcPtr = SRC.PointerVal;
-
-  GenericValue Result;
-  Result.PointerVal = SrcPtr + getElementOffset(I, SF);
-  SetValue(&I, Result, SF);
+  SetValue(&I, executeGEPOperation(I.getPointerOperand(),
+                                   I.idx_begin(), I.idx_end(), SF), SF);
 }
 
 static void executeLoadInst(LoadInst &I, ExecutionContext &SF) {
   GenericValue SRC = getOperandValue(I.getPointerOperand(), SF);
-  PointerTy SrcPtr = SRC.PointerVal;
-  PointerTy Offset = getElementOffset(I, SF);  // Handle any structure indices
-  SrcPtr += Offset;
-
-  GenericValue *Ptr = (GenericValue*)SrcPtr;
+  GenericValue *Ptr = (GenericValue*)SRC.PointerVal;
   GenericValue Result;
 
-  switch (I.getType()->getPrimitiveID()) {
-  case Type::BoolTyID:
-  case Type::UByteTyID:
-  case Type::SByteTyID:   Result.SByteVal   = Ptr->SByteVal; break;
-  case Type::UShortTyID:
-  case Type::ShortTyID:   Result.ShortVal   = Ptr->ShortVal; break;
-  case Type::UIntTyID:
-  case Type::IntTyID:     Result.IntVal     = Ptr->IntVal; break;
-  case Type::ULongTyID:
-  case Type::LongTyID:    Result.ULongVal   = Ptr->ULongVal; break;
-  case Type::PointerTyID: Result.PointerVal = Ptr->PointerVal; break;
-  case Type::FloatTyID:   Result.FloatVal   = Ptr->FloatVal; break;
-  case Type::DoubleTyID:  Result.DoubleVal  = Ptr->DoubleVal; break;
-  default:
-    cout << "Cannot load value of type " << I.getType() << "!\n";
+  if (TD.isLittleEndian()) {
+    switch (I.getType()->getPrimitiveID()) {
+    case Type::BoolTyID:
+    case Type::UByteTyID:
+    case Type::SByteTyID:   Result.Untyped[0] = Ptr->UByteVal; break;
+    case Type::UShortTyID:
+    case Type::ShortTyID:   Result.Untyped[0] = Ptr->UShortVal & 255;
+                            Result.Untyped[1] = (Ptr->UShortVal >> 8) & 255;
+                            break;
+    case Type::FloatTyID:
+    case Type::UIntTyID:
+    case Type::IntTyID:     Result.Untyped[0] =  Ptr->UIntVal        & 255;
+                            Result.Untyped[1] = (Ptr->UIntVal >>  8) & 255;
+                            Result.Untyped[2] = (Ptr->UIntVal >> 16) & 255;
+                            Result.Untyped[3] = (Ptr->UIntVal >> 24) & 255;
+                            break;
+    case Type::DoubleTyID:
+    case Type::ULongTyID:
+    case Type::LongTyID:    
+    case Type::PointerTyID: Result.Untyped[0] =  Ptr->ULongVal        & 255;
+                            Result.Untyped[1] = (Ptr->ULongVal >>  8) & 255;
+                            Result.Untyped[2] = (Ptr->ULongVal >> 16) & 255;
+                            Result.Untyped[3] = (Ptr->ULongVal >> 24) & 255;
+                            Result.Untyped[4] = (Ptr->ULongVal >> 32) & 255;
+                            Result.Untyped[5] = (Ptr->ULongVal >> 40) & 255;
+                            Result.Untyped[6] = (Ptr->ULongVal >> 48) & 255;
+                            Result.Untyped[7] = (Ptr->ULongVal >> 56) & 255;
+                            break;
+    default:
+      cout << "Cannot load value of type " << I.getType() << "!\n";
+    }
+  } else {
+    switch (I.getType()->getPrimitiveID()) {
+    case Type::BoolTyID:
+    case Type::UByteTyID:
+    case Type::SByteTyID:   Result.Untyped[0] = Ptr->UByteVal; break;
+    case Type::UShortTyID:
+    case Type::ShortTyID:   Result.Untyped[1] = Ptr->UShortVal & 255;
+                            Result.Untyped[0] = (Ptr->UShortVal >> 8) & 255;
+                            break;
+    case Type::FloatTyID:
+    case Type::UIntTyID:
+    case Type::IntTyID:     Result.Untyped[3] =  Ptr->UIntVal        & 255;
+                            Result.Untyped[2] = (Ptr->UIntVal >>  8) & 255;
+                            Result.Untyped[1] = (Ptr->UIntVal >> 16) & 255;
+                            Result.Untyped[0] = (Ptr->UIntVal >> 24) & 255;
+                            break;
+    case Type::DoubleTyID:
+    case Type::ULongTyID:
+    case Type::LongTyID:    
+    case Type::PointerTyID: Result.Untyped[7] =  Ptr->ULongVal        & 255;
+                            Result.Untyped[6] = (Ptr->ULongVal >>  8) & 255;
+                            Result.Untyped[5] = (Ptr->ULongVal >> 16) & 255;
+                            Result.Untyped[4] = (Ptr->ULongVal >> 24) & 255;
+                            Result.Untyped[3] = (Ptr->ULongVal >> 32) & 255;
+                            Result.Untyped[2] = (Ptr->ULongVal >> 40) & 255;
+                            Result.Untyped[1] = (Ptr->ULongVal >> 48) & 255;
+                            Result.Untyped[0] = (Ptr->ULongVal >> 56) & 255;
+                            break;
+    default:
+      cout << "Cannot load value of type " << I.getType() << "!\n";
+    }
   }
 
   SetValue(&I, Result, SF);
 }
 
-static void executeStoreInst(StoreInst &I, ExecutionContext &SF) {
-  GenericValue SRC = getOperandValue(I.getPointerOperand(), SF);
-  PointerTy SrcPtr = SRC.PointerVal;
-  SrcPtr += getElementOffset(I, SF);  // Handle any structure indices
+static void StoreValueToMemory(GenericValue Val, GenericValue *Ptr,
+                               const Type *Ty) {
+  if (TD.isLittleEndian()) {
+    switch (Ty->getPrimitiveID()) {
+    case Type::BoolTyID:
+    case Type::UByteTyID:
+    case Type::SByteTyID:   Ptr->Untyped[0] = Val.UByteVal; break;
+    case Type::UShortTyID:
+    case Type::ShortTyID:   Ptr->Untyped[0] = Val.UShortVal & 255;
+                            Ptr->Untyped[1] = (Val.UShortVal >> 8) & 255;
+                            break;
+    case Type::FloatTyID:
+    case Type::UIntTyID:
+    case Type::IntTyID:     Ptr->Untyped[0] =  Val.UIntVal        & 255;
+                            Ptr->Untyped[1] = (Val.UIntVal >>  8) & 255;
+                            Ptr->Untyped[2] = (Val.UIntVal >> 16) & 255;
+                            Ptr->Untyped[3] = (Val.UIntVal >> 24) & 255;
+                            break;
+    case Type::DoubleTyID:
+    case Type::ULongTyID:
+    case Type::LongTyID:    
+    case Type::PointerTyID: Ptr->Untyped[0] =  Val.ULongVal        & 255;
+                            Ptr->Untyped[1] = (Val.ULongVal >>  8) & 255;
+                            Ptr->Untyped[2] = (Val.ULongVal >> 16) & 255;
+                            Ptr->Untyped[3] = (Val.ULongVal >> 24) & 255;
+                            Ptr->Untyped[4] = (Val.ULongVal >> 32) & 255;
+                            Ptr->Untyped[5] = (Val.ULongVal >> 40) & 255;
+                            Ptr->Untyped[6] = (Val.ULongVal >> 48) & 255;
+                            Ptr->Untyped[7] = (Val.ULongVal >> 56) & 255;
+                            break;
+    default:
+      cout << "Cannot load value of type " << Ty << "!\n";
+    }
+  } else {
+    switch (Ty->getPrimitiveID()) {
+    case Type::BoolTyID:
+    case Type::UByteTyID:
+    case Type::SByteTyID:   Ptr->Untyped[0] = Val.UByteVal; break;
+    case Type::UShortTyID:
+    case Type::ShortTyID:   Ptr->Untyped[1] = Val.UShortVal & 255;
+                            Ptr->Untyped[0] = (Val.UShortVal >> 8) & 255;
+                            break;
+    case Type::FloatTyID:
+    case Type::UIntTyID:
+    case Type::IntTyID:     Ptr->Untyped[3] =  Val.UIntVal        & 255;
+                            Ptr->Untyped[2] = (Val.UIntVal >>  8) & 255;
+                            Ptr->Untyped[1] = (Val.UIntVal >> 16) & 255;
+                            Ptr->Untyped[0] = (Val.UIntVal >> 24) & 255;
+                            break;
+    case Type::DoubleTyID:
+    case Type::ULongTyID:
+    case Type::LongTyID:    
+    case Type::PointerTyID: Ptr->Untyped[7] =  Val.ULongVal        & 255;
+                            Ptr->Untyped[6] = (Val.ULongVal >>  8) & 255;
+                            Ptr->Untyped[5] = (Val.ULongVal >> 16) & 255;
+                            Ptr->Untyped[4] = (Val.ULongVal >> 24) & 255;
+                            Ptr->Untyped[3] = (Val.ULongVal >> 32) & 255;
+                            Ptr->Untyped[2] = (Val.ULongVal >> 40) & 255;
+                            Ptr->Untyped[1] = (Val.ULongVal >> 48) & 255;
+                            Ptr->Untyped[0] = (Val.ULongVal >> 56) & 255;
+                            break;
+    default:
+      cout << "Cannot load value of type " << Ty << "!\n";
+    }
+  }
+}
 
-  GenericValue *Ptr = (GenericValue *)SrcPtr;
+static void executeStoreInst(StoreInst &I, ExecutionContext &SF) {
   GenericValue Val = getOperandValue(I.getOperand(0), SF);
-
-  switch (I.getOperand(0)->getType()->getPrimitiveID()) {
-  case Type::BoolTyID:
-  case Type::UByteTyID:
-  case Type::SByteTyID:   Ptr->SByteVal = Val.SByteVal; break;
-  case Type::UShortTyID:
-  case Type::ShortTyID:   Ptr->ShortVal = Val.ShortVal; break;
-  case Type::UIntTyID:
-  case Type::IntTyID:     Ptr->IntVal = Val.IntVal; break;
-  case Type::ULongTyID:
-  case Type::LongTyID:    Ptr->LongVal = Val.LongVal; break;
-  case Type::PointerTyID: Ptr->PointerVal = Val.PointerVal; break;
-  case Type::FloatTyID:   Ptr->FloatVal = Val.FloatVal; break;
-  case Type::DoubleTyID:  Ptr->DoubleVal = Val.DoubleVal; break;
-  default:
-    cout << "Cannot store value of type " << I.getType() << "!\n";
-  }
+  GenericValue SRC = getOperandValue(I.getPointerOperand(), SF);
+  StoreValueToMemory(Val, (GenericValue *)SRC.PointerVal, I.getType());
 }
 
 
@@ -1000,11 +1093,10 @@ static void executeShrInst(ShiftInst &I, ExecutionContext &SF) {
    IMPLEMENT_CAST_CASE_FP_IMP(DESTTY, DESTCTY); \
    IMPLEMENT_CAST_CASE_END()
 
-static void executeCastInst(CastInst &I, ExecutionContext &SF) {
-  const Type *Ty    = I.getType();
-  const Type *SrcTy = I.getOperand(0)->getType();
-  GenericValue Src  = getOperandValue(I.getOperand(0), SF);
-  GenericValue Dest;
+static GenericValue executeCastOperation(Value *SrcVal, const Type *Ty,
+                                         ExecutionContext &SF) {
+  const Type *SrcTy = SrcVal->getType();
+  GenericValue Dest, Src = getOperandValue(SrcVal, SF);
 
   switch (Ty->getPrimitiveID()) {
     IMPLEMENT_CAST_CASE(UByte  , (unsigned char));
@@ -1021,10 +1113,14 @@ static void executeCastInst(CastInst &I, ExecutionContext &SF) {
   default:
     cout << "Unhandled dest type for cast instruction: " << Ty << "\n";
   }
-  SetValue(&I, Dest, SF);
+
+  return Dest;
 }
 
 
+static void executeCastInst(CastInst &I, ExecutionContext &SF) {
+  SetValue(&I, executeCastOperation(I.getOperand(0), I.getType(), SF), SF);
+}
 
 
 //===----------------------------------------------------------------------===//
@@ -1079,7 +1175,7 @@ void Interpreter::callMethod(Function *M, const vector<GenericValue> &ArgVals) {
         cout << "\n";
         
         if (RetTy->isIntegral())
-          ExitCode = Result.SByteVal;   // Capture the exit code of the program
+          ExitCode = Result.IntVal;   // Capture the exit code of the program
       }
     }
 
@@ -1138,7 +1234,7 @@ bool Interpreter::executeInstruction() {
   if (int SigNo = sigsetjmp(SignalRecoverBuffer, 1)) {
     --SF.CurInst;   // Back up to erroring instruction
     if (SigNo != SIGINT) {
-      cout << "EXCEPTION OCCURRED [" << _sys_siglistp[SigNo] << "]:\n";
+      cout << "EXCEPTION OCCURRED [" << strsignal(SigNo) << "]:\n";
       printStackTrace();
       // If -abort-on-exception was specified, terminate LLI instead of trying
       // to debug it.