[llvm-commits] [hlvm] r38382 - in /hlvm/trunk/hlvm: AST/Bundle.cpp AST/Constants.cpp AST/Constants.h AST/ContainerType.h AST/Type.cpp AST/Type.h CodeGen/LLVMEmitter.cpp CodeGen/LLVMEmitter.h CodeGen/LLVMGenerator.cpp CodeGen/LLVMGenerator.h Pass/Validate.cpp Reader/HLVM.rng Reader/XMLReader.cpp

Reid Spencer reid at x10sys.com
Sat Jul 7 17:02:52 PDT 2007


Author: reid
Date: Sat Jul  7 19:02:51 2007
New Revision: 38382

URL: http://llvm.org/viewvc/llvm-project?rev=38382&view=rev
Log:
Implement several unimplemented or misimplemented features found via the
test case generator.

Modified:
    hlvm/trunk/hlvm/AST/Bundle.cpp
    hlvm/trunk/hlvm/AST/Constants.cpp
    hlvm/trunk/hlvm/AST/Constants.h
    hlvm/trunk/hlvm/AST/ContainerType.h
    hlvm/trunk/hlvm/AST/Type.cpp
    hlvm/trunk/hlvm/AST/Type.h
    hlvm/trunk/hlvm/CodeGen/LLVMEmitter.cpp
    hlvm/trunk/hlvm/CodeGen/LLVMEmitter.h
    hlvm/trunk/hlvm/CodeGen/LLVMGenerator.cpp
    hlvm/trunk/hlvm/CodeGen/LLVMGenerator.h
    hlvm/trunk/hlvm/Pass/Validate.cpp
    hlvm/trunk/hlvm/Reader/HLVM.rng
    hlvm/trunk/hlvm/Reader/XMLReader.cpp

Modified: hlvm/trunk/hlvm/AST/Bundle.cpp
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/AST/Bundle.cpp?rev=38382&r1=38381&r2=38382&view=diff

==============================================================================
--- hlvm/trunk/hlvm/AST/Bundle.cpp (original)
+++ hlvm/trunk/hlvm/AST/Bundle.cpp Sat Jul  7 19:02:51 2007
@@ -62,7 +62,9 @@
     ttable.insert(ty);
   } else if (Constant* C = dyn_cast<Constant>(kid)) {
     clist.push_back(C);
-    ctable.insert(C);
+    // Constants without names are permitted, but not Linkables
+    if (isa<Linkable>(C) || C->hasName())
+      ctable.insert(C);
   } else
     hlvmAssert("Don't know how to insert that in a Bundle");
 }

Modified: hlvm/trunk/hlvm/AST/Constants.cpp
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/AST/Constants.cpp?rev=38382&r1=38381&r2=38382&view=diff

==============================================================================
--- hlvm/trunk/hlvm/AST/Constants.cpp (original)
+++ hlvm/trunk/hlvm/AST/Constants.cpp Sat Jul  7 19:02:51 2007
@@ -29,6 +29,7 @@
 
 #include <hlvm/AST/Constants.h>
 #include <hlvm/AST/Type.h>
+#include <hlvm/AST/ContainerType.h>
 #include <hlvm/Base/Assert.h>
 #include <llvm/Support/Casting.h>
 
@@ -67,6 +68,14 @@
 }
 
 ConstantArray::~ConstantArray() { }
+
+const Type* 
+ConstantArray::getElementType() const
+{
+  const ArrayType* AT = llvm::cast<ArrayType>(this->getType());
+  return AT->getElementType();
+}
+
 ConstantVector::~ConstantVector() { }
 ConstantStructure::~ConstantStructure() { }
 ConstantContinuation::~ConstantContinuation() { }

Modified: hlvm/trunk/hlvm/AST/Constants.h
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/AST/Constants.h?rev=38382&r1=38381&r2=38382&view=diff

==============================================================================
--- hlvm/trunk/hlvm/AST/Constants.h (original)
+++ hlvm/trunk/hlvm/AST/Constants.h Sat Jul  7 19:02:51 2007
@@ -62,6 +62,7 @@
   public:
     /// Get the name of the Constant
     const std::string& getName() const { return name; }
+    bool hasName() const { return !name.empty(); }
     static inline bool classof(const Constant*) { return true; }
     static inline bool classof(const Node* N) { return N->isConstant(); }
 
@@ -438,6 +439,7 @@
   /// @name Accessors
   /// @{
   public:
+    const Type* getElementType() const;
     static inline bool classof(const ConstantArray*) { return true; }
     static inline bool classof(const Node* N) { return N->is(ConstantArrayID); }
 

Modified: hlvm/trunk/hlvm/AST/ContainerType.h
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/AST/ContainerType.h?rev=38382&r1=38381&r2=38382&view=diff

==============================================================================
--- hlvm/trunk/hlvm/AST/ContainerType.h (original)
+++ hlvm/trunk/hlvm/AST/ContainerType.h Sat Jul  7 19:02:51 2007
@@ -214,6 +214,7 @@
   public:
     /// Get the maximum size the array can grow to.
     const std::string& getName()  const { return name; }
+    bool hasName() const { return !name.empty(); }
     const Type* getType() const { return type; }
 
     /// Methods to support type inquiry via is, cast, dyn_cast

Modified: hlvm/trunk/hlvm/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/AST/Type.cpp?rev=38382&r1=38381&r2=38382&view=diff

==============================================================================
--- hlvm/trunk/hlvm/AST/Type.cpp (original)
+++ hlvm/trunk/hlvm/AST/Type.cpp Sat Jul  7 19:02:51 2007
@@ -170,6 +170,19 @@
 {
 }
 
+bool 
+EnumerationType::getEnumValue(const std::string& name, uint64_t& val) const
+{
+  val = 0;
+  for (const_iterator I = begin(), E = end(); I != E; ++I ) { 
+    if (*I == name)
+      return true;
+    val++;
+  }
+  val = 0;
+  return false;
+}
+
 const char* 
 EnumerationType::getPrimitiveName() const
 {

Modified: hlvm/trunk/hlvm/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/AST/Type.h?rev=38382&r1=38381&r2=38382&view=diff

==============================================================================
--- hlvm/trunk/hlvm/AST/Type.h (original)
+++ hlvm/trunk/hlvm/AST/Type.h Sat Jul  7 19:02:51 2007
@@ -62,6 +62,7 @@
   public:
     bool isIntrinsic() const { return flags & IntrinsicTF; }
     const std::string& getName() const { return name; }
+    bool hasName() const { return !name.empty(); }
     virtual const char* getPrimitiveName() const;
     bool isPrimitive() const { return getPrimitiveName() != 0; }
 
@@ -306,7 +307,7 @@
   /// @name Constructors
   /// @{
   protected:
-    RangeType(uint64_t n, uint64_t x) : Type(RangeTypeID), min(n), max(x) {}
+    RangeType(int64_t n, int64_t x) : Type(RangeTypeID), min(n), max(x) {}
     virtual ~RangeType();
 
   /// @}
@@ -366,6 +367,7 @@
   /// @{
   public:
     virtual const char* getPrimitiveName() const;
+    bool getEnumValue(const std::string& enum_name, uint64_t& val) const;
     // Methods to support type inquiry via is, cast, dyn_cast
     static inline bool classof(const EnumerationType*) { return true; }
     static inline bool classof(const Node* T) 

Modified: hlvm/trunk/hlvm/CodeGen/LLVMEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/CodeGen/LLVMEmitter.cpp?rev=38382&r1=38381&r2=38382&view=diff

==============================================================================
--- hlvm/trunk/hlvm/CodeGen/LLVMEmitter.cpp (original)
+++ hlvm/trunk/hlvm/CodeGen/LLVMEmitter.cpp Sat Jul  7 19:02:51 2007
@@ -36,14 +36,15 @@
 
 LLVMEmitter::LLVMEmitter()
   : TheModule(0), TheFunction(0), TheEntryBlock(0), TheExitBlock(0), 
-    EntryInsertionPoint(0), TheBlock(0), // TheTarget(0),
+    EntryInsertionPoint(0), TheBlock(0),
     hlvm_text(0), hlvm_text_create(0), hlvm_text_delete(0),
     hlvm_text_to_buffer(0), 
     hlvm_buffer(0), hlvm_buffer_create(0), hlvm_buffer_delete(0),
     hlvm_stream(0), hlvm_stream_open(0), hlvm_stream_read(0),
     hlvm_stream_write_buffer(0), hlvm_stream_write_text(0), 
     hlvm_stream_write_string(0), hlvm_stream_close(0), 
-    hlvm_program_signature(0)
+    hlvm_program_signature(0),
+    llvm_memcpy(0), llvm_memmove(0), llvm_memset(0)
 { 
 }
 
@@ -237,6 +238,321 @@
   continues.clear();
 }
 
+/// Return the number of elements in the specified type that will need to be 
+/// loaded/stored if we copy this one element at a time.
+unsigned 
+LLVMEmitter::getNumElements(const Type *Ty) 
+{
+  if (Ty->isFirstClassType()) return 1;
+
+  if (const StructType *STy = dyn_cast<StructType>(Ty)) {
+    unsigned NumElts = 0;
+    for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
+      NumElts += getNumElements(STy->getElementType(i));
+    return NumElts;
+  } else if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
+    return ATy->getNumElements() * getNumElements(ATy->getElementType());
+  } else if (const PackedType* PTy = dyn_cast<PackedType>(Ty)) {
+    return PTy->getNumElements() * getNumElements(PTy->getElementType());
+  } else
+    hlvmAssert(!"Don't know how to count elements of this type");
+  return 0;
+}
+
+Constant*
+LLVMEmitter::getFirstElement(GlobalVariable* GV)
+{
+  ArgList indices;
+  TwoZeroIndices(indices);
+  return ConstantExpr::getGetElementPtr(GV,indices);
+}
+
+FunctionType*
+LLVMEmitter::getFunctionType(
+  const std::string& name, const Type* resultTy, 
+  const TypeList& args, bool varargs)
+{
+  // The args might contain non-first-class typed arguments. We build a
+  // new argument list the contains the argument types after conversion.
+  TypeList Params;
+
+  // We can't have results that are not first class so we use the
+  // first argument to point to where the result should be stored and
+  // switch the result type to VoidTy.
+  if (!resultTy->isFirstClassType()) {
+    Params.push_back(getFirstClassType(resultTy));
+    resultTy = Type::VoidTy;
+  }
+
+  for (TypeList::const_iterator I = args.begin(), E = args.end(); I != E; ++I ) 
+  {
+    if ((*I)->isFirstClassType())
+      Params.push_back(*I);
+    else 
+      Params.push_back(getFirstClassType(*I));
+  }
+
+  FunctionType* result = FunctionType::get(resultTy, Params, varargs);
+  if (!name.empty())
+    TheModule->addTypeName(name,result);
+  return result;
+}
+
+void
+LLVMEmitter::emitAssign(Value* dest, Value* src)
+{
+  // If the destination is a load instruction then its the result of a previous
+  // nested block so just get the first operand as the real destination.
+  if (isa<LoadInst>(dest))
+    dest = cast<LoadInst>(dest)->getOperand(0);
+
+  // The destination must be a pointer type
+  hlvmAssert(isa<PointerType>(dest->getType()));
+
+  // Get the type of the destination and source
+  const Type* destTy = cast<PointerType>(dest->getType())->getElementType();
+  const Type* srcTy = src->getType();
+
+  if (destTy->isFirstClassType()) {
+    // Can't store an aggregate to a first class type
+    hlvmAssert(srcTy->isFirstClassType());
+    if (destTy == srcTy) {
+      // simple case, the types match and they are both first class types, 
+      // just emit a store instruction
+      emitStore(src,dest);
+    } else if (const PointerType* srcPT = dyn_cast<PointerType>(srcTy)) {
+      // The source is a pointer to the value to return so just get a
+      // pointer to its first element and store it since its pointing to
+      // a first class type. Assert that this is true.
+      hlvmAssert( srcPT->getElementType() == destTy );
+      ArgList idx;
+      TwoZeroIndices(idx);
+      GetElementPtrInst* GEP = new GetElementPtrInst(src, idx, "",TheBlock);
+      emitStore(GEP,dest);
+    } else {
+      // they are both first class types and the source is not a pointer, so 
+      // just cast them
+      CastInst* CI = emitCast(src,destTy,src->getName());
+      emitStore(CI,dest);
+    }
+  } 
+  else if (const PointerType* srcPT = dyn_cast<PointerType>(srcTy)) 
+  {
+    // We have an aggregate to copy
+    emitAggregateCopy(dest,src);
+  } 
+  else if (Constant* srcC = dyn_cast<Constant>(src)) 
+  {
+    // We have a constant aggregate to move into an aggregate gvar. We must
+    // create a temporary gvar based on the constant in order to copy it.
+    GlobalVariable* GVar = NewGConst(srcTy, srcC, srcC->getName());
+    // Now we can aggregate copy it
+    emitAggregateCopy(dest, GVar);
+  }
+}
+
+/// Recursively traverse the potientially aggregate src/dest ptrs, copying all 
+/// of the elements from src to dest.
+static void 
+CopyAggregate(
+  Value *DestPtr, 
+  bool DestVolatile, 
+  Value *SrcPtr, 
+  bool SrcVolatile,
+  BasicBlock *BB) 
+{
+  assert(DestPtr->getType() == SrcPtr->getType() &&
+         "Cannot copy between two pointers of different type!");
+  const Type *ElTy = cast<PointerType>(DestPtr->getType())->getElementType();
+  if (ElTy->isFirstClassType()) {
+    Value *V = new LoadInst(SrcPtr, "tmp", SrcVolatile, BB);
+    new StoreInst(V, DestPtr, DestVolatile, BB);
+  } else if (const StructType *STy = dyn_cast<StructType>(ElTy)) {
+    Constant *Zero = ConstantUInt::get(Type::UIntTy, 0);
+    for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
+      Constant *Idx = ConstantUInt::get(Type::UIntTy, i);
+      Value *DElPtr = new GetElementPtrInst(DestPtr, Zero, Idx, "tmp", BB);
+      Value *SElPtr = new GetElementPtrInst(SrcPtr, Zero, Idx, "tmp", BB);
+      CopyAggregate(DElPtr, DestVolatile, SElPtr, SrcVolatile, BB);
+    }
+  } else {
+    const ArrayType *ATy = cast<ArrayType>(ElTy);
+    Constant *Zero = ConstantUInt::get(Type::UIntTy, 0);
+    for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) {
+      Constant *Idx = ConstantUInt::get(Type::UIntTy, i);
+      Value *DElPtr = new GetElementPtrInst(DestPtr, Zero, Idx, "tmp", BB);
+      Value *SElPtr = new GetElementPtrInst(SrcPtr, Zero, Idx, "tmp", BB);
+      CopyAggregate(DElPtr, DestVolatile, SElPtr, SrcVolatile, BB);
+    }
+  }
+}
+
+/// EmitAggregateCopy - Copy the elements from SrcPtr to DestPtr, using the
+/// GCC type specified by GCCType to know which elements to copy.
+void 
+LLVMEmitter::emitAggregateCopy(
+  Value *DestPtr,
+  Value *SrcPtr )
+{
+  // Make sure we're not mixing apples and oranges
+  hlvmAssert(DestPtr->getType() == SrcPtr->getType());
+
+  // Degenerate case, same pointer
+  if (DestPtr == SrcPtr)
+    return;  // noop copy.
+
+  // If the type has just a few elements, then copy the elements directly 
+  // using load/store. Otherwise use the llvm.memcpy.i64 intrinsic. This just
+  // saves a function call for really small structures and arrays. 
+  const Type* Ty = SrcPtr->getType();
+  if (getNumElements(Ty) <= 8) 
+    CopyAggregate(DestPtr, false, SrcPtr, false, TheBlock);
+  else 
+    emitMemCpy(DestPtr, SrcPtr, llvm::ConstantExpr::getSizeOf(Ty));
+}
+
+ReturnInst*
+LLVMEmitter::emitReturn(Value* retVal)
+{
+  // First deal with the degenerate case, a void return
+  if (retVal == 0) {
+    hlvmAssert(getReturnType() == Type::VoidTy);
+    return new llvm::ReturnInst(0,TheBlock);
+  }
+
+  // Now, deal with first class result types. Becasue of the way function
+  // types are generated, a void type at this point indicates an aggregate
+  // result. If we don't have a void type, then it must be a first class result.
+  const Type* resultTy = retVal->getType();
+  if (getReturnType() != llvm::Type::VoidTy) {
+    Value* result = 0;
+    if (const PointerType* PTy = dyn_cast<PointerType>(resultTy)) {
+      // must be an autovar or global var, just load the value
+      hlvmAssert(PTy->getElementType() == getReturnType());
+      result = emitLoad(retVal,getBlockName() + "_result");
+    } else if (resultTy != getReturnType()) {
+      hlvmAssert(resultTy->isFirstClassType());
+      result = emitCast(retVal, getReturnType(), getBlockName()+"_result");
+    } else {
+      hlvmAssert(resultTy->isFirstClassType());
+      result = retVal;
+    }
+    hlvmAssert(result && "No result for function");
+    return new llvm::ReturnInst(result,TheBlock);
+  }
+
+  // Now, deal with the aggregate result case. At this point the function return
+  // type must be void and the first argument must be a pointer to the storage
+  // area for the result.
+  hlvmAssert(getReturnType() == Type::VoidTy);
+
+  // Get the first argument.
+  hlvmAssert(!TheFunction->arg_empty());
+  Argument* result_arg = TheFunction->arg_begin();
+
+  // Both the first argument and the result should have the same type which
+  // both should be pointer to the aggregate
+  hlvmAssert(result_arg->getType() == resultTy);
+
+  // Copy the aggregate result
+  emitAggregateCopy(result_arg, retVal);
+
+  // Emit the void return
+  return new llvm::ReturnInst(0, TheBlock);
+}
+
+llvm::CallInst* 
+LLVMEmitter::emitCall(llvm::Function* F, const ArgList& args) 
+{
+  // Detect the aggregate result case
+  if ((F->getReturnType() == Type::VoidTy) &&
+      (args.size() == F->arg_size() - 1)) {
+    const Type* arg1Ty = F->arg_begin()->getType();
+    if (const PointerType* PTy = dyn_cast<PointerType>(arg1Ty))
+    {
+      // This is the case where the result is a temporary variable that
+      // holds the aggregate and is passed as the first argument
+      const Type* elemTy = PTy->getElementType();
+      hlvmAssert(!elemTy->isFirstClassType());
+
+      // Get a temporary for the result
+      AllocaInst* result = NewAutoVar(elemTy, F->getName() + "_result");
+
+      // Install the temporary result area into a new arg list
+      ArgList newArgs;
+      newArgs.push_back(result);
+
+      // Copy the other arguments
+      for (ArgList::const_iterator I = args.begin(), E = args.end(); 
+           I != E; ++I)
+        if (isa<Constant>(*I) && !isa<GlobalValue>(*I) && 
+            !(*I)->getType()->isFirstClassType())
+          newArgs.push_back(NewGConst((*I)->getType(), 
+            cast<Constant>(*I), (*I)->getName()));
+        else
+          newArgs.push_back(*I);
+
+      // Generate the call
+      return new llvm::CallInst(F, newArgs, "", TheBlock);
+    }
+  }
+
+  // The result must be a first class type at this point, ensure it
+  hlvmAssert(F->getReturnType()->isFirstClassType());
+
+  return new llvm::CallInst(F, args, F->getName() + "_result", TheBlock);
+}
+
+void 
+LLVMEmitter::emitMemCpy(
+  llvm::Value *dest, 
+  llvm::Value *src, 
+  llvm::Value *size
+)
+{
+  const Type *SBP = PointerType::get(Type::SByteTy);
+  ArgList args;
+  args.push_back(CastToType(dest, SBP));
+  args.push_back(CastToType(src, SBP));
+  args.push_back(size);
+  args.push_back(ConstantUInt::get(Type::UIntTy, 0));
+  new CallInst(get_llvm_memcpy(), args, "", TheBlock);
+}
+
+/// Emit an llvm.memmove.i64 intrinsic
+void 
+LLVMEmitter::emitMemMove(
+  llvm::Value *dest,
+  llvm::Value *src, 
+  llvm::Value *size
+)
+{
+  const Type *SBP = PointerType::get(Type::SByteTy);
+  ArgList args;
+  args.push_back(CastToType(dest, SBP));
+  args.push_back(CastToType(src, SBP));
+  args.push_back(size);
+  args.push_back(ConstantUInt::get(Type::UIntTy, 0));
+  new CallInst(get_llvm_memmove(), args, "", TheBlock);
+}
+
+/// Emit an llvm.memset.i64 intrinsic
+void 
+LLVMEmitter::emitMemSet(
+  llvm::Value *dest, 
+  llvm::Value *val, 
+  llvm::Value *size 
+)
+{
+  const Type *SBP = PointerType::get(Type::SByteTy);
+  ArgList args;
+  args.push_back(CastToType(dest, SBP));
+  args.push_back(CastToType(val, Type::UByteTy));
+  args.push_back(size);
+  args.push_back(ConstantUInt::get(Type::UIntTy, 0));
+  new CallInst(get_llvm_memset(), args, "", TheBlock);
+}
+
 llvm::Type*
 LLVMEmitter::get_hlvm_size()
 {
@@ -247,6 +563,11 @@
 LLVMEmitter::get_hlvm_text()
 {
   if (! hlvm_text) {
+    // An hlvm_text is a variable length array of signed bytes preceded by
+    // an
+    // Arglist args;
+    // args.push_back(Type::UIntTy);
+    // args.push_back(ArrayType::Get(Type::SByteTy,0));
     llvm::OpaqueType* opq = llvm::OpaqueType::get();
     TheModule->addTypeName("hlvm_text_obj", opq);
     hlvm_text = llvm::PointerType::get(opq);
@@ -553,4 +874,41 @@
   return hlvm_program_signature;
 }
 
+llvm::Function* 
+LLVMEmitter::get_llvm_memcpy()
+{
+  if (!llvm_memcpy) {
+    const Type *SBP = PointerType::get(Type::SByteTy);
+    llvm_memcpy = TheModule->getOrInsertFunction(
+      "llvm.memcpy.i64", Type::VoidTy, SBP, SBP, Type::ULongTy, Type::UIntTy, 
+      NULL);
+  }
+  return llvm_memcpy;
+}
+
+llvm::Function* 
+LLVMEmitter::get_llvm_memmove()
+{
+  if (!llvm_memmove) {
+    const Type *SBP = PointerType::get(Type::SByteTy);
+    llvm_memmove = TheModule->getOrInsertFunction(
+      "llvm.memmove.i64", Type::VoidTy, SBP, SBP, Type::ULongTy, Type::UIntTy, 
+      NULL);
+  }
+
+  return llvm_memmove;
+}
+
+llvm::Function* 
+LLVMEmitter::get_llvm_memset()
+{
+  if (!llvm_memset) {
+    const Type *SBP = PointerType::get(Type::SByteTy);
+    llvm_memset = TheModule->getOrInsertFunction(
+      "llvm.memset.i64", Type::VoidTy, SBP, Type::UByteTy, Type::ULongTy, 
+      Type::UIntTy, NULL);
+  }
+  return llvm_memset;
+}
+
 }

Modified: hlvm/trunk/hlvm/CodeGen/LLVMEmitter.h
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/CodeGen/LLVMEmitter.h?rev=38382&r1=38381&r2=38382&view=diff

==============================================================================
--- hlvm/trunk/hlvm/CodeGen/LLVMEmitter.h (original)
+++ hlvm/trunk/hlvm/CodeGen/LLVMEmitter.h Sat Jul  7 19:02:51 2007
@@ -59,6 +59,9 @@
 /// A list of LLVM Values, used for argument lists
 typedef std::vector<llvm::Value*> ArgList;
 
+/// A list of LLVM types, used for function types
+typedef std::vector<const llvm::Type*> TypeList;
+
 /// This class provides utility functions for emitting LLVM code. It has no
 /// concept of how to translate HLVM into LLVM, that logic is in LLVMGenerator
 /// class. This class just keeps track of things in the LLVM world and provides
@@ -174,6 +177,14 @@
       return TheFunction->getReturnType();
     }
 
+    /// Return the total number of elements in the Type, examining recursively,
+    /// any nested aggregate types.
+    unsigned getNumElements(const llvm::Type *Ty);
+
+    /// Return a constant expression for indexing into the first element of
+    /// a constant global variable.
+    llvm::Constant* getFirstElement(llvm::GlobalVariable* GV);
+
     /// If V is a PointerType then load its value unless the referent type is
     /// not first class type
     llvm::Value* Pointer2Value(llvm::Value* V) const;
@@ -203,54 +214,24 @@
       indices.push_back(llvm::Constant::getNullValue(llvm::Type::UIntTy));
     }
 
-  /// @}
-  /// @name Accessors for interface to HLVM Runtime Library
-  /// @{
-  public:
-    /// Buffer manipulation methods
-    llvm::PointerType*  get_hlvm_buffer();
-    llvm::Function*     get_hlvm_buffer_create();
-    llvm::CallInst*     call_hlvm_buffer_create(
-        const ArgList& args, const char* name = 0);
-    llvm::Function*     get_hlvm_buffer_delete();
-    llvm::CallInst*     call_hlvm_buffer_delete(const ArgList& args);
-
-    /// Get the signature for an HLVM program
-    llvm::FunctionType* get_hlvm_program_signature();
-
-    /// Get the LLVM type for an HLVM "size" type
-    llvm::Type*         get_hlvm_size();
-
-    /// Stream manipulation methods
-    llvm::PointerType*  get_hlvm_stream();
-    llvm::Function*     get_hlvm_stream_open();
-    llvm::CallInst*     call_hlvm_stream_open(
-        const ArgList& args, const char* name = 0);
-    llvm::Function*     get_hlvm_stream_read();
-    llvm::CallInst*     call_hlvm_stream_read(
-        const ArgList& args, const char* name = 0);
-    llvm::Function*     get_hlvm_stream_write_buffer();
-    llvm::CallInst*     call_hlvm_stream_write_buffer(
-        const ArgList& args, const char* name = 0);
-    llvm::Function*     get_hlvm_stream_write_text();
-    llvm::CallInst*     call_hlvm_stream_write_text(
-        const ArgList& args, const char* name = 0);
-    llvm::Function*     get_hlvm_stream_write_string();
-    llvm::CallInst*     call_hlvm_stream_write_string(
-        const ArgList& args, const char* name = 0);
-    llvm::Function*     get_hlvm_stream_close();
-    llvm::CallInst*     call_hlvm_stream_close(const ArgList& args);
-
-    /// Text manipulation methods.
-    llvm::PointerType*  get_hlvm_text();
-    llvm::Function*     get_hlvm_text_create();
-    llvm::CallInst*     call_hlvm_text_create(
-        const ArgList& args, const char* name = 0);
-    llvm::Function*     get_hlvm_text_delete();
-    llvm::CallInst*     call_hlvm_text_delete(const ArgList& args);
-    llvm::Function*     get_hlvm_text_to_buffer();
-    llvm::CallInst*     call_hlvm_text_to_buffer(
-        const ArgList& args, const char* name = 0);
+    /// Convert a non-first-class type into a first-class type by constructing
+    /// a pointer to the original type.
+    const llvm::Type* getFirstClassType(const llvm::Type* Ty) {
+      if (!Ty->isFirstClassType())
+        return llvm::PointerType::get(Ty);
+      return Ty;
+    }
+
+    /// Get an LLVM FunctionType for the corresponding arguments. This handles
+    /// the details of converting non-first-class arguments and results into
+    /// the appropriate pointers to those types and making the first function
+    /// argument a pointer to the result storage, if necessary.
+    llvm::FunctionType* getFunctionType(
+      const std::string& name,       ///< The name to give the function type
+      const llvm::Type* resultTy,    ///< The type of the function's result
+      const TypeList& args,          ///< The list of the function's arguments
+      bool varargs                   ///< Whether its a varargs function or not
+    );
 
   /// @}
   /// @name Simple Value getters
@@ -274,7 +255,7 @@
       return llvm::ConstantFP::get(Ty,1.0);
     }
     llvm::Constant* getSOne() const {
-      return llvm::ConstantInt::get(llvm::Type::IntTy,1);
+      return llvm::ConstantSInt::get(llvm::Type::IntTy,1);
     }
     llvm::Constant* getUOne() const {
       return llvm::ConstantUInt::get(llvm::Type::UIntTy,1);
@@ -282,6 +263,12 @@
     llvm::Constant* getIOne(const llvm::Type* Ty) const {
       return llvm::ConstantInt::get(Ty,1);
     }
+    llvm::Constant* getSVal(const llvm::Type* Ty, int64_t val) const {
+      return llvm::ConstantSInt::get(Ty,val);
+    }
+    llvm::Constant* getUVal(const llvm::Type* Ty, uint64_t val) const {
+      return llvm::ConstantUInt::get(Ty,val);
+    }
     llvm::Constant* getNullValue(const llvm::Type* Ty) const { 
       return llvm::Constant::getNullValue(Ty);
     }
@@ -409,15 +396,50 @@
       continues.push_back(brnch);
       return brnch;
     }
-    llvm::ReturnInst* emitReturn(llvm::Value* V) {
-      return new llvm::ReturnInst(V,TheBlock);
-    }
-    llvm::CallInst* emitCall(llvm::Function* F, const ArgList& args) {
-      return new llvm::CallInst(F,args,"call_" + F->getName(),TheBlock);
-    }
+
+    llvm::ReturnInst* emitReturn(llvm::Value* V);
+
+    llvm::CallInst* emitCall(llvm::Function* F, const ArgList& args); 
+
     llvm::GetElementPtrInst* emitGEP(llvm::Value* V, const ArgList& indices) {
       return new llvm::GetElementPtrInst(V,indices,"",TheBlock);
     }
+
+    /// This method implements an assignment of a src value to a pointer to a
+    /// destination value. It handles all cases from a simple store instruction
+    /// for first class types, to construction of temporary global variables 
+    /// for assignment of constant aggregates to variables.
+    void emitAssign(llvm::Value* dest, llvm::Value* src);
+
+    /// Copy one aggregate to another. This method will use individual load and
+    /// store instructions for small aggregates or the llvm.memcpy intrinsic for
+    /// larger ones.
+    void emitAggregateCopy(
+      llvm::Value *DestPtr,  ///< Pointer to destination aggregate
+      llvm::Value *SrcPtr    ///< Pointer to source aggregate
+    );
+
+    /// Emit an llvm.memcpy.i64 intrinsic
+    void emitMemCpy(
+      llvm::Value *dest,  ///< A Pointer type value to receive the data
+      llvm::Value *src,   ///< A Pointer type value that is the data source
+      llvm::Value *size   ///< A ULong Type value to specify # of bytes to copy
+    );
+
+    /// Emit an llvm.memmove.i64 intrinsic
+    void emitMemMove(
+      llvm::Value *dest,  ///< A Pointer type value to receive the data
+      llvm::Value *src,   ///< A Pointer type value that is the data source
+      llvm::Value *size   ///< A ULong Type value to specify # of bytes to move
+    );
+
+    /// Emit an llvm.memset.i64 intrinsic
+    void emitMemSet(
+      llvm::Value *dest,  ///< A Pointer type value to receive the data
+      llvm::Value *val,   ///< An integer type that specifies the byte to set
+      llvm::Value *size   ///< A ULong Type value to specif # of bytes to set
+    );
+
   /// @}
   /// @name Other miscellaneous functions
   /// @{
@@ -431,38 +453,9 @@
     /// goto block.
     llvm::BasicBlock *getIndirectGotoBlock();
     
-    /// Copy the elements from SrcPtr to DestPtr, using the
-    /// GCC type specified by GCCType to know which elements to copy.
-    void EmitAggregateCopy(
-      llvm::Value *DestPtr, llvm::Value *SrcPtr, bool isVolatile);
-
     /// Zero the elements of DestPtr.
     void EmitAggregateZero(llvm::Value *DestPtr);
                            
-    /// Emit an llvm.memcpy.i32 or llvm.memcpy.i64 intrinsic
-    void EmitMemCpy(
-      llvm::Value *DestPtr, 
-      llvm::Value *SrcPtr, 
-      llvm::Value *Size, 
-      unsigned Align
-    );
-
-    /// Emit an llvm.memmove.i32 or llvm.memmove.i64 intrinsic
-    void EmitMemMove(
-      llvm::Value *DestPtr,
-      llvm::Value *SrcPtr, 
-      llvm::Value *Size, 
-      unsigned Align
-    );
-
-    /// Emit an llvm.memset.i32 or llvm.memset.i64 intrinsic
-    void EmitMemSet(
-      llvm::Value *DestPtr, 
-      llvm::Value *SrcVal, 
-      llvm::Value *Size, 
-      unsigned Align
-    );
-
     /// Emit an unconditional branch to the specified basic block, running 
     /// cleanups if the branch exits scopes.  The argument specify
     /// how to handle these cleanups.
@@ -474,6 +467,63 @@
     void AddBranchFixup(llvm::BranchInst *BI, bool isExceptionEdge);
 
   /// @}
+  /// @name Accessors for interface to HLVM Runtime Library
+  /// @{
+  public:
+    /// Buffer manipulation methods
+    llvm::PointerType*  get_hlvm_buffer();
+    llvm::Function*     get_hlvm_buffer_create();
+    llvm::CallInst*     call_hlvm_buffer_create(
+        const ArgList& args, const char* name = 0);
+    llvm::Function*     get_hlvm_buffer_delete();
+    llvm::CallInst*     call_hlvm_buffer_delete(const ArgList& args);
+
+    /// Get the signature for an HLVM program
+    llvm::FunctionType* get_hlvm_program_signature();
+
+    /// Get the LLVM type for an HLVM "size" type
+    llvm::Type*         get_hlvm_size();
+
+    /// Stream manipulation methods
+    llvm::PointerType*  get_hlvm_stream();
+    llvm::Function*     get_hlvm_stream_open();
+    llvm::CallInst*     call_hlvm_stream_open(
+        const ArgList& args, const char* name = 0);
+    llvm::Function*     get_hlvm_stream_read();
+    llvm::CallInst*     call_hlvm_stream_read(
+        const ArgList& args, const char* name = 0);
+    llvm::Function*     get_hlvm_stream_write_buffer();
+    llvm::CallInst*     call_hlvm_stream_write_buffer(
+        const ArgList& args, const char* name = 0);
+    llvm::Function*     get_hlvm_stream_write_text();
+    llvm::CallInst*     call_hlvm_stream_write_text(
+        const ArgList& args, const char* name = 0);
+    llvm::Function*     get_hlvm_stream_write_string();
+    llvm::CallInst*     call_hlvm_stream_write_string(
+        const ArgList& args, const char* name = 0);
+    llvm::Function*     get_hlvm_stream_close();
+    llvm::CallInst*     call_hlvm_stream_close(const ArgList& args);
+
+    /// Text manipulation methods.
+    llvm::PointerType*  get_hlvm_text();
+    llvm::Function*     get_hlvm_text_create();
+    llvm::CallInst*     call_hlvm_text_create(
+        const ArgList& args, const char* name = 0);
+    llvm::Function*     get_hlvm_text_delete();
+    llvm::CallInst*     call_hlvm_text_delete(const ArgList& args);
+    llvm::Function*     get_hlvm_text_to_buffer();
+    llvm::CallInst*     call_hlvm_text_to_buffer(
+        const ArgList& args, const char* name = 0);
+
+  /// @}
+  /// @name Accessors for LLVM intrinsics
+  /// @{
+  public:
+    llvm::Function* get_llvm_memcpy();
+    llvm::Function* get_llvm_memmove();
+    llvm::Function* get_llvm_memset();
+
+  /// @}
   /// @name Data Members
   /// @{
   private:
@@ -486,7 +536,6 @@
     llvm::BasicBlock* TheExitBlock; ///< The function's exit (return) block
     llvm::Instruction* EntryInsertionPoint; ///< Insertion point for entry stuff
     llvm::BasicBlock* TheBlock;     ///< The current block we're building
-    //llvm::TargetMachine *TheTarget; /// The current target being compiled for.
 
     // Caches of things to interface with the HLVM Runtime Library
     llvm::PointerType*  hlvm_text;          ///< Opaque type for text objects
@@ -504,6 +553,12 @@
     llvm::Function*     hlvm_stream_write_string; ///< Write string to stream
     llvm::Function*     hlvm_stream_close;  ///< Function for stream_close
     llvm::FunctionType* hlvm_program_signature; ///< The llvm type for programs
+
+    // Caches of LLVM Intrinsic functions
+    llvm::Function*     llvm_memcpy;         ///< llvm.memcpy.i64
+    llvm::Function*     llvm_memmove;        ///< llvm.memmove.i64
+    llvm::Function*     llvm_memset;         ///< llvm.memset.i64
+
   /// @}
 };
 

Modified: hlvm/trunk/hlvm/CodeGen/LLVMGenerator.cpp
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/CodeGen/LLVMGenerator.cpp?rev=38382&r1=38381&r2=38382&view=diff

==============================================================================
--- hlvm/trunk/hlvm/CodeGen/LLVMGenerator.cpp (original)
+++ hlvm/trunk/hlvm/CodeGen/LLVMGenerator.cpp Sat Jul  7 19:02:51 2007
@@ -284,13 +284,16 @@
     }
     case SignatureTypeID:
     {
-      std::vector<const llvm::Type*> params;
+      TypeList params;
       const SignatureType* st = llvm::cast<SignatureType>(ty);
+      // Now, push the arguments onto the argument list
       for (SignatureType::const_iterator I = st->begin(), E = st->end(); 
            I != E; ++I)
-        params.push_back(getFirstClassType((*I)->getType()));
-      result = llvm::FunctionType::get(
-        getFirstClassType(st->getResultType()),params,st->isVarArgs());
+        params.push_back(getType((*I)->getType()));
+      // Get the Result Type
+      const llvm::Type* resultTy = getType(st->getResultType());
+      result = 
+        em.getFunctionType(st->getName(), resultTy, params, st->isVarArgs());
       break;
     }
     case OpaqueTypeID: {
@@ -338,17 +341,31 @@
       result = llvm::ConstantBool::get(CI->getValue());
       break;
     }
+    case ConstantEnumeratorID:
+    {
+      const ConstantEnumerator* CE = llvm::cast<ConstantEnumerator>(C);
+      const EnumerationType* eType = llvm::cast<EnumerationType>(C->getType());
+      uint64_t val = 0;
+      bool gotEnumValue = eType->getEnumValue( CE->getValue(), val );
+      hlvmAssert(gotEnumValue && "Enumerator not valid for type");
+      result = em.getUVal(lType,val);
+      break;
+    }
     case ConstantIntegerID:
     {
       const ConstantInteger* CI = llvm::cast<const ConstantInteger>(C);
-      const IntegerType* iType = llvm::cast<IntegerType>(hType);
-      if (iType->isSigned()) {
+      if (const IntegerType* iType = llvm::dyn_cast<IntegerType>(hType)) {
+        if (iType->isSigned()) {
+          int64_t val = strtoll(CI->getValue().c_str(),0,CI->getBase());
+          result = em.getSVal(lType,val);
+        }
+        else {
+          uint64_t val = strtoull(CI->getValue().c_str(),0,CI->getBase());
+          result = em.getUVal(lType,val);
+        }
+      } else if (const RangeType* rType = llvm::dyn_cast<RangeType>(hType)) {
         int64_t val = strtoll(CI->getValue().c_str(),0,CI->getBase());
-        result = llvm::ConstantSInt::get(lType,val);
-      }
-      else {
-        uint64_t val = strtoull(CI->getValue().c_str(),0,CI->getBase());
-        result = llvm::ConstantUInt::get(lType,val);
+        result = em.getSVal(lType,val);
       }
       break;
     }
@@ -382,13 +399,21 @@
     case ConstantArrayID:
     {
       const ConstantArray* hCA = llvm::cast<ConstantArray>(C);
-      const llvm::ArrayType* Ty = 
-        llvm::cast<llvm::ArrayType>(getType(hCA->getType()));
+      const llvm::Type* elemType = getType(hCA->getElementType());
+      const llvm::ArrayType* lAT = llvm::ArrayType::get(elemType,hCA->size());
       std::vector<llvm::Constant*> elems;
       for (ConstantArray::const_iterator I = hCA->begin(), E = hCA->end();
            I != E; ++I )
         elems.push_back(getConstant(*I));
-      result = llvm::ConstantArray::get(Ty,elems);
+      llvm::Constant* lCA = llvm::ConstantArray::get(lAT,elems);
+      llvm::GlobalVariable* lGV = em.NewGConst(lAT,lCA,hCA->getName()+"_init");
+      llvm::Constant* lCE = em.getFirstElement(lGV);
+      const llvm::StructType* Ty = 
+        llvm::cast<llvm::StructType>(getType(hCA->getType()));
+      elems.clear();
+      elems.push_back(em.getUVal(llvm::Type::UIntTy,hCA->size()));
+      elems.push_back(lCE);
+      result = llvm::ConstantStruct::get(Ty,elems);
       break;
     }
     case ConstantVectorID:
@@ -641,7 +666,7 @@
   if (!llvm::isa<Block>(op->getParent())) {
     const llvm::Type* Ty = getType(op->getType());
     result = em.NewAutoVar(Ty, name + "_var");
-    em.emitStore(em.getNullValue(Ty),result);
+    em.emitAssign(result,em.getNullValue(Ty));
   }
   return result;
 }
@@ -694,35 +719,7 @@
     C = getConstant(av->getInitializer());
   else
     C = em.getNullValue(elemType);
-
-  if (C) {
-    const llvm::Type* CType = C->getType();
-    if (CType != elemType) {
-      if (llvm::isa<llvm::PointerType>(CType) && 
-          llvm::isa<llvm::PointerType>(elemType)) {
-        const llvm::Type* CElemType = 
-          llvm::cast<llvm::PointerType>(CType)->getElementType();
-        const llvm::Type* avElemType = 
-            llvm::cast<llvm::PointerType>(elemType)->getElementType();
-        if (CElemType != avElemType)
-        {
-          // We have pointers to different element types. This *can* be okay if
-          // we apply conversions.
-          if (CElemType == llvm::Type::SByteTy) {
-            // The initializer is an sbyte*, which we can convert to either a
-            // hlvm_text or an hlvm_buffer.
-            if (elemType == em.get_hlvm_buffer()) {
-              // Assign the constant string to the buffer
-            } else if (elemType == em.get_hlvm_text()) {
-            }
-          }
-        }
-      }
-      hlvmAssert(CType->isLosslesslyConvertibleTo(elemType));
-      C = llvm::ConstantExpr::getCast(C,elemType);
-    }
-    llvm::Value* store = em.emitStore(C,alloca);
-  }
+  em.emitAssign(alloca,C);
   pushOperand(alloca,av);
   lvars[av] = alloca;
 }
@@ -1314,62 +1311,29 @@
 LLVMGeneratorPass::gen(ResultOp* r)
 {
   // Get the result operand
-  llvm::Value* result = popOperand(r->getOperand(0));
+  llvm::Value* src = popOperand(r->getOperand(0));
   // Get the block this result applies to
   hlvm::Block* B = llvm::cast<hlvm::Block>(r->getParent());
   // Get the location into which we will store the result
-  llvm::Value* instr = operands[B];
+  llvm::Value* dest = operands[B];
 
-  // If the value to be stored is not first class
-  if (const llvm::PointerType* PT = 
-      llvm::dyn_cast<llvm::PointerType>(instr->getType()))  {
-    if (!PT->getElementType()->isFirstClassType()) {
-      // We have to treat non-first class values specially because LLVM won't
-      // store anything other than first-class values. If the number of stores
-      // required is <= 8 then we emit them individually, otherwise we call
-      // the llvm intrinsic llvm_memcpy_i32.
-      const llvm::Type* Ty = PT->getElementType();
-      if (const llvm::StructType* ST = llvm::dyn_cast<llvm::StructType>(Ty)) {
-        if (ST->getNumElements() > 8) {
-          // Use the intrinsic
-        } else {
-          // sequence of stores
-        }
-      } else if (const llvm::ArrayType* AT = 
-                 llvm::dyn_cast<llvm::ArrayType>(AT)) {
-      }
-    }
-  }
-  // Generate a store into the location set up by the block for its result
-  if (llvm::isa<llvm::LoadInst>(instr))
-    instr = llvm::cast<llvm::LoadInst>(instr)->getOperand(0);
-  em.emitStore(result,instr);
+  // Assign the source to the destination
+  em.emitAssign(dest, src);
 }
 
 template<> void
 LLVMGeneratorPass::gen(ReturnOp* r)
 {
-  // Initialize the result value. A null Value* indicates no result.
-  llvm::Value* result = 0;
-
-  // If this function returns a result then we need a return value
-  if (em.getReturnType() != llvm::Type::VoidTy) {
-    result = operands[function->getBlock()];
-    const llvm::Type* resultTy = result->getType();
-    if (const llvm::PointerType* PTy = 
-        llvm::dyn_cast<llvm::PointerType>(resultTy)) {
-      hlvmAssert(PTy->getElementType() == em.getReturnType());
-      result = em.emitLoad(result,em.getBlockName()+ "_result");
-    } else if (resultTy != em.getReturnType()) {
-      result = em.emitCast(result, em.getReturnType(), 
-        em.getBlockName()+"_result");
-    }
-    hlvmAssert(result && "No result for function");
+  // First, if this function returns nothing (void) then just issue a void
+  // return instruction.
+  const Type* resTy = function->getResultType();
+  if (resTy == 0) {
+    em.emitReturn(0);
+    return;
   }
 
-  // RetInst is never the operand of another instruction because it is
-  // a terminator and cannot return a value. Consequently, we don't push it
-  // on the operand stack.
+  // If we get here then the function has a result. 
+  llvm::Value* result = operands[function->getBlock()];
   em.emitReturn(result);
 }
 
@@ -1414,7 +1378,7 @@
   llvm::Value* value =    popOperand(s->getOperand(1));
   // We don't push the StoreInst as an operand because it has no value and
   // therefore cannot be an operand.
-  em.emitStore(value,location);
+  em.emitAssign(location,value);
 }
 
 template<> void
@@ -1656,7 +1620,7 @@
           const llvm::Type* Ty = getType(B->getType());
           llvm::AllocaInst* result = em.NewAutoVar(Ty, name+"_var");
           // Initialize the autovar to null
-          em.emitStore(em.getNullValue(Ty),result);
+          em.emitAssign(result,em.getNullValue(Ty));
           pushOperand(result,B); 
         }
         break;
@@ -1742,6 +1706,7 @@
         modules.push_back(em.FinishModule());
         break;
       case ConstantBooleanID:       
+      case ConstantEnumeratorID:
       case ConstantIntegerID:      
       case ConstantRealID:        
       case ConstantStringID:     
@@ -1798,18 +1763,21 @@
 }
 
 
-llvm::cl::opt<bool>
-  NoInline("no-inlining", 
-    llvm::cl::desc("Do not run the LLVM inliner pass"));
-
-llvm::cl::opt<bool>
-  NoOptimizations("no-optimization",
-    llvm::cl::desc("Do not run any LLVM optimization passes"));
+llvm::cl::opt<bool> NoVerify("no-verify", 
+  llvm::cl::init(false),
+  llvm::cl::desc("Don't verify generated LLVM module"));
+
+llvm::cl::opt<bool> NoInline("no-inlining", 
+  llvm::cl::init(false),
+ llvm::cl::desc("Do not run the LLVM inliner pass"));
+
+llvm::cl::opt<bool> NoOptimizations("no-optimization",
+  llvm::cl::init(false),
+  llvm::cl::desc("Do not run any LLVM optimization passes"));
 
-void 
+static void 
 getCleanupPasses(llvm::PassManager& PM)
 {
-  
   PM.add(llvm::createLowerSetJmpPass());          // Lower llvm.setjmp/.longjmp
   PM.add(llvm::createFunctionResolvingPass());    // Resolve (...) functions
   if (NoOptimizations)
@@ -1860,10 +1828,26 @@
   PM.add(llvm::createConstantMergePass());        // Merge dup global constants
 }
 
+static bool
+optimizeModule(llvm::Module* mod, std::string& ErrMsg)
+{
+  llvm::PassManager Passes;
+  Passes.add(new llvm::TargetData(mod));
+  if (!NoVerify)
+    if (llvm::verifyModule(*mod,llvm::ReturnStatusAction,&ErrMsg))
+      return false;
+  getCleanupPasses(Passes);
+  Passes.run(*mod);
+  if (!NoVerify)
+    if (llvm::verifyModule(*mod,llvm::ReturnStatusAction,&ErrMsg))
+      return false;
+  return true;
+}
+
 }
 
 bool
-hlvm::generateBytecode(AST* tree, std::ostream& output, bool verify)
+hlvm::generateBytecode(AST* tree, std::ostream& output, std::string& ErrMsg)
 {
   hlvm::PassManager* PM = hlvm::PassManager::create();
   LLVMGeneratorPass genPass(tree);
@@ -1871,23 +1855,15 @@
   PM->runOn(tree);
   delete PM;
   llvm::Module* mod = genPass.linkModules();
-  bool result = false;
-  llvm::PassManager Passes;
-  Passes.add(new llvm::TargetData(mod));
-  if (verify)
-    Passes.add(llvm::createVerifierPass());
-  getCleanupPasses(Passes);
-  if (verify)
-    Passes.add(llvm::createVerifierPass());
-  Passes.run(*mod);
-  llvm::WriteBytecodeToFile(mod, output, /*compress= */ true);
-  result = true;
+  bool result = optimizeModule(mod,ErrMsg);
+  if (result)
+    llvm::WriteBytecodeToFile(mod, output, /*compress= */ true);
   delete mod;
   return result;
 }
 
 bool
-hlvm::generateAssembly(AST* tree, std::ostream& output, bool verify)
+hlvm::generateAssembly(AST* tree, std::ostream& output, std::string& ErrMsg)
 {
   hlvm::PassManager* PM = hlvm::PassManager::create();
   LLVMGeneratorPass genPass(tree);
@@ -1895,23 +1871,18 @@
   PM->runOn(tree);
   delete PM;
   llvm::Module* mod = genPass.linkModules();
-  bool result = false;
-  llvm::PassManager lPM;
-  lPM.add(new llvm::TargetData(mod));
-  if (verify)
-    lPM.add(llvm::createVerifierPass());
-  getCleanupPasses(lPM);
-  if (verify)
-    lPM.add(llvm::createVerifierPass());
-  lPM.add(new llvm::PrintModulePass(&output));
-  lPM.run(*mod);
-  result = true;
+  bool result = optimizeModule(mod,ErrMsg);
+  if (result) {
+    llvm::PassManager Passes;
+    Passes.add(new llvm::PrintModulePass(&output));
+    Passes.run(*mod);
+  }
   delete mod;
   return result;
 }
 
 llvm::Module* 
-hlvm::generateModule(AST* tree, bool verify)
+hlvm::generateModule(AST* tree, std::string& ErrMsg)
 {
   hlvm::PassManager* PM = hlvm::PassManager::create();
   LLVMGeneratorPass genPass(tree);
@@ -1919,14 +1890,10 @@
   PM->runOn(tree);
   delete PM;
   llvm::Module* mod = genPass.linkModules();
-  llvm::PassManager lPM;
-  lPM.add(new llvm::TargetData(mod));
-  if (verify)
-    lPM.add(llvm::createVerifierPass());
-  getCleanupPasses(lPM);
-  if (verify)
-    lPM.add(llvm::createVerifierPass());
-  lPM.run(*mod);
+  if (!optimizeModule(mod,ErrMsg)) {
+    delete mod;
+    return 0;
+  }
   return mod;
 }
 

Modified: hlvm/trunk/hlvm/CodeGen/LLVMGenerator.h
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/CodeGen/LLVMGenerator.h?rev=38382&r1=38381&r2=38382&view=diff

==============================================================================
--- hlvm/trunk/hlvm/CodeGen/LLVMGenerator.h (original)
+++ hlvm/trunk/hlvm/CodeGen/LLVMGenerator.h Sat Jul  7 19:02:51 2007
@@ -42,14 +42,14 @@
 
   /// Convert an Abstract Syntax Tree into LLVM bytecode written on the output 
   /// stream.
-  bool generateBytecode(AST* input, std::ostream& output, bool verify = true);
+  bool generateBytecode(AST* input, std::ostream& output, std::string& ErrMsg);
 
   /// Convert an Abstract Syntax Tree into LLVM assembly written on the output
   /// stream.
-  bool generateAssembly(AST* input, std::ostream& output, bool verify = true);
+  bool generateAssembly(AST* input, std::ostream& output, std::string& ErrMsg);
 
   /// Convert an Abstract Syntax Tree into an LLVM Module
-  llvm::Module* generateModule(AST* input, bool verify = true);
+  llvm::Module* generateModule(AST* input, std::string& ErrMsg );
 
 } // hlvm
 #endif

Modified: hlvm/trunk/hlvm/Pass/Validate.cpp
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/Pass/Validate.cpp?rev=38382&r1=38381&r2=38382&view=diff

==============================================================================
--- hlvm/trunk/hlvm/Pass/Validate.cpp (original)
+++ hlvm/trunk/hlvm/Pass/Validate.cpp Sat Jul  7 19:02:51 2007
@@ -144,7 +144,7 @@
     error(t,"Bad ID for a Type");
     result = false;
   }
-  if (t->getName().empty()) {
+  if (!t->hasName()) {
     error(t, "Empty type name");
     result = false;
   }
@@ -169,8 +169,8 @@
 ValidateImpl::checkConstant(Constant* C,NodeIDs id)
 {
   if (checkValue(C,id)) {
-    if (C->getName().empty()) {
-      error(C,"Constants must not have empty name");
+    if (!C->hasName() && llvm::isa<Linkable>(C)) {
+      error(C,"Linkables must not have an empty name");
       return false;
     }
   }
@@ -239,7 +239,7 @@
         error(n,std::string("Null type not permited in DisparateContainerType")
             + " for '" + (*I)->getName() + "'");
         result = false;
-      } else if ((*I)->getName().empty()) {
+      } else if (!(*I)->hasName()) {
         error((*I)->getType(),"Type has no field name");
         result = false;
       }
@@ -489,7 +489,16 @@
 template<> inline void
 ValidateImpl::validate(ConstantEnumerator* n)
 {
-  checkConstant(n,ConstantEnumeratorID);
+  if (checkConstant(n,ConstantEnumeratorID)) {
+    uint64_t val;
+    if (const EnumerationType* ET = dyn_cast<EnumerationType>(n->getType())) {
+      if (!ET->getEnumValue( n->getValue(), val))
+        error(n, "Enumerator '" + n->getValue() + "' not valid for type '" +
+          ET->getName());
+    } else {
+      error(n,"Type for ConstantEnumerator is not EnumerationType");
+    }
+  }
 }
 
 template<> inline void
@@ -547,7 +556,8 @@
       unsigned exp_bits_required = (sizeof(uint64_t)*8 - leading_zeros);
       const RealType* Ty = llvm::cast<RealType>(CR->getType());
       if (Ty->getExponent() < exp_bits_required) {
-        error(CR,"Real constant requires too many exponent bits for type '" +
+        error(CR,"Real constant requires too many exponent bits (" +
+            llvm::utostr(exp_bits_required) + ") for type '" +
             Ty->getName() + "'");
         return;
       }

Modified: hlvm/trunk/hlvm/Reader/HLVM.rng
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/Reader/HLVM.rng?rev=38382&r1=38381&r2=38382&view=diff

==============================================================================
--- hlvm/trunk/hlvm/Reader/HLVM.rng (original)
+++ hlvm/trunk/hlvm/Reader/HLVM.rng Sat Jul  7 19:02:51 2007
@@ -500,6 +500,7 @@
       <ref name="vect.elem"/>
       <ref name="struct.elem"/>
       <ref name="cont.elem"/>
+      <ref name="cref.elem"/>
     </choice>
   </define>
 
@@ -635,6 +636,13 @@
     </element>
   </define>
 
+  <define name="cref.elem">
+    <element name="ref">
+      <ref name="Named_Element.pat"/>
+      <ref name="Documentation.pat"/>
+    </element>
+  </define>
+
   <!-- PATTERNS FOR VARIABLES-->
 
   <define name="variable.elem">

Modified: hlvm/trunk/hlvm/Reader/XMLReader.cpp
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/Reader/XMLReader.cpp?rev=38382&r1=38381&r2=38382&view=diff

==============================================================================
--- hlvm/trunk/hlvm/Reader/XMLReader.cpp (original)
+++ hlvm/trunk/hlvm/Reader/XMLReader.cpp Sat Jul  7 19:02:51 2007
@@ -403,14 +403,12 @@
   switch (token) {
     case TKN_false:   
     {
-      std::string nm = name.empty() ? "bool_false" : name;
-      C = ast->new_ConstantBoolean(nm, bundle,Ty,false, getLocator(cur)); 
+      C = ast->new_ConstantBoolean(name, bundle,Ty,false, getLocator(cur)); 
       break;
     }
     case TKN_true:
     {
-      std::string nm = name.empty() ? "bool_true" : name;
-      C = ast->new_ConstantBoolean(nm,bundle,Ty,true, getLocator(cur));
+      C = ast->new_ConstantBoolean(name,bundle,Ty,true, getLocator(cur));
       break;
     }
     case TKN_bool:
@@ -419,9 +417,7 @@
       xmlNodePtr child = cur->children;
       getTextContent(child,buffer);
       bool value = recognize_boolean( buffer.c_str() );
-      std::string nm = name.empty() ? std::string("bool_") + 
-        (value?"true_":"false") : name;
-      C = ast->new_ConstantBoolean(nm, bundle,Ty,value, getLocator(cur));
+      C = ast->new_ConstantBoolean(name, bundle,Ty,value, getLocator(cur));
       break;
     }
     case TKN_char:
@@ -429,8 +425,7 @@
       std::string buffer;
       xmlNodePtr child = cur->children;
       getTextContent(child,buffer);
-      std::string nm = name.empty() ?  std::string("char_") + buffer : name;
-      C = ast->new_ConstantCharacter(nm, bundle,Ty,buffer, getLocator(cur));
+      C = ast->new_ConstantCharacter(name, bundle,Ty,buffer, getLocator(cur));
       break;
     }
     case TKN_enum:
@@ -438,8 +433,7 @@
       std::string value;
       xmlNodePtr child = cur->children;
       getTextContent(child,value);
-      std::string nm = name.empty() ? std::string("enum_") + value : name;
-      C = ast->new_ConstantEnumerator(nm,bundle,Ty,value,getLocator(cur));
+      C = ast->new_ConstantEnumerator(name,bundle,Ty,value,getLocator(cur));
       break;
     }
     case TKN_bin:
@@ -452,8 +446,7 @@
       getTextContent(child,value);
       uint16_t base = (token == TKN_dec ? 10 : (token == TKN_hex ? 16 : 
                       (token == TKN_oct ? 8 : (token == TKN_bin ? 2 : 10))));
-      std::string nm = name.empty() ?  std::string("int_") + value : name;
-      C = ast->new_ConstantInteger(nm,bundle,Ty,value,base,getLocator(cur));
+      C = ast->new_ConstantInteger(name,bundle,Ty,value,base,getLocator(cur));
       break;
     }
     case TKN_flt:
@@ -463,8 +456,7 @@
       std::string value;
       xmlNodePtr child = cur->children;
       getTextContent(child,value);
-      std::string nm = name.empty() ? std::string("real_") + value : name;
-      C = ast->new_ConstantReal(nm,bundle,Ty,value,getLocator(cur));
+      C = ast->new_ConstantReal(name,bundle,Ty,value,getLocator(cur));
       break;
     }
     case TKN_str:
@@ -472,18 +464,16 @@
       std::string value;
       xmlNodePtr child = cur->children;
       getTextContent(child,value);
-      std::string nm = name.empty() ? std::string("str_") + value : name;
-      C =  ast->new_ConstantString(nm,bundle,Ty,value,getLocator(cur));
+      C =  ast->new_ConstantString(name,bundle,Ty,value,getLocator(cur));
       break;
     }
     case TKN_ptr:
     {
       std::string to = getAttribute(cur,"to");
-      std::string nm = name.empty() ? std::string("ptr_") + to : name;
       Constant* referent = bundle->getConst(to);
       if (!referent)
         error(loc,"Unkown referent for constant pointer");
-      C = ast->new_ConstantPointer(nm,bundle,Ty,referent,loc);
+      C = ast->new_ConstantPointer(name,bundle,Ty,referent,loc);
       break;
     }
     case TKN_arr:
@@ -497,8 +487,7 @@
         elems.push_back(elem);
         child = child->next;
       }
-      std::string nm = name.empty() ? std::string("arr") : name;
-      C = ast->new_ConstantArray(nm,bundle,AT,elems,getLocator(cur));
+      C = ast->new_ConstantArray(name,bundle,AT,elems,getLocator(cur));
       break;
     }
     case TKN_vect:
@@ -512,8 +501,7 @@
         elems.push_back(elem);
         child = child->next;
       }
-      std::string nm = name.empty() ? std::string("vec") : name;
-      C = ast->new_ConstantVector(nm,bundle,VT,elems,getLocator(cur));
+      C = ast->new_ConstantVector(name,bundle,VT,elems,getLocator(cur));
       break;
     }
     case TKN_struct:
@@ -528,8 +516,7 @@
         child = child->next;
         ++I;
       }
-      std::string nm = name.empty() ? std::string("struct") :name;
-      C = ast->new_ConstantStructure(nm,bundle,ST,fields,getLocator(cur));
+      C = ast->new_ConstantStructure(name,bundle,ST,fields,getLocator(cur));
       break;
     }
     case TKN_cont:
@@ -544,8 +531,7 @@
         child = child->next;
         ++I;
       }
-      std::string nm = name.empty() ? std::string("struct") :name;
-      C = ast->new_ConstantContinuation(nm,bundle,CT,fields,getLocator(cur));
+      C = ast->new_ConstantContinuation(name,bundle,CT,fields,getLocator(cur));
       break;
     }
     default:





More information about the llvm-commits mailing list