[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