[llvm-commits] [hlvm] r38380 - in /hlvm/trunk/hlvm/CodeGen: LLVMEmitter.cpp LLVMEmitter.h LLVMGenerator.cpp

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


Author: reid
Date: Sat Jul  7 19:02:50 2007
New Revision: 38380

URL: http://llvm.org/viewvc/llvm-project?rev=38380&view=rev
Log:
Factor the LLVM Code Emission components out of the LLVM Generator. This is just
to unclutter the Generator code and ensure that a consistent model for code
generation is used.

Added:
    hlvm/trunk/hlvm/CodeGen/LLVMEmitter.cpp
    hlvm/trunk/hlvm/CodeGen/LLVMEmitter.h
Modified:
    hlvm/trunk/hlvm/CodeGen/LLVMGenerator.cpp

Added: hlvm/trunk/hlvm/CodeGen/LLVMEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/CodeGen/LLVMEmitter.cpp?rev=38380&view=auto

==============================================================================
--- hlvm/trunk/hlvm/CodeGen/LLVMEmitter.cpp (added)
+++ hlvm/trunk/hlvm/CodeGen/LLVMEmitter.cpp Sat Jul  7 19:02:50 2007
@@ -0,0 +1,552 @@
+//===-- LLVM Code Emitter Implementation ------------------------*- C++ -*-===//
+//
+//                      High Level Virtual Machine (HLVM)
+//
+// Copyright (C) 2006 Reid Spencer. All Rights Reserved.
+//
+// This software is free software; you can redistribute it and/or modify it 
+// under the terms of the GNU Lesser General Public License as published by 
+// the Free Software Foundation; either version 2.1 of the License, or (at 
+// your option) any later version.
+//
+// This software is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for 
+// more details.
+//
+// You should have received a copy of the GNU Lesser General Public License 
+// along with this library in the file named LICENSE.txt; if not, write to the 
+// Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+// MA 02110-1301 USA
+//
+//===----------------------------------------------------------------------===//
+/// @file hlvm/CodeGen/LLVMEmitter.cpp
+/// @author Reid Spencer <rspencer at x10sys.com>
+/// @date 2006/07/08
+/// @since 0.2.0
+/// @brief Provides the implementation of the LLVM Code Emitter
+//===----------------------------------------------------------------------===//
+
+#include <hlvm/CodeGen/LLVMEmitter.h>
+#include <hlvm/Base/Assert.h>
+
+using namespace llvm;
+
+namespace hlvm {
+
+LLVMEmitter::LLVMEmitter()
+  : TheModule(0), TheFunction(0), TheEntryBlock(0), TheExitBlock(0), 
+    EntryInsertionPoint(0), TheBlock(0), // TheTarget(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)
+{ 
+}
+
+llvm::Module*
+LLVMEmitter::StartModule(const std::string& ID)
+{
+  hlvmAssert(TheModule == 0);
+  return TheModule = new llvm::Module(ID);
+}
+
+llvm::Module*
+LLVMEmitter::FinishModule()
+{
+  hlvmAssert(TheModule != 0);
+  llvm::Module* result = TheModule;
+  TheModule = 0;
+  return result;
+}
+
+void
+LLVMEmitter::StartFunction(Function* F)
+{
+  hlvmAssert(F != 0 && "Null function?");
+  hlvmAssert(F->empty() && "Function already emitted!");
+
+  // Ensure previous state is cleared
+  // operands.clear();
+  // enters.clear();
+  // exits.clear();
+  blocks.clear();
+  breaks.clear();
+  continues.clear();
+  // lvars.clear();
+
+  // Set up for new function
+  TheFunction = F;
+
+  // Instantiate an entry block for the alloca'd variables. This block
+  // is only used for such variables. By placing the alloca'd variables in
+  // the entry block, their allocation is free since the stack pointer 
+  // must be adjusted anyway, all that happens is that it gets adjusted
+  // by a larger amount. 
+  TheBlock = TheEntryBlock = new BasicBlock("entry",F);
+
+  // Instantiate a no-op as an insertion point for the entry point stuff such
+  // as the alloca variables and argument setup. This allows us to fill and
+  // terminate the entry block as usual while still retaining a point for 
+  // insertion in the entry block that retains declaration order.
+  EntryInsertionPoint = 
+    new CastInst(Constant::getNullValue(Type::IntTy),Type::IntTy,
+        "entry_point", TheEntryBlock);
+
+  // Create a new block for the return node, but don't insert it yet.
+  TheExitBlock = new BasicBlock("exit");
+}
+
+void
+LLVMEmitter::FinishFunction()
+{
+  hlvmAssert(blocks.empty());
+  hlvmAssert(breaks.empty());
+  hlvmAssert(continues.empty());
+}
+
+llvm::BasicBlock*
+LLVMEmitter::pushBlock(const std::string& name)
+{
+  TheBlock = new llvm::BasicBlock(name,TheFunction);
+  blocks.push_back(TheBlock);
+  return TheBlock;
+}
+
+llvm::BasicBlock* 
+LLVMEmitter::popBlock()
+{
+  llvm::BasicBlock* result = blocks.back();
+  blocks.pop_back();
+  if (blocks.empty())
+    TheBlock = 0;
+  else
+    TheBlock = blocks.back();
+  return result;
+}
+
+llvm::BasicBlock*
+LLVMEmitter::newBlock(const std::string& name)
+{
+  blocks.pop_back();
+  TheBlock = new llvm::BasicBlock(name,TheFunction);
+  blocks.push_back(TheBlock);
+  return TheBlock;
+}
+
+llvm::Value* 
+LLVMEmitter::ConvertToBoolean(llvm::Value* V) const
+{
+  const llvm::Type* Ty = V->getType();
+  if (Ty == llvm::Type::BoolTy)
+    return V;
+
+  if (Ty->isInteger() || Ty->isFloatingPoint()) {
+    llvm::Constant* CI = llvm::Constant::getNullValue(V->getType());
+    return new llvm::SetCondInst(llvm::Instruction::SetNE, V, CI, "i2b", 
+        TheBlock);
+  } else if (llvm::isa<llvm::GlobalValue>(V)) {
+    // GlobalValues always have non-zero constant address values, so always true
+    return llvm::ConstantBool::get(true);
+  }
+  hlvmAssert(!"Don't know how to convert V into bool");
+  return llvm::ConstantBool::get(true);
+}
+
+Value* 
+LLVMEmitter::Pointer2Value(llvm::Value* V) const
+{
+  if (!llvm::isa<llvm::PointerType>(V->getType()))
+    return V;
+
+ // llvm::GetElementPtrInst* GEP = new llvm::GetElementPtrIns(V,
+  //    llvm::ConstantInt::get(llvm::Type::UIntTy,0),
+   //   llvm::ConstantInt::get(llvm::Type::UIntTy,0),
+    //  "ptr2Value", TheBlock);
+  return new llvm::LoadInst(V,"ptr2Value", TheBlock);
+}
+
+bool
+LLVMEmitter::IsNoopCast(Value* V, const Type* Ty)
+{
+  // check signed to unsigned
+  const Type *VTy = V->getType();
+  if (VTy->isLosslesslyConvertibleTo(Ty)) return true;
+  
+  // Constant int to anything, to work around stuff like: "xor short X, int 1".
+  if (isa<ConstantInt>(V)) return true;
+  
+  return false;
+}
+
+/// CastToType - Cast the specified value to the specified type if it is
+/// not already that type.
+Value *
+LLVMEmitter::CastToType(Value *V, const Type *Ty) 
+{
+  // If they are the same type, no cast needed
+  if (V->getType() == Ty) 
+    return V;
+
+  // If its a constant then we want a constant cast
+  if (Constant *C = dyn_cast<Constant>(V))
+    return ConstantExpr::getCast(C, Ty);
+  
+  // If its a cast instruction and we're casting back to the original type, 
+  // which is bool, then just get the operand of the cast instead of emitting 
+  // duplicate cast instructions. This is just an optimization of a frequently
+  // occurring case.
+  if (CastInst *CI = dyn_cast<CastInst>(V))
+    if (Ty == Type::BoolTy && CI->getOperand(0)->getType() == Type::BoolTy)
+      return CI->getOperand(0);
+
+  // Otherwise, just issue the cast
+  return new CastInst(V, Ty, V->getName(), TheBlock);
+}
+
+Value *
+LLVMEmitter::NoopCastToType(Value *V, const Type *Ty)
+{
+  hlvmAssert(IsNoopCast(V, Ty) && "Invalid Noop Cast!");
+  return CastToType(V, Ty);
+}
+
+void 
+LLVMEmitter::ResolveBreaks(llvm::BasicBlock* exit)
+{
+  for (BranchList::iterator I = breaks.begin(), E = breaks.end(); I != E; ++I) {
+    (*I)->setOperand(0,exit);
+  }
+  breaks.clear();
+}
+
+void 
+LLVMEmitter::ResolveContinues(llvm::BasicBlock* entry)
+{
+  for (BranchList::iterator I = continues.begin(), E = continues.end(); 
+       I != E; ++I) {
+    (*I)->setOperand(0,entry);
+  }
+  continues.clear();
+}
+
+llvm::Type*
+LLVMEmitter::get_hlvm_size()
+{
+  return llvm::Type::ULongTy;
+}
+
+llvm::PointerType*
+LLVMEmitter::get_hlvm_text()
+{
+  if (! hlvm_text) {
+    llvm::OpaqueType* opq = llvm::OpaqueType::get();
+    TheModule->addTypeName("hlvm_text_obj", opq);
+    hlvm_text = llvm::PointerType::get(opq);
+    TheModule->addTypeName("hlvm_text", hlvm_text);
+  }
+  return hlvm_text;
+}
+
+llvm::Function*
+LLVMEmitter::get_hlvm_text_create()
+{
+  if (! hlvm_text_create) {
+    llvm::Type* result = get_hlvm_text();
+    std::vector<const llvm::Type*> arg_types;
+    arg_types.push_back(llvm::PointerType::get(llvm::Type::SByteTy));
+    llvm::FunctionType* FT = llvm::FunctionType::get(result,arg_types,false);
+    TheModule->addTypeName("hlvm_text_create",FT);
+    hlvm_text_create = 
+      new llvm::Function(FT, llvm::GlobalValue::ExternalLinkage, 
+      "hlvm_text_create", TheModule);
+  }
+  return hlvm_text_create;
+}
+
+CallInst*
+LLVMEmitter::call_hlvm_text_create(const ArgList& args, const char* nm)
+{
+  Function* F = get_hlvm_text_create();
+  return new llvm::CallInst(F, args, (nm ? nm : "buffer"), TheBlock);
+}
+
+llvm::Function*
+LLVMEmitter::get_hlvm_text_delete()
+{
+  if (! hlvm_text_delete) {
+    llvm::Type* result = get_hlvm_text();
+    std::vector<const llvm::Type*> arg_types;
+    arg_types.push_back(get_hlvm_text());
+    llvm::FunctionType* FT = llvm::FunctionType::get(result,arg_types,false);
+    TheModule->addTypeName("hlvm_text_delete",FT);
+    hlvm_text_delete = 
+      new llvm::Function(FT, llvm::GlobalValue::ExternalLinkage, 
+      "hlvm_text_delete", TheModule);
+  }
+  return hlvm_text_delete;
+}
+
+CallInst*
+LLVMEmitter::call_hlvm_text_delete(const ArgList& args)
+{
+  Function* F = get_hlvm_text_delete();
+  return new llvm::CallInst(F, args, "hlvm_text_delete", TheBlock);
+}
+
+llvm::Function*
+LLVMEmitter::get_hlvm_text_to_buffer()
+{
+  if (! hlvm_text_to_buffer) {
+    llvm::Type* result = get_hlvm_buffer();
+    std::vector<const llvm::Type*> arg_types;
+    arg_types.push_back(get_hlvm_text());
+    llvm::FunctionType* FT = llvm::FunctionType::get(result,arg_types,false);
+    TheModule->addTypeName("hlvm_text_to_buffer_signature",FT);
+    hlvm_text_to_buffer = 
+      new llvm::Function(FT, llvm::GlobalValue::ExternalLinkage, 
+      "hlvm_text_to_buffer", TheModule);
+  }
+  return hlvm_text_to_buffer;
+}
+
+CallInst*
+LLVMEmitter::call_hlvm_text_to_buffer(const ArgList& args, const char* nm)
+{
+  Function* F = get_hlvm_text_to_buffer();
+  return new llvm::CallInst(F, args, (nm ? nm : "buffer"), TheBlock);
+}
+
+llvm::PointerType*
+LLVMEmitter::get_hlvm_buffer()
+{
+  if (! hlvm_buffer) {
+    llvm::OpaqueType* opq = llvm::OpaqueType::get();
+    TheModule->addTypeName("hlvm_buffer_obj", opq);
+    hlvm_buffer = llvm::PointerType::get(opq);
+    TheModule->addTypeName("hlvm_buffer", hlvm_buffer);
+  }
+  return hlvm_buffer;
+}
+
+llvm::Function*
+LLVMEmitter::get_hlvm_buffer_create()
+{
+  if (! hlvm_buffer_create) {
+    llvm::Type* result = get_hlvm_buffer();
+    std::vector<const llvm::Type*> arg_types;
+    arg_types.push_back(get_hlvm_size());
+    llvm::FunctionType* FT = llvm::FunctionType::get(result,arg_types,false);
+    TheModule->addTypeName("hlvm_buffer_create",FT);
+    hlvm_buffer_create = 
+      new llvm::Function(FT, llvm::GlobalValue::ExternalLinkage, 
+      "hlvm_buffer_create", TheModule);
+  }
+  return hlvm_buffer_create;
+}
+
+CallInst*
+LLVMEmitter::call_hlvm_buffer_create(const ArgList& args, const char* nm)
+{
+  Function* F = get_hlvm_buffer_create();
+  return new llvm::CallInst(F, args, (nm ? nm : "buffer"), TheBlock);
+}
+
+llvm::Function*
+LLVMEmitter::get_hlvm_buffer_delete()
+{
+  if (! hlvm_buffer_delete) {
+    llvm::Type* result = get_hlvm_buffer();
+    std::vector<const llvm::Type*> arg_types;
+    arg_types.push_back(get_hlvm_buffer());
+    llvm::FunctionType* FT = llvm::FunctionType::get(result,arg_types,false);
+    TheModule->addTypeName("hlvm_buffer_delete",FT);
+    hlvm_buffer_delete = 
+      new llvm::Function(FT, llvm::GlobalValue::ExternalLinkage, 
+      "hlvm_buffer_delete", TheModule);
+  }
+  return hlvm_buffer_delete;
+}
+
+CallInst*
+LLVMEmitter::call_hlvm_buffer_delete(const ArgList& args)
+{
+  Function* F = get_hlvm_buffer_delete();
+  return new llvm::CallInst(F, args, "", TheBlock);
+}
+
+llvm::PointerType* 
+LLVMEmitter::get_hlvm_stream()
+{
+  if (! hlvm_stream) {
+    llvm::OpaqueType* opq = llvm::OpaqueType::get();
+    TheModule->addTypeName("hlvm_stream_obj", opq);
+    hlvm_stream= llvm::PointerType::get(opq);
+    TheModule->addTypeName("hlvm_stream", hlvm_stream);
+  }
+  return hlvm_stream;
+}
+
+llvm::Function*
+LLVMEmitter::get_hlvm_stream_open()
+{
+  if (!hlvm_stream_open) {
+    llvm::Type* result = get_hlvm_stream();
+    std::vector<const llvm::Type*> arg_types;
+    arg_types.push_back(llvm::PointerType::get(llvm::Type::SByteTy));
+    llvm::FunctionType* FT = llvm::FunctionType::get(result,arg_types,false);
+    TheModule->addTypeName("hlvm_stream_open_signature",FT);
+    hlvm_stream_open = 
+      new llvm::Function(FT, llvm::GlobalValue::ExternalLinkage, 
+        "hlvm_stream_open", TheModule);
+  }
+  return hlvm_stream_open;
+}
+
+CallInst*
+LLVMEmitter::call_hlvm_stream_open(const ArgList& args, const char* nm)
+{
+  Function* F = get_hlvm_stream_open();
+  return new llvm::CallInst(F, args, (nm ? nm : "stream"), TheBlock);
+}
+
+llvm::Function*
+LLVMEmitter::get_hlvm_stream_read()
+{
+  if (!hlvm_stream_read) {
+    llvm::Type* result = get_hlvm_size();
+    std::vector<const llvm::Type*> arg_types;
+    arg_types.push_back(get_hlvm_stream());
+    arg_types.push_back(get_hlvm_buffer());
+    arg_types.push_back(get_hlvm_size());
+    llvm::FunctionType* FT = llvm::FunctionType::get(result,arg_types,false);
+    TheModule->addTypeName("hlvm_stream_read_signature",FT);
+    hlvm_stream_read = 
+      new llvm::Function(FT, llvm::GlobalValue::ExternalLinkage,
+      "hlvm_stream_read", TheModule);
+  }
+  return hlvm_stream_read;
+}
+
+CallInst*
+LLVMEmitter::call_hlvm_stream_read(const ArgList& args, const char* nm)
+{
+  Function* F = get_hlvm_stream_read();
+  return new llvm::CallInst(F, args, (nm ? nm : "readlen"), TheBlock);
+}
+
+llvm::Function*
+LLVMEmitter::get_hlvm_stream_write_buffer()
+{
+  if (!hlvm_stream_write_buffer) {
+    llvm::Type* result = get_hlvm_size();
+    std::vector<const llvm::Type*> arg_types;
+    arg_types.push_back(get_hlvm_stream());
+    arg_types.push_back(get_hlvm_buffer());
+    llvm::FunctionType* FT = llvm::FunctionType::get(result,arg_types,false);
+    TheModule->addTypeName("hlvm_stream_write_buffer_signature",FT);
+    hlvm_stream_write_buffer = 
+      new llvm::Function(FT, llvm::GlobalValue::ExternalLinkage,
+      "hlvm_stream_write_buffer", TheModule);
+  }
+  return hlvm_stream_write_buffer;
+}
+
+CallInst*
+LLVMEmitter::call_hlvm_stream_write_buffer(const ArgList& args, const char* nm)
+{
+  Function* F = get_hlvm_stream_write_buffer();
+  return new llvm::CallInst(F, args, (nm ? nm : "writelen"), TheBlock);
+}
+
+llvm::Function*
+LLVMEmitter::get_hlvm_stream_write_string()
+{
+  if (!hlvm_stream_write_string) {
+    llvm::Type* result = get_hlvm_size();
+    std::vector<const llvm::Type*> arg_types;
+    arg_types.push_back(get_hlvm_stream());
+    arg_types.push_back(llvm::PointerType::get(llvm::Type::SByteTy));
+    llvm::FunctionType* FT = llvm::FunctionType::get(result,arg_types,false);
+    TheModule->addTypeName("hlvm_stream_write_string_signature",FT);
+    hlvm_stream_write_string = 
+      new llvm::Function(FT, llvm::GlobalValue::ExternalLinkage,
+      "hlvm_stream_write_string", TheModule);
+  }
+  return hlvm_stream_write_string;
+}
+
+CallInst*
+LLVMEmitter::call_hlvm_stream_write_string(const ArgList& args, const char* nm)
+{
+  Function* F = get_hlvm_stream_write_string();
+  return new llvm::CallInst(F, args, (nm ? nm : "writelen"), TheBlock);
+}
+
+llvm::Function*
+LLVMEmitter::get_hlvm_stream_write_text()
+{
+  if (!hlvm_stream_write_text) {
+    llvm::Type* result = get_hlvm_size();
+    std::vector<const llvm::Type*> arg_types;
+    arg_types.push_back(get_hlvm_stream());
+    arg_types.push_back(get_hlvm_text());
+    llvm::FunctionType* FT = llvm::FunctionType::get(result,arg_types,false);
+    TheModule->addTypeName("hlvm_stream_write_text_signature",FT);
+    hlvm_stream_write_text = 
+      new llvm::Function(FT, llvm::GlobalValue::ExternalLinkage,
+      "hlvm_stream_write_text", TheModule);
+  }
+  return hlvm_stream_write_text;
+}
+
+CallInst*
+LLVMEmitter::call_hlvm_stream_write_text(const ArgList& args, const char* nm)
+{
+  Function* F = get_hlvm_stream_write_text();
+  return new llvm::CallInst(F, args, (nm ? nm : "writelen"), TheBlock);
+}
+
+llvm::Function*
+LLVMEmitter::get_hlvm_stream_close()
+{
+  if (!hlvm_stream_close) {
+    llvm::Type* result = llvm::Type::VoidTy;
+    std::vector<const llvm::Type*> arg_types;
+    arg_types.push_back(get_hlvm_stream());
+    llvm::FunctionType* FT = llvm::FunctionType::get(result,arg_types,false);
+    TheModule->addTypeName("hlvm_stream_close_signature",FT);
+    hlvm_stream_close = 
+      new llvm::Function(FT, llvm::GlobalValue::ExternalLinkage,
+      "hlvm_stream_close", TheModule);
+  }
+  return hlvm_stream_close;
+}
+
+CallInst*
+LLVMEmitter::call_hlvm_stream_close(const ArgList& args)
+{
+  Function* F = get_hlvm_stream_close();
+  return new llvm::CallInst(F, args, "", TheBlock);
+}
+
+llvm::FunctionType*
+LLVMEmitter::get_hlvm_program_signature()
+{
+  if (!hlvm_program_signature) {
+    // Get the type of function that all entry points must have
+    std::vector<const llvm::Type*> arg_types;
+    arg_types.push_back(llvm::Type::IntTy);
+    arg_types.push_back(
+      llvm::PointerType::get(llvm::PointerType::get(llvm::Type::SByteTy)));
+    hlvm_program_signature = 
+      llvm::FunctionType::get(llvm::Type::IntTy,arg_types,false);
+    TheModule->addTypeName("hlvm_program_signature",hlvm_program_signature);
+  }
+  return hlvm_program_signature;
+}
+
+}

Added: hlvm/trunk/hlvm/CodeGen/LLVMEmitter.h
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/CodeGen/LLVMEmitter.h?rev=38380&view=auto

==============================================================================
--- hlvm/trunk/hlvm/CodeGen/LLVMEmitter.h (added)
+++ hlvm/trunk/hlvm/CodeGen/LLVMEmitter.h Sat Jul  7 19:02:50 2007
@@ -0,0 +1,512 @@
+//===-- LLVM Code Emitter Interface -----------------------------*- C++ -*-===//
+//
+//                      High Level Virtual Machine (HLVM)
+//
+// Copyright (C) 2006 Reid Spencer. All Rights Reserved.
+//
+// This software is free software; you can redistribute it and/or modify it 
+// under the terms of the GNU Lesser General Public License as published by 
+// the Free Software Foundation; either version 2.1 of the License, or (at 
+// your option) any later version.
+//
+// This software is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for 
+// more details.
+//
+// You should have received a copy of the GNU Lesser General Public License 
+// along with this library in the file named LICENSE.txt; if not, write to the 
+// Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+// MA 02110-1301 USA
+//
+//===----------------------------------------------------------------------===//
+/// @file hlvm/CodeGen/LLVMEmitter.h
+/// @author Reid Spencer <rspencer at reidspencer.com> (original author)
+/// @date 2006/07/09
+/// @since 0.2.0
+/// @brief Declares the interface for emitting LLVM code
+//===----------------------------------------------------------------------===//
+
+#ifndef HLVM_CODEGEN_LLVMEMITTER_H
+#define HLVM_CODEGEN_LLVMEMITTER_H
+
+// Include the LLVM classes that we use
+#include <llvm/Module.h>
+#include <llvm/PassManager.h>
+#include <llvm/BasicBlock.h>
+#include <llvm/Function.h>
+#include <llvm/GlobalVariable.h>
+#include <llvm/Instructions.h>
+#include <llvm/DerivedTypes.h>
+#include <llvm/TypeSymbolTable.h>
+#include <llvm/Constants.h>
+#include <llvm/CallingConv.h>
+#include "llvm/Support/DataTypes.h"
+#include <vector>
+
+namespace hlvm {
+
+/// A simple list of LLVM Modules
+typedef std::vector<llvm::Module*> ModuleList;
+
+/// A List of LLVM Branch Instructions. These are used to record unconditional
+/// branches that need to be fixed up later with LLVMEmitter::ResolveBranches.
+typedef std::vector<llvm::BranchInst*> BranchList;
+
+/// A list of LLVM Blocks, presumably used in a push/pop stack fashion.
+typedef std::vector<llvm::BasicBlock*> BlockStack;
+
+/// A list of LLVM Values, used for argument lists
+typedef std::vector<llvm::Value*> ArgList;
+
+/// 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
+/// a group of methods to take care of the details of emitting LLVM code. The
+/// main purpose for this class is simply to unclutter LLVMGenerator.
+class LLVMEmitter 
+{
+  /// @name Constructors
+  /// @{
+  public:
+    LLVMEmitter();
+
+  /// @}
+  /// @name Function Emission
+  /// @{
+  public:
+
+    // Start a new modules
+    llvm::Module* StartModule(const std::string& ID);
+
+    // Finish the started module
+    llvm::Module* FinishModule();
+
+    /// Start a new function. This sets up the context of the emitter to start
+    /// generating code for function \p F.
+    void StartFunction(llvm::Function* F);
+
+    /// Finish the function previously started. This must be called after a call
+    /// to StartFunction. Mostly this just checks that the generated function is
+    /// sane.
+    void FinishFunction();
+
+    /// Add a type to the module
+    void AddType(const llvm::Type* Ty, const std::string& name)
+    {
+      TheModule->addTypeName(name, Ty);
+    }
+
+    /// Add a Function to the module
+    llvm::Function* NewFunction(
+      const llvm::FunctionType* Ty, 
+      llvm::GlobalValue::LinkageTypes LT,
+      const std::string& name) 
+    { 
+      return new llvm::Function(Ty, LT, name, TheModule); 
+    }
+
+    /// Add a global variable to the module
+    llvm::GlobalVariable* NewGVar(
+      const llvm::Type* Ty, 
+      llvm::GlobalValue::LinkageTypes LT,
+      llvm::Constant* init, 
+      const std::string& name)
+    {
+      return new llvm::GlobalVariable(Ty, false, LT, init, name, TheModule);
+    }
+    /// Add a global constant to the module
+    llvm::GlobalVariable* NewGConst(
+      const llvm::Type* Ty, 
+      llvm::Constant* init, 
+      const std::string& name)
+    {
+      return new llvm::GlobalVariable(Ty, true,
+         llvm::GlobalValue::InternalLinkage, init, name, TheModule);
+    }
+
+    /// Create a new AllocaInst in the entry block with the given name and type.
+    /// The Type must have a fixed/constant size.
+    llvm::AllocaInst* NewAutoVar(const llvm::Type* Ty, const std::string& name)
+    {
+      return new llvm::AllocaInst(Ty, 0, name, EntryInsertionPoint);
+    }
+
+    /// Add the specified basic block to the end of the function.  If
+    /// the previous block falls through into it, add an explicit branch.  Also,
+    /// manage fixups for EH info.
+    void EmitBlock(llvm::BasicBlock *BB);
+    
+    /// Create a new LLVM block with the given \p name and push it onto the
+    /// block stack.
+    llvm::BasicBlock* pushBlock(const std::string& name);
+
+    /// Pop a block off the block stack and return it.
+    llvm::BasicBlock* popBlock();
+
+    /// Replace the top of the block stack with a new block with the given
+    /// \p name
+    llvm::BasicBlock* newBlock(const std::string& name);
+
+  /// @}
+  /// @name Simple Helper Functions
+  /// @{
+  public: 
+    /// Get the current module we're building
+    llvm::Module* getModule() const { return TheModule; }
+
+    /// Get the current function we're building
+    llvm::Function* getFunction() const { return TheFunction; }
+
+    /// Get the current block we are filling
+    llvm::BasicBlock* getBlock() const { return TheBlock; }
+
+    /// Get the name of the current block we're inserting into
+    const std::string& getBlockName() const { 
+      return TheBlock->getName(); 
+    }
+    // Get the terminating instruction of the current block
+    llvm::Instruction* getBlockTerminator() const { 
+      return TheBlock->getTerminator();
+    }
+    // Get the return type of the current function
+    const llvm::Type* getReturnType() const {
+      return TheFunction->getReturnType();
+    }
+
+    /// 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;
+
+    /// Convert the value V into a Boolean value.
+    llvm::Value* ConvertToBoolean(llvm::Value* V) const;
+
+    /// Run through the \p list and set the first operand of each branch
+    /// instruction found there to the \p exit block. This presumes that the
+    /// branch instruction is unconditional.
+    void ResolveBreaks(llvm::BasicBlock* exit);
+    void ResolveContinues(llvm::BasicBlock* entry);
+
+    /// Return true if a cast from V to Ty does not change any bits.
+    static bool IsNoopCast(llvm::Value *V, const llvm::Type *Ty);
+
+    /// Cast the \p V  to \p Ty if it is not already that type.
+    llvm::Value *CastToType(llvm::Value *V, const llvm::Type *Ty);
+
+    /// Insert a cast of \p V to \p Ty if needed.  This checks that
+    /// the cast doesn't change any of the values bits.
+    llvm::Value *NoopCastToType(llvm::Value *V, const llvm::Type *Ty); 
+
+    static void TwoZeroIndices(ArgList& indices) {
+      indices.clear();
+      indices.push_back(llvm::Constant::getNullValue(llvm::Type::UIntTy));
+      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);
+
+  /// @}
+  /// @name Simple Value getters
+  /// @{
+  public:
+    llvm::Constant* getTrue() const { return llvm::ConstantBool::get(true); }
+    llvm::Constant* getFalse() const { return llvm::ConstantBool::get(false); }
+    llvm::Constant* getSZero() const { 
+      return llvm::Constant::getNullValue(llvm::Type::IntTy);
+    }
+    llvm::Constant* getUZero() const { 
+      return llvm::Constant::getNullValue(llvm::Type::UIntTy);
+    }
+    llvm::Constant* getFOne() const { 
+      return llvm::ConstantFP::get(llvm::Type::FloatTy,1.0);
+    }
+    llvm::Constant* getDOne() const { 
+      return llvm::ConstantFP::get(llvm::Type::DoubleTy,1.0);
+    }
+    llvm::Constant* getFPOne(const llvm::Type* Ty) const {
+      return llvm::ConstantFP::get(Ty,1.0);
+    }
+    llvm::Constant* getSOne() const {
+      return llvm::ConstantInt::get(llvm::Type::IntTy,1);
+    }
+    llvm::Constant* getUOne() const {
+      return llvm::ConstantUInt::get(llvm::Type::UIntTy,1);
+    }
+    llvm::Constant* getIOne(const llvm::Type* Ty) const {
+      return llvm::ConstantInt::get(Ty,1);
+    }
+    llvm::Constant* getNullValue(const llvm::Type* Ty) const { 
+      return llvm::Constant::getNullValue(Ty);
+    }
+    llvm::Constant* getAllOnes(const llvm::Type* Ty) const {
+      return llvm::ConstantIntegral::getAllOnesValue(Ty);
+    }
+  /// @}
+  /// @name Simple emitters
+  /// @{
+  public:
+    llvm::SetCondInst* emitNE(llvm::Value* V1, llvm::Value* V2) {
+      return new llvm::SetCondInst(llvm::Instruction::SetNE, 
+        V1, V2, "ne", TheBlock);
+    }
+    llvm::SetCondInst* emitEQ(llvm::Value* V1, llvm::Value* V2) {
+      return new llvm::SetCondInst(llvm::Instruction::SetEQ, 
+        V1,V2,"eq",TheBlock);
+    }
+    llvm::SetCondInst* emitLT(llvm::Value* V1, llvm::Value* V2) {
+      return new llvm::SetCondInst(llvm::Instruction::SetLT, 
+        V1,V2,"lt",TheBlock);
+    }
+    llvm::SetCondInst* emitGT(llvm::Value* V1, llvm::Value* V2) {
+      return new llvm::SetCondInst(llvm::Instruction::SetGT, 
+        V1,V2,"gt",TheBlock);
+    }
+    llvm::SetCondInst* emitLE(llvm::Value* V1, llvm::Value* V2) {
+      return new llvm::SetCondInst(llvm::Instruction::SetLE, 
+        V1,V2,"le",TheBlock);
+    }
+    llvm::SetCondInst* emitGE(llvm::Value* V1, llvm::Value* V2) {
+      return new llvm::SetCondInst(llvm::Instruction::SetGE, 
+        V1,V2,"ge",TheBlock);
+    }
+    llvm::CastInst* emitCast(llvm::Value* V1, const llvm::Type* Ty, 
+                             const std::string& name) {
+      return new llvm::CastInst(V1,Ty,name,TheBlock);
+    }
+    llvm::LoadInst* emitLoad(llvm::Value* V, const std::string& name) const {
+      return  new llvm::LoadInst(V,name,TheBlock);
+    }
+    llvm::StoreInst* emitStore(llvm::Value* from, llvm::Value* to) const {
+      return new llvm::StoreInst(from,to,TheBlock);
+    }
+    llvm::BinaryOperator* emitNeg(llvm::Value* V) const {
+      return llvm::BinaryOperator::createNeg(V,"neg",TheBlock);
+    }
+    llvm::BinaryOperator* emitCmpl(llvm::Value* V) const {
+      return llvm::BinaryOperator::create(llvm::Instruction::Xor,
+        V, getAllOnes(V->getType()), "cmpl", TheBlock);
+    }
+    llvm::BinaryOperator* emitAdd(llvm::Value* V1, llvm::Value* V2) {
+      return llvm::BinaryOperator::create(llvm::Instruction::Add, 
+        V1, V2, "add", TheBlock);
+    }
+    llvm::BinaryOperator* emitSub(llvm::Value* V1, llvm::Value* V2) {
+      return llvm::BinaryOperator::create(llvm::Instruction::Sub, 
+        V1, V2, "sub", TheBlock);
+    }
+    llvm::BinaryOperator* emitMul(llvm::Value* V1, llvm::Value* V2) {
+      return llvm::BinaryOperator::create(llvm::Instruction::Mul, 
+        V1, V2, "mul", TheBlock);
+    }
+    llvm::BinaryOperator* emitDiv(llvm::Value* V1, llvm::Value* V2) const {
+      return llvm::BinaryOperator::create(llvm::Instruction::Div, 
+        V1, V2, "div", TheBlock);
+    }
+    llvm::BinaryOperator* emitMod(llvm::Value* V1, llvm::Value* V2) const {
+      return llvm::BinaryOperator::create(llvm::Instruction::Rem, 
+        V1, V2, "mod", TheBlock);
+    }
+    llvm::BinaryOperator* emitBAnd(llvm::Value*V1, llvm::Value* V2) const {
+      return llvm::BinaryOperator::create(llvm::Instruction::And, 
+        V1, V2, "band", TheBlock);
+    }
+    llvm::BinaryOperator* emitBOr(llvm::Value*V1, llvm::Value* V2) const {
+      return llvm::BinaryOperator::create(llvm::Instruction::Or, 
+        V1, V2, "bor", TheBlock);
+    }
+    llvm::BinaryOperator* emitBXor(llvm::Value*V1, llvm::Value* V2) const {
+      return llvm::BinaryOperator::create(llvm::Instruction::Xor, 
+        V1, V2, "bxor", TheBlock);
+    }
+    llvm::BinaryOperator* emitBNor(llvm::Value* V1, llvm::Value* V2) const {
+      llvm::BinaryOperator* bor = llvm::BinaryOperator::create(
+        llvm::Instruction::Or, V1, V2, "bnor", TheBlock);
+      return llvm::BinaryOperator::createNot(bor,"bnor",TheBlock);
+    }
+    llvm::BinaryOperator* emitNot(llvm::Value* V1) const {
+      return llvm::BinaryOperator::createNot(
+          ConvertToBoolean(V1),"not",TheBlock);
+    }
+    llvm::BinaryOperator* emitAnd(llvm::Value* V1, llvm::Value* V2) const {
+      return llvm::BinaryOperator::create(llvm::Instruction::And, 
+        ConvertToBoolean(V1), ConvertToBoolean(V2), "and", TheBlock);
+    }
+    llvm::BinaryOperator* emitOr(llvm::Value* V1, llvm::Value* V2) const {
+      return llvm::BinaryOperator::create(llvm::Instruction::Or, 
+        ConvertToBoolean(V1), ConvertToBoolean(V2), "or", TheBlock);
+    }
+    llvm::BinaryOperator* emitXor(llvm::Value*V1, llvm::Value* V2) const {
+      return llvm::BinaryOperator::create(llvm::Instruction::Xor, 
+        ConvertToBoolean(V1), ConvertToBoolean(V2), "xor", TheBlock);
+    }
+    llvm::BinaryOperator* emitNor(llvm::Value* V1, llvm::Value* V2) const {
+      llvm::BinaryOperator* op = llvm::BinaryOperator::create(
+        llvm::Instruction::Or, ConvertToBoolean(V1), ConvertToBoolean(V2), 
+        "nor", TheBlock);
+      return llvm::BinaryOperator::createNot(op,"nor",TheBlock);
+    }
+    llvm::SelectInst* emitSelect(llvm::Value* V1, llvm::Value* V2, 
+      llvm::Value* V3, const std::string& name) {
+      return new llvm::SelectInst(V1,V2,V3,name,TheBlock);
+    }
+    llvm::BranchInst* emitBranch(llvm::BasicBlock* blk) {
+      return new llvm::BranchInst(blk,TheBlock);
+    }
+    llvm::BranchInst* emitBreak() {
+      llvm::BranchInst* brnch = new llvm::BranchInst(TheBlock,TheBlock);
+      breaks.push_back(brnch);
+      return brnch;
+    }
+    llvm::BranchInst* emitContinue() {
+      llvm::BranchInst* brnch = new llvm::BranchInst(TheBlock,TheBlock);
+      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::GetElementPtrInst* emitGEP(llvm::Value* V, const ArgList& indices) {
+      return new llvm::GetElementPtrInst(V,indices,"",TheBlock);
+    }
+  /// @}
+  /// @name Other miscellaneous functions
+  /// @{
+  public:
+
+    /// Return the unique ID of the specified basic
+    /// block for uses that take the address of it.
+    llvm::Constant *getIndirectGotoBlockNumber(llvm::BasicBlock *BB);
+    
+    /// Get (and potentially lazily create) the indirect
+    /// 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.
+    void EmitBranchInternal(llvm::BasicBlock *Dest, bool IsExceptionEdge);
+
+    /// Add the specified unconditional branch to the fixup list for the 
+    /// outermost exception scope, merging it if there is already a fixup that 
+    /// works.
+    void AddBranchFixup(llvm::BranchInst *BI, bool isExceptionEdge);
+
+  /// @}
+  /// @name Data Members
+  /// @{
+  private:
+    BlockStack blocks;              ///< The stack of nested blocks 
+    BranchList breaks;              ///< The list of breaks to fix up later
+    BranchList continues;           ///< The list of continues to fix up later
+    llvm::Module *TheModule;        ///< The module that we are compiling into.
+    llvm::Function * TheFunction;   ///< The function we're constructing
+    llvm::BasicBlock* TheEntryBlock;///< The function's entry block
+    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
+    llvm::Function*     hlvm_text_create;   ///< Create a new text object
+    llvm::Function*     hlvm_text_delete;   ///< Delete a text object
+    llvm::Function*     hlvm_text_to_buffer;///< Convert text to a buffer
+    llvm::PointerType*  hlvm_buffer;        ///< Pointer To octet
+    llvm::Function*     hlvm_buffer_create; ///< Create a new buffer object
+    llvm::Function*     hlvm_buffer_delete; ///< Delete a buffer
+    llvm::PointerType*  hlvm_stream;        ///< Pointer to stream type
+    llvm::Function*     hlvm_stream_open;   ///< Function for stream_open
+    llvm::Function*     hlvm_stream_read;   ///< Function for stream_read
+    llvm::Function*     hlvm_stream_write_buffer; ///< Write buffer to stream
+    llvm::Function*     hlvm_stream_write_text;   ///< Write text to stream
+    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
+  /// @}
+};
+
+} // end hlvm namespace
+
+#endif

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

==============================================================================
--- hlvm/trunk/hlvm/CodeGen/LLVMGenerator.cpp (original)
+++ hlvm/trunk/hlvm/CodeGen/LLVMGenerator.cpp Sat Jul  7 19:02:50 2007
@@ -42,14 +42,7 @@
 #include <hlvm/AST/Constants.h>
 #include <hlvm/Base/Assert.h>
 #include <hlvm/Pass/Pass.h>
-#include <llvm/Module.h>
-#include <llvm/PassManager.h>
-#include <llvm/BasicBlock.h>
-#include <llvm/Instructions.h>
-#include <llvm/DerivedTypes.h>
-#include <llvm/TypeSymbolTable.h>
-#include <llvm/Constants.h>
-#include <llvm/CallingConv.h>
+#include <hlvm/CodeGen/LLVMEmitter.h>
 #include <llvm/Linker.h>
 #include <llvm/Analysis/LoadValueNumbering.h>
 #include <llvm/Analysis/Verifier.h>
@@ -78,9 +71,7 @@
 
 class LLVMGeneratorPass : public hlvm::Pass
 {
-  typedef std::vector<llvm::Module*> ModuleList;
-  typedef std::vector<llvm::BranchInst*> BranchList;
-  typedef std::vector<llvm::BasicBlock*> BlockStack;
+  LLVMEmitter em;
   typedef std::map<const hlvm::Operator*,llvm::Value*> OperandMap;
   typedef std::map<const hlvm::Block*,llvm::BasicBlock*> BlockMap;
   typedef std::map<const hlvm::Operator*,llvm::BasicBlock*> LoopMap;
@@ -90,9 +81,6 @@
   typedef std::map<const hlvm::Constant*,llvm::Constant*> ConstantMap;
   typedef std::map<const hlvm::Function*,llvm::Function*> FunctionMap;
   ModuleList modules;           ///< The list of modules we construct
-  llvm::Module*     lmod;       ///< The current module we're generation 
-  llvm::Function*   lfunc;      ///< The current LLVM function we're generating 
-  llvm::BasicBlock* lblk;       ///< The current LLVM block we're generating
   OperandMap operands;          ///< The current list of instruction operands
   BlockMap enters;              ///< Map of Block to entry BasicBlock
   BlockMap exits;               ///< Map of Block to exit BasicBlock
@@ -110,43 +98,19 @@
   const Block* block;           ///< The current Block we're traversing
   std::vector<llvm::Function*> progs; ///< The list of programs to emit
 
-  /// Interfaces to the HLVM Runtime Library
-  llvm::PointerType*  hlvm_text;          ///< Opaque type for text objects
-  llvm::Function*     hlvm_text_create;   ///< Create a new text object
-  llvm::Function*     hlvm_text_delete;   ///< Delete a text object
-  llvm::Function*     hlvm_text_to_buffer;///< Convert text to a buffer
-  llvm::PointerType*  hlvm_buffer;        ///< Pointer To octet
-  llvm::Function*     hlvm_buffer_create; ///< Create a new buffer object
-  llvm::Function*     hlvm_buffer_delete; ///< Delete a buffer
-  llvm::PointerType*  hlvm_stream;        ///< Pointer to stream type
-  llvm::Function*     hlvm_stream_open;   ///< Function for stream_open
-  llvm::Function*     hlvm_stream_read;   ///< Function for stream_read
-  llvm::Function*     hlvm_stream_write_buffer; ///< Write buffer to stream
-  llvm::Function*     hlvm_stream_write_text;   ///< Write text to stream
-  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
-
   public:
     LLVMGeneratorPass(const AST* tree)
-      : Pass(0,Pass::PreAndPostOrderTraversal),
-      modules(), lmod(0), lfunc(0), lblk(0), operands(), blocks(), breaks(), 
+      : Pass(0,Pass::PreAndPostOrderTraversal), em(),
+      modules(), operands(), blocks(), breaks(), 
       continues(),
       gvars(), lvars(), ltypes(), consts(), funcs(),
-      ast(tree),   bundle(0), function(0), block(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)
+      ast(tree), bundle(0), function(0), block(0)
       { }
     ~LLVMGeneratorPass() { }
 
   /// Conversion functions
   const llvm::Type* getType(const hlvm::Type* ty);
+  inline const llvm::Type* getFirstClassType(const hlvm::Type* ty);
   llvm::Constant* getConstant(const hlvm::Constant* C);
   llvm::Value* getVariable(const hlvm::Variable* V);
   llvm::Function* getFunction(const hlvm::Function* F);
@@ -176,25 +140,6 @@
     llvm::BasicBlock* to, llvm::BasicBlock* from);
 
   inline void startNewFunction(llvm::Function* f);
-  void resolveBranches(BranchList& list, llvm::BasicBlock* exit);
-
-  /// Accessors for HLVM Runtime Library things
-  inline llvm::Type*         get_hlvm_size();
-  inline llvm::PointerType*  get_hlvm_text();
-  inline llvm::Function*     get_hlvm_text_create();
-  inline llvm::Function*     get_hlvm_text_delete();
-  inline llvm::Function*     get_hlvm_text_to_buffer();
-  inline llvm::PointerType*  get_hlvm_buffer();
-  inline llvm::Function*     get_hlvm_buffer_create();
-  inline llvm::Function*     get_hlvm_buffer_delete();
-  inline llvm::PointerType*  get_hlvm_stream();
-  inline llvm::Function*     get_hlvm_stream_open();
-  inline llvm::Function*     get_hlvm_stream_read();
-  inline llvm::Function*     get_hlvm_stream_write_buffer();
-  inline llvm::Function*     get_hlvm_stream_write_text();
-  inline llvm::Function*     get_hlvm_stream_write_string();
-  inline llvm::Function*     get_hlvm_stream_close();
-  inline llvm::FunctionType* get_hlvm_program_signature();
 
   /// Generator
   template <class NodeClass>
@@ -209,245 +154,6 @@
   inline llvm::Module* linkModules();
 };
 
-llvm::Type*
-LLVMGeneratorPass::get_hlvm_size()
-{
-  return llvm::Type::ULongTy;
-}
-
-llvm::PointerType*
-LLVMGeneratorPass::get_hlvm_text()
-{
-  if (! hlvm_text) {
-    llvm::OpaqueType* opq = llvm::OpaqueType::get();
-    lmod->addTypeName("hlvm_text_obj", opq);
-    hlvm_text = llvm::PointerType::get(opq);
-    lmod->addTypeName("hlvm_text", hlvm_text);
-  }
-  return hlvm_text;
-}
-
-llvm::Function*
-LLVMGeneratorPass::get_hlvm_text_create()
-{
-  if (! hlvm_text_create) {
-    llvm::Type* result = get_hlvm_text();
-    std::vector<const llvm::Type*> arg_types;
-    arg_types.push_back(llvm::PointerType::get(llvm::Type::SByteTy));
-    llvm::FunctionType* FT = llvm::FunctionType::get(result,arg_types,false);
-    lmod->addTypeName("hlvm_text_create",FT);
-    hlvm_text_create = 
-      new llvm::Function(FT, llvm::GlobalValue::ExternalLinkage, 
-      "hlvm_text_create", lmod);
-  }
-  return hlvm_text_create;
-}
-
-llvm::Function*
-LLVMGeneratorPass::get_hlvm_text_delete()
-{
-  if (! hlvm_text_delete) {
-    llvm::Type* result = get_hlvm_text();
-    std::vector<const llvm::Type*> arg_types;
-    arg_types.push_back(get_hlvm_text());
-    llvm::FunctionType* FT = llvm::FunctionType::get(result,arg_types,false);
-    lmod->addTypeName("hlvm_text_delete",FT);
-    hlvm_text_delete = 
-      new llvm::Function(FT, llvm::GlobalValue::ExternalLinkage, 
-      "hlvm_text_delete", lmod);
-  }
-  return hlvm_text_delete;
-}
-
-llvm::Function*
-LLVMGeneratorPass::get_hlvm_text_to_buffer()
-{
-  if (! hlvm_text_to_buffer) {
-    llvm::Type* result = get_hlvm_buffer();
-    std::vector<const llvm::Type*> arg_types;
-    arg_types.push_back(get_hlvm_text());
-    llvm::FunctionType* FT = llvm::FunctionType::get(result,arg_types,false);
-    lmod->addTypeName("hlvm_text_to_buffer_signature",FT);
-    hlvm_text_to_buffer = 
-      new llvm::Function(FT, llvm::GlobalValue::ExternalLinkage, 
-      "hlvm_text_to_buffer", lmod);
-  }
-  return hlvm_text_to_buffer;
-}
-
-llvm::PointerType*
-LLVMGeneratorPass::get_hlvm_buffer()
-{
-  if (! hlvm_buffer) {
-    llvm::OpaqueType* opq = llvm::OpaqueType::get();
-    lmod->addTypeName("hlvm_buffer_obj", opq);
-    hlvm_buffer = llvm::PointerType::get(opq);
-    lmod->addTypeName("hlvm_buffer", hlvm_buffer);
-  }
-  return hlvm_buffer;
-}
-
-llvm::Function*
-LLVMGeneratorPass::get_hlvm_buffer_create()
-{
-  if (! hlvm_buffer_create) {
-    llvm::Type* result = get_hlvm_buffer();
-    std::vector<const llvm::Type*> arg_types;
-    arg_types.push_back(get_hlvm_size());
-    llvm::FunctionType* FT = llvm::FunctionType::get(result,arg_types,false);
-    lmod->addTypeName("hlvm_buffer_create",FT);
-    hlvm_buffer_create = 
-      new llvm::Function(FT, llvm::GlobalValue::ExternalLinkage, 
-      "hlvm_buffer_create", lmod);
-  }
-  return hlvm_buffer_create;
-}
-
-llvm::Function*
-LLVMGeneratorPass::get_hlvm_buffer_delete()
-{
-  if (! hlvm_buffer_delete) {
-    llvm::Type* result = get_hlvm_buffer();
-    std::vector<const llvm::Type*> arg_types;
-    arg_types.push_back(get_hlvm_buffer());
-    llvm::FunctionType* FT = llvm::FunctionType::get(result,arg_types,false);
-    lmod->addTypeName("hlvm_buffer_delete",FT);
-    hlvm_buffer_delete = 
-      new llvm::Function(FT, llvm::GlobalValue::ExternalLinkage, 
-      "hlvm_buffer_delete", lmod);
-  }
-  return hlvm_buffer_delete;
-}
-
-llvm::PointerType* 
-LLVMGeneratorPass::get_hlvm_stream()
-{
-  if (! hlvm_stream) {
-    llvm::OpaqueType* opq = llvm::OpaqueType::get();
-    lmod->addTypeName("hlvm_stream_obj", opq);
-    hlvm_stream= llvm::PointerType::get(opq);
-    lmod->addTypeName("hlvm_stream", hlvm_stream);
-  }
-  return hlvm_stream;
-}
-
-llvm::Function*
-LLVMGeneratorPass::get_hlvm_stream_open()
-{
-  if (!hlvm_stream_open) {
-    llvm::Type* result = get_hlvm_stream();
-    std::vector<const llvm::Type*> arg_types;
-    arg_types.push_back(llvm::PointerType::get(llvm::Type::SByteTy));
-    llvm::FunctionType* FT = llvm::FunctionType::get(result,arg_types,false);
-    lmod->addTypeName("hlvm_stream_open_signature",FT);
-    hlvm_stream_open = 
-      new llvm::Function(FT, llvm::GlobalValue::ExternalLinkage, 
-        "hlvm_stream_open", lmod);
-  }
-  return hlvm_stream_open;
-}
-
-llvm::Function*
-LLVMGeneratorPass::get_hlvm_stream_read()
-{
-  if (!hlvm_stream_read) {
-    llvm::Type* result = get_hlvm_size();
-    std::vector<const llvm::Type*> arg_types;
-    arg_types.push_back(get_hlvm_stream());
-    arg_types.push_back(get_hlvm_buffer());
-    arg_types.push_back(get_hlvm_size());
-    llvm::FunctionType* FT = llvm::FunctionType::get(result,arg_types,false);
-    lmod->addTypeName("hlvm_stream_read_signature",FT);
-    hlvm_stream_read = 
-      new llvm::Function(FT, llvm::GlobalValue::ExternalLinkage,
-      "hlvm_stream_read", lmod);
-  }
-  return hlvm_stream_read;
-}
-
-llvm::Function*
-LLVMGeneratorPass::get_hlvm_stream_write_buffer()
-{
-  if (!hlvm_stream_write_buffer) {
-    llvm::Type* result = get_hlvm_size();
-    std::vector<const llvm::Type*> arg_types;
-    arg_types.push_back(get_hlvm_stream());
-    arg_types.push_back(get_hlvm_buffer());
-    llvm::FunctionType* FT = llvm::FunctionType::get(result,arg_types,false);
-    lmod->addTypeName("hlvm_stream_write_buffer_signature",FT);
-    hlvm_stream_write_buffer = 
-      new llvm::Function(FT, llvm::GlobalValue::ExternalLinkage,
-      "hlvm_stream_write_buffer", lmod);
-  }
-  return hlvm_stream_write_buffer;
-}
-
-llvm::Function*
-LLVMGeneratorPass::get_hlvm_stream_write_string()
-{
-  if (!hlvm_stream_write_string) {
-    llvm::Type* result = get_hlvm_size();
-    std::vector<const llvm::Type*> arg_types;
-    arg_types.push_back(get_hlvm_stream());
-    arg_types.push_back(llvm::PointerType::get(llvm::Type::SByteTy));
-    llvm::FunctionType* FT = llvm::FunctionType::get(result,arg_types,false);
-    lmod->addTypeName("hlvm_stream_write_string_signature",FT);
-    hlvm_stream_write_string = 
-      new llvm::Function(FT, llvm::GlobalValue::ExternalLinkage,
-      "hlvm_stream_write_string", lmod);
-  }
-  return hlvm_stream_write_string;
-}
-
-llvm::Function*
-LLVMGeneratorPass::get_hlvm_stream_write_text()
-{
-  if (!hlvm_stream_write_text) {
-    llvm::Type* result = get_hlvm_size();
-    std::vector<const llvm::Type*> arg_types;
-    arg_types.push_back(get_hlvm_stream());
-    arg_types.push_back(get_hlvm_text());
-    llvm::FunctionType* FT = llvm::FunctionType::get(result,arg_types,false);
-    lmod->addTypeName("hlvm_stream_write_text_signature",FT);
-    hlvm_stream_write_text = 
-      new llvm::Function(FT, llvm::GlobalValue::ExternalLinkage,
-      "hlvm_stream_write_text", lmod);
-  }
-  return hlvm_stream_write_text;
-}
-
-llvm::Function*
-LLVMGeneratorPass::get_hlvm_stream_close()
-{
-  if (!hlvm_stream_close) {
-    llvm::Type* result = llvm::Type::VoidTy;
-    std::vector<const llvm::Type*> arg_types;
-    arg_types.push_back(get_hlvm_stream());
-    llvm::FunctionType* FT = llvm::FunctionType::get(result,arg_types,false);
-    lmod->addTypeName("hlvm_stream_close_signature",FT);
-    hlvm_stream_close = 
-      new llvm::Function(FT, llvm::GlobalValue::ExternalLinkage,
-      "hlvm_stream_close", lmod);
-  }
-  return hlvm_stream_close;
-}
-
-llvm::FunctionType*
-LLVMGeneratorPass::get_hlvm_program_signature()
-{
-  if (!hlvm_program_signature) {
-    // Get the type of function that all entry points must have
-    std::vector<const llvm::Type*> arg_types;
-    arg_types.push_back(llvm::Type::IntTy);
-    arg_types.push_back(
-      llvm::PointerType::get(llvm::PointerType::get(llvm::Type::SByteTy)));
-    hlvm_program_signature = 
-      llvm::FunctionType::get(llvm::Type::IntTy,arg_types,false);
-    lmod->addTypeName("hlvm_program_signature",hlvm_program_signature);
-  }
-  return hlvm_program_signature;
-}
-
 std::string
 LLVMGeneratorPass::getLinkageName(const Linkable* lk)
 {
@@ -531,13 +237,13 @@
       break;
     }
     case TextTypeID:
-      result = get_hlvm_text();
+      result = em.get_hlvm_text();
       break;
     case StreamTypeID: 
-      result = get_hlvm_stream();
+      result = em.get_hlvm_stream();
       break;
     case BufferTypeID: 
-      result = get_hlvm_buffer();
+      result = em.get_hlvm_buffer();
       break;
     case PointerTypeID: 
     {
@@ -549,7 +255,7 @@
       // If the element type is opaque then we need to add a type name for this
       // pointer type because all opaques are unique unless named similarly.
       if (llvm::isa<llvm::OpaqueType>(lElemType))
-        lmod->addTypeName(ty->getName(), result);
+        em.AddType(result, ty->getName());
       break;
     }
     case VectorTypeID: {
@@ -582,9 +288,9 @@
       const SignatureType* st = llvm::cast<SignatureType>(ty);
       for (SignatureType::const_iterator I = st->begin(), E = st->end(); 
            I != E; ++I)
-        params.push_back(getType((*I)->getType()));
+        params.push_back(getFirstClassType((*I)->getType()));
       result = llvm::FunctionType::get(
-        getType(st->getResultType()),params,st->isVarArgs());
+        getFirstClassType(st->getResultType()),params,st->isVarArgs());
       break;
     }
     case OpaqueTypeID: {
@@ -600,6 +306,15 @@
   return result;
 }
 
+const llvm::Type*
+LLVMGeneratorPass::getFirstClassType(const hlvm::Type* ty)
+{
+  const llvm::Type* Ty = getType(ty);
+  if (!Ty->isFirstClassType())
+    return llvm::PointerType::get(Ty);
+  return Ty;
+}
+
 llvm::Constant*
 LLVMGeneratorPass::getConstant(const hlvm::Constant* C)
 {
@@ -648,8 +363,69 @@
     {
       const ConstantString* CT = llvm::cast<ConstantString>(C);
       llvm::Constant* CA = llvm::ConstantArray::get(CT->getValue(), true);
-      result = new llvm::GlobalVariable(CA->getType(), true, 
-          llvm::GlobalValue::InternalLinkage, CA, C->getName(), lmod);
+      llvm::GlobalVariable* GV  = em.NewGConst(CA->getType(), CA, C->getName());
+      std::vector<llvm::Constant*> indices;
+      indices.push_back(llvm::Constant::getNullValue(llvm::Type::UIntTy));
+      indices.push_back(llvm::Constant::getNullValue(llvm::Type::UIntTy));
+      result = llvm::ConstantExpr::getGetElementPtr(GV,indices);
+      break;
+    }
+    case ConstantPointerID:
+    {
+      const ConstantPointer* hCT = llvm::cast<ConstantPointer>(C);
+      const Constant* hC = hCT->getValue();
+      const llvm::Type* Ty = getType(hC->getType());
+      llvm::Constant* Init = getConstant(hC);
+      result = em.NewGConst(Ty,Init, hCT->getName());
+      break;
+    }
+    case ConstantArrayID:
+    {
+      const ConstantArray* hCA = llvm::cast<ConstantArray>(C);
+      const llvm::ArrayType* Ty = 
+        llvm::cast<llvm::ArrayType>(getType(hCA->getType()));
+      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);
+      break;
+    }
+    case ConstantVectorID:
+    {
+      const ConstantVector* hCA = llvm::cast<ConstantVector>(C);
+      const llvm::ArrayType* Ty =
+        llvm::cast<llvm::ArrayType>(getType(hCA->getType()));
+      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);
+      break;
+    }
+    case ConstantStructureID:
+    {
+      const ConstantStructure* hCS = llvm::cast<ConstantStructure>(C);
+      const llvm::StructType* Ty = 
+        llvm::cast<llvm::StructType>(getType(hCS->getType()));
+      std::vector<llvm::Constant*> fields;
+      for (ConstantStructure::const_iterator I = hCS->begin(), E = hCS->end(); 
+           I != E; ++I)
+        fields.push_back(getConstant(*I));
+      result = llvm::ConstantStruct::get(Ty,fields);
+      break;
+    }
+    case ConstantContinuationID:
+    {
+      const ConstantContinuation* hCC = llvm::cast<ConstantContinuation>(C);
+      const llvm::StructType* Ty = 
+        llvm::cast<llvm::StructType>(getType(hCC->getType()));
+      std::vector<llvm::Constant*> fields;
+      for (ConstantStructure::const_iterator I = hCC->begin(), E = hCC->end(); 
+           I != E; ++I)
+        fields.push_back(getConstant(*I));
+      // FIXME: Need to add extra fields required for Continuation
+      result = llvm::ConstantStruct::get(Ty,fields);
       break;
     }
     default:
@@ -680,13 +456,12 @@
     Initializer = getConstant(V->getInitializer());
   else
     Initializer = llvm::Constant::getNullValue(getType(V->getType()));
-  llvm::Value* gv = new llvm::GlobalVariable(
+
+  llvm::Value* gv = em.NewGVar(
     /*Ty=*/ getType(V->getType()),
-    /*isConstant=*/ false,
     /*Linkage=*/ getLinkageTypes(V->getLinkageKind()), 
     /*Initializer=*/ Initializer,
-    /*Name=*/ getLinkageName(V),
-    /*Parent=*/ lmod
+    /*Name=*/ getLinkageName(V)
   );
   gvars[V] = gv;
   return gv;
@@ -703,14 +478,11 @@
   if (I != funcs.end())
     return I->second;
 
-  llvm::Function* func = new llvm::Function(
+  return funcs[F] = em.NewFunction(
     /*Type=*/ llvm::cast<llvm::FunctionType>(getType(F->getType())),
     /*Linkage=*/ getLinkageTypes(F->getLinkageKind()), 
-    /*Name=*/ getLinkageName(F),
-    /*Parent=*/ lmod
+    /*Name=*/ getLinkageName(F)
   );
-  funcs[F] = func;
-  return func;
 }
 
 llvm::GlobalValue::LinkageTypes
@@ -766,14 +538,14 @@
     return V;
 
   if (Ty->isInteger() || Ty->isFloatingPoint()) {
-    llvm::Constant* CI = llvm::Constant::getNullValue(V->getType());
-    return new llvm::SetCondInst(llvm::Instruction::SetNE, V, CI, "i2b", lblk);
+    llvm::Constant* C = llvm::Constant::getNullValue(V->getType());
+    return em.emitNE(V,C);
   } else if (llvm::isa<llvm::GlobalValue>(V)) {
     // GlobalValues always have non-zero constant address values, so always true
-    return llvm::ConstantBool::get(true);
+    return em.getTrue(); 
   }
   hlvmAssert(!"Don't know how to convert V into bool");
-  return llvm::ConstantBool::get(true);
+  return em.getTrue();
 }
 
 llvm::Value* 
@@ -782,12 +554,7 @@
   if (!llvm::isa<llvm::PointerType>(V->getType()))
     return V;
 
- // llvm::GetElementPtrInst* GEP = new llvm::GetElementPtrIns(V,
-  //    llvm::ConstantInt::get(llvm::Type::UIntTy,0),
-   //   llvm::ConstantInt::get(llvm::Type::UIntTy,0),
-    //  "ptr2Value", lblk);
-  llvm::LoadInst* Load = new llvm::LoadInst(V,"ptr2Value",lblk);
-  return Load;
+  return em.emitLoad(V,"ptr2Value");
 }
 
 void 
@@ -834,7 +601,7 @@
     result = operand;
   } else {
     hlvmAssert(operand && "No operand for operator?");
-    entry_block = exit_block = new llvm::BasicBlock(name,lfunc); 
+    entry_block = exit_block = new llvm::BasicBlock(name,em.getFunction()); 
     llvm::Value* V = operand;
     hlvmAssert(V && "No value for operand?");
     if (llvm::Instruction* ins = llvm::dyn_cast<llvm::Instruction>(V)) {
@@ -867,48 +634,14 @@
   return result;
 }
 
-llvm::BasicBlock*
-LLVMGeneratorPass::pushBlock(const std::string& name)
-{
-  lblk = new llvm::BasicBlock(name,lfunc);
-  blocks.push_back(lblk);
-  return lblk;
-}
-
-llvm::BasicBlock* 
-LLVMGeneratorPass::popBlock(llvm::BasicBlock* curBlock)
-{
-  llvm::BasicBlock* result = blocks.back();
-  blocks.pop_back();
-  if (blocks.empty())
-    lblk = 0;
-  else
-    lblk = blocks.back();
-  return result;
-}
-
-llvm::BasicBlock*
-LLVMGeneratorPass::newBlock(const std::string& name)
-{
-  blocks.pop_back();
-  lblk = new llvm::BasicBlock(name,lfunc);
-  blocks.push_back(lblk);
-  return lblk;
-}
-
 llvm::AllocaInst* 
 LLVMGeneratorPass::getOperatorResult(Operator* op, const std::string& name)
 {
   llvm::AllocaInst* result = 0;
   if (!llvm::isa<Block>(op->getParent())) {
     const llvm::Type* Ty = getType(op->getType());
-    result = new llvm::AllocaInst(
-      /*Ty=*/ Ty,
-      /*ArraySize=*/ llvm::ConstantUInt::get(llvm::Type::UIntTy,1),
-      /*Name=*/ name + "_var",
-      /*InsertAtEnd=*/ &lfunc->front()
-    ); 
-    new llvm::StoreInst(llvm::Constant::getNullValue(Ty),result,lblk);
+    result = em.NewAutoVar(Ty, name + "_var");
+    em.emitStore(em.getNullValue(Ty),result);
   }
   return result;
 }
@@ -916,11 +649,11 @@
 llvm::Value* 
 LLVMGeneratorPass::getBlockResult(Block* B)
 {
-  if (B->getResult() && !lblk->getTerminator()) {
+  if (B->getResult() && !em.getBlockTerminator()) {
     llvm::Value* result = operands[B];
     if (llvm::isa<llvm::LoadInst>(result))
       result = llvm::cast<llvm::LoadInst>(result)->getOperand(0);
-    result = new llvm::LoadInst(result,lblk->getName()+"_result",lblk);
+    result = em.emitLoad(result,em.getBlockName()+"_result");
     pushOperand(result,B);
     return result;
   }
@@ -938,54 +671,29 @@
 void
 LLVMGeneratorPass::startNewFunction(llvm::Function* F)
 {
+  em.StartFunction(F);
   // Clear the function related variables
-  lblk = 0;
   operands.clear();
   enters.clear();
   exits.clear();
   blocks.clear();
-  breaks.clear();
-  continues.clear();
   lvars.clear();
-  // Instantiate an entry block for the alloca'd variables. This block
-  // is only used for such variables. By placing the alloca'd variables in
-  // the entry block, their allocation is free since the stack pointer 
-  // must be adjusted anyway, all that happens is that it gets adjusted
-  // by a larger amount. This block is not entered onto the block stack as it
-  // has no use but for the alloca'd variables. It is terminated when
-  // the function exits
-  new llvm::BasicBlock("entry",F);
-}
-
-void 
-LLVMGeneratorPass::resolveBranches(BranchList& list, llvm::BasicBlock* exit)
-{
-  for (BranchList::iterator I = list.begin(), E = list.end(); I != E; ++I) {
-    (*I)->setOperand(0,exit);
-  }
-  list.clear();
 }
 
 template<> void
 LLVMGeneratorPass::gen(AutoVarOp* av)
 {
-  assert(lblk  != 0 && "Not in block context");
   // Emit an automatic variable. Note that this is inserted into the entry 
   // block, not the current block, for efficiency. This makes automatic 
   // variables zero cost as well as safeguarding against stack growth if the
   // alloca is in a block that is in a loop.
   const llvm::Type* elemType = getType(av->getType());
-  llvm::Value* alloca = new llvm::AllocaInst(
-    /*Ty=*/ elemType,
-    /*ArraySize=*/ llvm::ConstantUInt::get(llvm::Type::UIntTy,1),
-    /*Name=*/ av->getName(),
-    /*InsertAtEnd=*/ &lfunc->front()
-  );
+  llvm::Value* alloca = em.NewAutoVar(elemType,av->getName()); 
   llvm::Constant* C = 0;
   if (av->hasInitializer())
     C = getConstant(av->getInitializer());
   else
-    C = llvm::Constant::getNullValue(elemType);
+    C = em.getNullValue(elemType);
 
   if (C) {
     const llvm::Type* CType = C->getType();
@@ -1003,9 +711,9 @@
           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 == get_hlvm_buffer()) {
+            if (elemType == em.get_hlvm_buffer()) {
               // Assign the constant string to the buffer
-            } else if (elemType == get_hlvm_text()) {
+            } else if (elemType == em.get_hlvm_text()) {
             }
           }
         }
@@ -1013,7 +721,7 @@
       hlvmAssert(CType->isLosslesslyConvertibleTo(elemType));
       C = llvm::ConstantExpr::getCast(C,elemType);
     }
-    llvm::Value* store = new llvm::StoreInst(C,alloca,lblk);
+    llvm::Value* store = em.emitStore(C,alloca);
   }
   pushOperand(alloca,av);
   lvars[av] = alloca;
@@ -1027,9 +735,7 @@
   hlvmAssert((operand->getType()->isInteger() || 
             operand->getType()->isFloatingPoint()) && 
             "Can't negate non-numeric");
-  llvm::BinaryOperator* neg = 
-  llvm::BinaryOperator::createNeg(operand,"neg",lblk);
-  pushOperand(neg,op);
+  pushOperand(em.emitNeg(operand),op);
 }
 
 template<> void
@@ -1039,11 +745,7 @@
   operand = ptr2Value(operand);
   const llvm::Type* lType = operand->getType();
   hlvmAssert(lType->isInteger() && "Can't complement non-integral type");
-  llvm::ConstantIntegral* allOnes = 
-  llvm::ConstantIntegral::getAllOnesValue(lType);
-  llvm::BinaryOperator* cmpl = llvm::BinaryOperator::create(
-    llvm::Instruction::Xor,operand,allOnes,"cmpl",lblk);
-  pushOperand(cmpl,op);
+  pushOperand(em.emitCmpl(operand),op);
 }
 
 template<> void
@@ -1054,19 +756,15 @@
   hlvmAssert(llvm::isa<llvm::PointerType>(lType));
   const llvm::PointerType* PT = llvm::cast<llvm::PointerType>(lType);
   lType = PT->getElementType();
-  llvm::LoadInst* load = new llvm::LoadInst(operand,"preincr",lblk);
+  llvm::LoadInst* load = em.emitLoad(operand,"preincr");
   if (lType->isFloatingPoint()) {
-    llvm::ConstantFP* one = llvm::ConstantFP::get(lType,1.0);
-    llvm::BinaryOperator* add = llvm::BinaryOperator::create(
-      llvm::Instruction::Add, load, one, "preincr", lblk);
-    new llvm::StoreInst(add,operand,lblk);
-    pushOperand(add,op);
+    llvm::Constant* one = em.getFPOne(lType);
+    llvm::BinaryOperator* add = em.emitAdd(load,one); 
+    pushOperand(em.emitStore(add,operand),op);
   } else if (lType->isInteger()) {
-    llvm::ConstantInt* one = llvm::ConstantInt::get(lType,1);
-    llvm::BinaryOperator* add = llvm::BinaryOperator::create(
-      llvm::Instruction::Add, load, one, "preincr", lblk);
-    new llvm::StoreInst(add,operand,lblk);
-    pushOperand(add,op);
+    llvm::Constant* one = em.getIOne(lType);
+    llvm::BinaryOperator* add = em.emitAdd(load,one); 
+    pushOperand(em.emitStore(add,operand),op);
   } else {
     hlvmAssert(!"PreIncrOp on non-numeric");
   }
@@ -1080,19 +778,15 @@
   hlvmAssert(llvm::isa<llvm::PointerType>(lType));
   const llvm::PointerType* PT = llvm::cast<llvm::PointerType>(lType);
   lType = PT->getElementType();
-  llvm::LoadInst* load = new llvm::LoadInst(operand,"predecr",lblk);
+  llvm::LoadInst* load = em.emitLoad(operand,"predecr");
   if (lType->isFloatingPoint()) {
-    llvm::ConstantFP* one = llvm::ConstantFP::get(lType,1.0);
-    llvm::BinaryOperator* sub = llvm::BinaryOperator::create(
-      llvm::Instruction::Sub, load, one, "predecr", lblk);
-    new llvm::StoreInst(sub,operand,lblk);
-    pushOperand(sub,op);
+    llvm::Constant* one = em.getFPOne(lType);
+    llvm::BinaryOperator* sub = em.emitSub(load,one);
+    pushOperand(em.emitStore(sub,operand),op);
   } else if (lType->isInteger()) {
-    llvm::ConstantInt* one = llvm::ConstantInt::get(lType,1);
-    llvm::BinaryOperator* sub = llvm::BinaryOperator::create(
-      llvm::Instruction::Sub, load, one, "predecr", lblk);
-    new llvm::StoreInst(sub,operand,lblk);
-    pushOperand(sub,op);
+    llvm::Constant* one = em.getIOne(lType);
+    llvm::BinaryOperator* sub = em.emitSub(load, one);
+    pushOperand(em.emitStore(sub,operand),op);
   } else {
     hlvmAssert(!"PreIncrOp on non-numeric");
   }
@@ -1106,18 +800,16 @@
   hlvmAssert(llvm::isa<llvm::PointerType>(lType));
   const llvm::PointerType* PT = llvm::cast<llvm::PointerType>(lType);
   lType = PT->getElementType();
-  llvm::LoadInst* load = new llvm::LoadInst(operand,"postincr",lblk);
+  llvm::LoadInst* load = em.emitLoad(operand,"postincr");
   if (lType->isFloatingPoint()) {
-    llvm::ConstantFP* one = llvm::ConstantFP::get(lType,1.0);
-    llvm::BinaryOperator* add = llvm::BinaryOperator::create(
-      llvm::Instruction::Add, load, one, "postincr", lblk);
-    new llvm::StoreInst(add,operand,lblk);
+    llvm::Constant* one = em.getFPOne(lType);
+    llvm::BinaryOperator* add = em.emitAdd(load,one); 
+    em.emitStore(add,operand);
     pushOperand(load,op);
   } else if (lType->isInteger()) {
-    llvm::ConstantInt* one = llvm::ConstantInt::get(lType,1);
-    llvm::BinaryOperator* add = llvm::BinaryOperator::create(
-      llvm::Instruction::Add, load, one, "postincr", lblk);
-    new llvm::StoreInst(add,operand,lblk);
+    llvm::Constant* one = em.getIOne(lType);
+    llvm::BinaryOperator* add = em.emitAdd(load,one); 
+    em.emitStore(add,operand);
     pushOperand(load,op);
   } else {
     hlvmAssert(!"PostDecrOp on non-numeric");
@@ -1132,18 +824,16 @@
   hlvmAssert(llvm::isa<llvm::PointerType>(lType));
   const llvm::PointerType* PT = llvm::cast<llvm::PointerType>(lType);
   lType = PT->getElementType();
-  llvm::LoadInst* load = new llvm::LoadInst(operand,"postdecr",lblk);
+  llvm::LoadInst* load = em.emitLoad(operand,"postdecr");
   if (lType->isFloatingPoint()) {
-    llvm::ConstantFP* one = llvm::ConstantFP::get(lType,1.0);
-    llvm::BinaryOperator* sub = llvm::BinaryOperator::create(
-      llvm::Instruction::Sub, load, one, "postdecr", lblk);
-    new llvm::StoreInst(sub,operand,lblk);
+    llvm::Constant* one = em.getFPOne(lType);
+    llvm::BinaryOperator* sub = em.emitSub(load, one);
+    em.emitStore(sub,operand);
     pushOperand(load,op);
   } else if (lType->isInteger()) {
-    llvm::ConstantInt* one = llvm::ConstantInt::get(lType,1);
-    llvm::BinaryOperator* sub = llvm::BinaryOperator::create(
-      llvm::Instruction::Sub, load, one, "postdecr", lblk);
-    new llvm::StoreInst(sub,operand,lblk);
+    llvm::Constant* one = em.getIOne(lType);
+    llvm::BinaryOperator* sub = em.emitSub(load, one);
+    em.emitStore(sub,operand);
     pushOperand(load,op);
   } else {
     hlvmAssert(!"PostDecrOp on non-numeric");
@@ -1157,9 +847,7 @@
   llvm::Value* op2 = popOperand(op->getOperand(1)); 
   op1 = ptr2Value(op1);
   op2 = ptr2Value(op2);
-  llvm::BinaryOperator* add = llvm::BinaryOperator::create(
-  llvm::Instruction::Add, op1, op2, "add", lblk);
-  pushOperand(add,op);
+  pushOperand(em.emitAdd(op1,op2),op);
 }
 
 template<> void
@@ -1169,9 +857,7 @@
   llvm::Value* op2 = popOperand(op->getOperand(1)); 
   op1 = ptr2Value(op1);
   op2 = ptr2Value(op2);
-  llvm::BinaryOperator* sub = llvm::BinaryOperator::create(
-  llvm::Instruction::Sub, op1, op2, "add", lblk);
-  pushOperand(sub,op);
+  pushOperand(em.emitSub(op1,op2),op);
 }
 
 template<> void
@@ -1181,9 +867,7 @@
   llvm::Value* op2 = popOperand(op->getOperand(1)); 
   op1 = ptr2Value(op1);
   op2 = ptr2Value(op2);
-  llvm::BinaryOperator* mul = llvm::BinaryOperator::create(
-  llvm::Instruction::Mul, op1, op2, "mul", lblk);
-  pushOperand(mul,op);
+  pushOperand(em.emitMul(op1,op2),op);
 }
 
 template<> void
@@ -1193,9 +877,7 @@
   llvm::Value* op2 = popOperand(op->getOperand(1)); 
   op1 = ptr2Value(op1);
   op2 = ptr2Value(op2);
-  llvm::BinaryOperator* div = llvm::BinaryOperator::create(
-  llvm::Instruction::Div, op1, op2, "div", lblk);
-  pushOperand(div,op);
+  pushOperand(em.emitDiv(op1,op2),op);
 }
 
 template<> void
@@ -1205,9 +887,7 @@
   llvm::Value* op2 = popOperand(op->getOperand(1)); 
   op1 = ptr2Value(op1);
   op2 = ptr2Value(op2);
-  llvm::BinaryOperator* rem = llvm::BinaryOperator::create(
-  llvm::Instruction::Rem, op1, op2, "mod", lblk);
-  pushOperand(rem,op);
+  pushOperand(em.emitMod(op1,op2),op);
 }
 
 template<> void
@@ -1217,9 +897,7 @@
   llvm::Value* op2 = popOperand(op->getOperand(1)); 
   op1 = ptr2Value(op1);
   op2 = ptr2Value(op2);
-  llvm::BinaryOperator* band = llvm::BinaryOperator::create(
-  llvm::Instruction::And, op1, op2, "band", lblk);
-  pushOperand(band,op);
+  pushOperand(em.emitBAnd(op1,op2),op);
 }
 
 template<> void
@@ -1229,9 +907,7 @@
   llvm::Value* op2 = popOperand(op->getOperand(1)); 
   op1 = ptr2Value(op1);
   op2 = ptr2Value(op2);
-  llvm::BinaryOperator* bor = llvm::BinaryOperator::create(
-  llvm::Instruction::Or, op1, op2, "bor", lblk);
-  pushOperand(bor,op);
+  pushOperand(em.emitBOr(op1,op2),op);
 }
 
 template<> void
@@ -1241,9 +917,7 @@
   llvm::Value* op2 = popOperand(op->getOperand(1)); 
   op1 = ptr2Value(op1);
   op2 = ptr2Value(op2);
-  llvm::BinaryOperator* Xor = llvm::BinaryOperator::create(
-  llvm::Instruction::Xor, op1, op2, "bxor", lblk);
-  pushOperand(Xor,op);
+  pushOperand(em.emitBXor(op1,op2),op);
 }
 
 template<> void
@@ -1253,10 +927,7 @@
   llvm::Value* op2 = popOperand(op->getOperand(1)); 
   op1 = ptr2Value(op1);
   op2 = ptr2Value(op2);
-  llvm::BinaryOperator* bor = llvm::BinaryOperator::create(
-  llvm::Instruction::Or, op1, op2, "bnor", lblk);
-  llvm::BinaryOperator* nor = llvm::BinaryOperator::createNot(bor,"bnor",lblk);
-  pushOperand(nor,op);
+  pushOperand(em.emitBNor(op1,op2),op);
 }
 
 template<> void
@@ -1265,9 +936,7 @@
   llvm::Value* op1 = popOperand(op->getOperand(0)); 
   llvm::Value* op2 = popOperand(op->getOperand(1)); 
   op1 = ptr2Value(op1);
-  llvm::Value* b1 = toBoolean(op1);
-  llvm::BinaryOperator* Not = llvm::BinaryOperator::createNot(b1,"not",lblk);
-  pushOperand(Not,op);
+  pushOperand(em.emitNot(op1),op);
 }
 
 template<> void
@@ -1277,11 +946,7 @@
   llvm::Value* op2 = popOperand(op->getOperand(1)); 
   op1 = ptr2Value(op1);
   op2 = ptr2Value(op2);
-  llvm::Value* b1 = toBoolean(op1);
-  llvm::Value* b2 = toBoolean(op2);
-  llvm::BinaryOperator* And = llvm::BinaryOperator::create(
-  llvm::Instruction::And, b1, b2, "and", lblk);
-  pushOperand(And,op);
+  pushOperand(em.emitAnd(op1,op2),op);
 }
 
 template<> void
@@ -1291,11 +956,7 @@
   llvm::Value* op2 = popOperand(op->getOperand(1)); 
   op1 = ptr2Value(op1);
   op2 = ptr2Value(op2);
-  llvm::Value* b1 = toBoolean(op1);
-  llvm::Value* b2 = toBoolean(op2);
-  llvm::BinaryOperator* Or = llvm::BinaryOperator::create(
-  llvm::Instruction::Or, b1, b2, "or", lblk);
-  pushOperand(Or,op);
+  pushOperand(em.emitOr(op1,op2),op);
 }
 
 template<> void
@@ -1305,12 +966,7 @@
   llvm::Value* op2 = popOperand(op->getOperand(1)); 
   op1 = ptr2Value(op1);
   op2 = ptr2Value(op2);
-  llvm::Value* b1 = toBoolean(op1);
-  llvm::Value* b2 = toBoolean(op2);
-  llvm::BinaryOperator* Or = llvm::BinaryOperator::create(
-  llvm::Instruction::Or, b1, b2, "nor", lblk);
-  llvm::BinaryOperator* Nor = llvm::BinaryOperator::createNot(Or,"nor",lblk);
-  pushOperand(Nor,op);
+  pushOperand(em.emitNor(op1,op2),op);
 }
 
 template<> void
@@ -1320,11 +976,7 @@
   llvm::Value* op2 = popOperand(op->getOperand(1)); 
   op1 = ptr2Value(op1);
   op2 = ptr2Value(op2);
-  llvm::Value* b1 = toBoolean(op1);
-  llvm::Value* b2 = toBoolean(op2);
-  llvm::BinaryOperator* Xor = llvm::BinaryOperator::create(
-  llvm::Instruction::Xor, b1, b2, "xor", lblk);
-  pushOperand(Xor,op);
+  pushOperand(em.emitXor(op1,op2),op);
 }
 
 template<> void
@@ -1334,9 +986,7 @@
   llvm::Value* op2 = popOperand(op->getOperand(1)); 
   op1 = ptr2Value(op1);
   op2 = ptr2Value(op2);
-  llvm::SetCondInst* SCI = 
-  new llvm::SetCondInst(llvm::Instruction::SetEQ, op1,op2,"eq",lblk);
-  pushOperand(SCI,op);
+  pushOperand(em.emitEQ(op1,op2),op);
 }
 
 template<> void
@@ -1346,9 +996,7 @@
   llvm::Value* op2 = popOperand(op->getOperand(1)); 
   op1 = ptr2Value(op1);
   op2 = ptr2Value(op2);
-  llvm::SetCondInst* SCI = 
-  new llvm::SetCondInst(llvm::Instruction::SetNE, op1,op2,"ne",lblk);
-  pushOperand(SCI,op);
+  pushOperand(em.emitNE(op1,op2),op);
 }
 
 template<> void
@@ -1356,9 +1004,9 @@
 {
   llvm::Value* op1 = popOperand(op->getOperand(0)); 
   llvm::Value* op2 = popOperand(op->getOperand(1)); 
-  llvm::SetCondInst* SCI = 
-  new llvm::SetCondInst(llvm::Instruction::SetLT, op1,op2,"lt",lblk);
-  pushOperand(SCI,op);
+  op1 = ptr2Value(op1);
+  op2 = ptr2Value(op2);
+  pushOperand(em.emitLT(op1,op2),op);
 }
 
 template<> void
@@ -1366,9 +1014,9 @@
 {
   llvm::Value* op1 = popOperand(op->getOperand(0)); 
   llvm::Value* op2 = popOperand(op->getOperand(1)); 
-  llvm::SetCondInst* SCI = 
-  new llvm::SetCondInst(llvm::Instruction::SetGT, op1,op2,"gt",lblk);
-  pushOperand(SCI,op);
+  op1 = ptr2Value(op1);
+  op2 = ptr2Value(op2);
+  pushOperand(em.emitLT(op1,op2),op);
 }
 
 template<> void
@@ -1376,9 +1024,9 @@
 {
   llvm::Value* op1 = popOperand(op->getOperand(0)); 
   llvm::Value* op2 = popOperand(op->getOperand(1)); 
-  llvm::SetCondInst* SCI = 
-  new llvm::SetCondInst(llvm::Instruction::SetGE, op1,op2,"ge",lblk);
-  pushOperand(SCI,op);
+  op1 = ptr2Value(op1);
+  op2 = ptr2Value(op2);
+  pushOperand(em.emitGE(op1,op2),op);
 }
 
 template<> void
@@ -1386,9 +1034,9 @@
 {
   llvm::Value* op1 = popOperand(op->getOperand(0)); 
   llvm::Value* op2 = popOperand(op->getOperand(1)); 
-  llvm::SetCondInst* SCI = 
-  new llvm::SetCondInst(llvm::Instruction::SetLE, op1,op2,"le",lblk);
-  pushOperand(SCI,op);
+  op1 = ptr2Value(op1);
+  op2 = ptr2Value(op2);
+  pushOperand(em.emitLE(op1,op2),op);
 }
 
 template<> void
@@ -1408,7 +1056,7 @@
     hlvmAssert(op1->getType() == llvm::Type::BoolTy);
     hlvmAssert(op2->getType()->isFirstClassType());
     hlvmAssert(op3->getType()->isFirstClassType());
-    pushOperand(new llvm::SelectInst(op1,op2,op3,"select",lblk),op);
+    pushOperand(em.emitSelect(op1,op2,op3,"select"),op);
     return;
   }
 
@@ -1424,7 +1072,7 @@
   popOperandAsCondition(op->getOperand(0),"select",cond_entry,cond_exit);
 
   // Branch the current block into the condition block
-  new llvm::BranchInst(cond_entry,lblk);
+  em.emitBranch(cond_entry); 
 
   // Get the true case
   llvm::BasicBlock *true_entry, *true_exit;
@@ -1443,7 +1091,7 @@
     new llvm::StoreInst(op3,select_result,false_exit);
 
   // Create the exit block
-  llvm::BasicBlock* select_exit = newBlock("select_exit");
+  llvm::BasicBlock* select_exit = em.newBlock("select_exit");
 
   // Branch the the true and false cases to the exit
   branchIfNotTerminated(select_exit,true_exit);
@@ -1475,7 +1123,7 @@
     popOperandAsCondition(op->getOperand(0),"while",cond_entry,cond_exit);
 
   // Branch the current block into the condition block
-  new llvm::BranchInst(cond_entry,lblk);
+  em.emitBranch(cond_entry);
 
   // Get the while loop's body
   llvm::BasicBlock *body_entry, *body_exit;
@@ -1487,7 +1135,7 @@
     new llvm::StoreInst(op2,while_result,body_exit);
 
   // Create the exit block
-  llvm::BasicBlock* while_exit = newBlock("while_exit");
+  llvm::BasicBlock* while_exit = em.newBlock("while_exit");
 
   // Branch the the body block back to the condition branch
   branchIfNotTerminated(cond_entry,body_exit);
@@ -1500,8 +1148,8 @@
     pushOperand(new llvm::LoadInst(while_result,"while_result",while_exit),op);
 
   // Fix up any break or continue operators
-  resolveBranches(breaks,while_exit);
-  resolveBranches(continues,cond_entry);
+  em.ResolveBreaks(while_exit);
+  em.ResolveContinues(cond_entry);
 }
 
 template<> void
@@ -1516,7 +1164,7 @@
     popOperandAsCondition(op->getOperand(0),"unless",cond_entry,cond_exit);
 
   // Branch the current block into the condition block
-  new llvm::BranchInst(cond_entry,lblk);
+  em.emitBranch(cond_entry);
 
   // Get the unless block's body
   llvm::BasicBlock *body_entry, *body_exit;
@@ -1528,7 +1176,7 @@
     new llvm::StoreInst(op2,unless_result,body_exit);
 
   // Create the exit block
-  llvm::BasicBlock* unless_exit = newBlock("unless_exit");
+  llvm::BasicBlock* unless_exit = em.newBlock("unless_exit");
 
   // Branch the the body block back to the condition branch
   branchIfNotTerminated(cond_entry,body_exit);
@@ -1542,8 +1190,8 @@
       new llvm::LoadInst(unless_result,"unless_result",unless_exit),op);
 
   // Fix up any break or continue operators
-  resolveBranches(breaks,unless_exit);
-  resolveBranches(continues,cond_entry);
+  em.ResolveBreaks(unless_exit);
+  em.ResolveContinues(cond_entry);
 }
 
 template<> void
@@ -1567,13 +1215,13 @@
     new llvm::StoreInst(op1,until_result,body_exit);
 
   // Branch the current block into the body block
-  new llvm::BranchInst(body_entry,lblk);
+  em.emitBranch(body_entry);
 
   // Branch the body block to the condition block
   branchIfNotTerminated(cond_entry,body_exit);
 
   // Create the exit block
-  llvm::BasicBlock* until_exit = newBlock("until_exit");
+  llvm::BasicBlock* until_exit = em.newBlock("until_exit");
 
   // Finally, install the conditional branch into condition block
   new llvm::BranchInst(until_exit,body_entry,op2,cond_exit);
@@ -1583,8 +1231,8 @@
     pushOperand(new llvm::LoadInst(until_result,"until_result",until_exit),op);
 
   // Fix up any break or continue operators
-  resolveBranches(breaks,until_exit);
-  resolveBranches(continues,cond_entry);
+  em.ResolveBreaks(until_exit);
+  em.ResolveContinues(cond_entry);
 }
 
 template<> void
@@ -1600,7 +1248,7 @@
       start_cond_entry,start_cond_exit);
 
   // Branch the current block into the start condition block
-  new llvm::BranchInst(start_cond_entry,lblk);
+  em.emitBranch(start_cond_entry);
 
   // Get the loop body
   llvm::BasicBlock *body_entry, *body_exit;
@@ -1621,7 +1269,7 @@
   branchIfNotTerminated(end_cond_entry,body_exit);
 
   // Create the exit block
-  llvm::BasicBlock* loop_exit = newBlock("loop_exit");
+  llvm::BasicBlock* loop_exit = em.newBlock("loop_exit");
 
   // Install the conditional branches for start and end condition blocks
   new llvm::BranchInst(body_entry,loop_exit,op1,start_cond_exit);
@@ -1632,8 +1280,8 @@
     pushOperand(new llvm::LoadInst(loop_result,"loop_result",loop_exit),op);
 
   // Fix up any break or continue operators
-  resolveBranches(breaks,loop_exit);
-  resolveBranches(continues,end_cond_entry);
+  em.ResolveBreaks(loop_exit);
+  em.ResolveContinues(end_cond_entry);
 }
 
 template<> void
@@ -1645,8 +1293,7 @@
 
   // Just push a place-holder branch onto the breaks list so it can
   // be fixed up later once we know the destination
-  llvm::BranchInst* brnch = new llvm::BranchInst(lblk,lblk);
-  breaks.push_back(brnch);
+  llvm::BranchInst* brnch = em.emitBreak();
   pushOperand(brnch,op);
 }
 
@@ -1659,8 +1306,7 @@
 
   // Just push a place-holder branch onto the continues list so it can
   // be fixed up later once we know the destination
-  llvm::BranchInst* brnch = new llvm::BranchInst(lblk,lblk);
-  continues.push_back(brnch);
+  llvm::BranchInst* brnch = em.emitContinue();
   pushOperand(brnch,op);
 }
 
@@ -1671,11 +1317,33 @@
   llvm::Value* result = popOperand(r->getOperand(0));
   // Get the block this result applies to
   hlvm::Block* B = llvm::cast<hlvm::Block>(r->getParent());
-  // Generate a store into the location set up by the block for its result
+  // Get the location into which we will store the result
   llvm::Value* instr = 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);
-  new llvm::StoreInst(result,instr,lblk);
+  em.emitStore(result,instr);
 }
 
 template<> void
@@ -1685,16 +1353,16 @@
   llvm::Value* result = 0;
 
   // If this function returns a result then we need a return value
-  if (lfunc->getReturnType() != llvm::Type::VoidTy) {
+  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() == lfunc->getReturnType());
-      result = new llvm::LoadInst(result,lblk->getName()+"_result",lblk);
-    } else if (resultTy != lfunc->getReturnType()) {
-      result = new llvm::CastInst(result,lfunc->getReturnType(),
-        lblk->getName()+"_result",lblk);
+      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");
   }
@@ -1702,7 +1370,7 @@
   // 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.
-  new llvm::ReturnInst(result,lblk);
+  em.emitReturn(result);
 }
 
 template<> void
@@ -1736,7 +1404,7 @@
     llvm::cast<llvm::Function>(funcToCall));
 
   // Make the call
-  pushOperand(new llvm::CallInst(F,args,"call_" + hFunc->getName(),lblk),co);
+  pushOperand(em.emitCall(F,args),co);
 }
 
 template<> void
@@ -1746,14 +1414,22 @@
   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.
-  new llvm::StoreInst(value,location,lblk);
+  em.emitStore(value,location);
 }
 
 template<> void
 LLVMGeneratorPass::gen(LoadOp* l)
 {
   llvm::Value* location = popOperand(l->getOperand(0));
-  pushOperand(new llvm::LoadInst(location,location->getName(),lblk),l);
+  const llvm::PointerType* PT = 
+    llvm::dyn_cast<llvm::PointerType>(location->getType());
+  hlvmAssert(PT && "Attempt to load non-pointer?");
+
+  const llvm::Type* ET = PT->getElementType();
+  if (!ET->isFirstClassType())
+    pushOperand(location,l);
+  else
+    pushOperand(em.emitLoad(location,location->getName()),l);
 }
 
 template<> void
@@ -1781,19 +1457,14 @@
   } else if (llvm::isa<llvm::ArrayType>(Ty) && 
              llvm::cast<llvm::ArrayType>(Ty)->getElementType() == 
              llvm::Type::SByteTy) {
-    std::vector<llvm::Value*> indices;
-    indices.push_back(llvm::Constant::getNullValue(llvm::Type::UIntTy));
-    indices.push_back(llvm::Constant::getNullValue(llvm::Type::UIntTy));
-    llvm::GetElementPtrInst* gep = 
-      new llvm::GetElementPtrInst(strm,indices,"",lblk);
-    args.push_back(gep);
+    ArgList indices;
+    em.TwoZeroIndices(indices);
+    args.push_back(em.emitGEP(strm,indices));
   } else
     hlvmAssert(!"Array element type is not SByteTy");
   } else
     hlvmAssert(!"OpenOp parameter is not a pointer");
-  llvm::CallInst* ci = new 
-  llvm::CallInst(get_hlvm_stream_open(), args, "open", lblk);
-  pushOperand(ci,o);
+  pushOperand(em.call_hlvm_stream_open(args,"open"),o);
 }
 
 template<> void
@@ -1807,14 +1478,11 @@
   if (llvm::isa<llvm::PointerType>(arg2->getType()))
   if (llvm::cast<llvm::PointerType>(arg2->getType())->getElementType() ==
       llvm::Type::SByteTy)
-    pushOperand(
-      new llvm::CallInst(get_hlvm_stream_write_string(), args, "", lblk),o);
-  if (arg2->getType() == get_hlvm_text())
-    pushOperand(
-      new llvm::CallInst(get_hlvm_stream_write_text(), args, "", lblk),o);
-  else if (arg2->getType() == get_hlvm_buffer())
-    pushOperand(
-      new llvm::CallInst(get_hlvm_stream_write_buffer(), args, "write",lblk),o);
+    pushOperand(em.call_hlvm_stream_write_string(args,"write"),o);
+  if (arg2->getType() == em.get_hlvm_text())
+    pushOperand(em.call_hlvm_stream_write_text(args,"write"),o);
+  else if (arg2->getType() == em.get_hlvm_buffer())
+    pushOperand(em.call_hlvm_stream_write_buffer(args,"write"),o);
 }
 
 template<> void
@@ -1827,9 +1495,7 @@
   args.push_back(strm);
   args.push_back(arg2);
   args.push_back(arg3);
-  llvm::CallInst* ci = 
-    new llvm::CallInst(get_hlvm_stream_read(), args, "read", lblk);
-  pushOperand(ci,o);
+  pushOperand(em.call_hlvm_stream_read(args,"read"),o);
 }
 
 template<> void
@@ -1838,9 +1504,7 @@
   llvm::Value* strm = popOperand(o->getOperand(0));
   std::vector<llvm::Value*> args;
   args.push_back(strm);
-  llvm::CallInst* ci = 
-    new llvm::CallInst(get_hlvm_stream_close(), args, "", lblk);
-  pushOperand(ci,o);
+  pushOperand(em.call_hlvm_stream_close(args),o);
 }
 
 void 
@@ -1854,7 +1518,7 @@
   // a string and a pointer to the function).
   std::vector<const llvm::Type*> Fields;
   Fields.push_back(llvm::PointerType::get(llvm::Type::SByteTy));
-  Fields.push_back(llvm::PointerType::get(get_hlvm_program_signature()));
+  Fields.push_back(llvm::PointerType::get(em.get_hlvm_program_signature()));
   llvm::StructType* entry_elem_type = llvm::StructType::get(Fields);
 
   // Define the type of the array for the entry points
@@ -1872,13 +1536,10 @@
     llvm::Constant* name_val = llvm::ConstantArray::get(funcName,true);
 
     // Create a constant global variable to hold the name of the program.
-    llvm::GlobalVariable* name = new llvm::GlobalVariable(
+    llvm::GlobalVariable* name = em.NewGConst(
       /*Type=*/name_val->getType(),
-      /*isConst=*/true,
-      /*Linkage=*/llvm::GlobalValue::InternalLinkage, 
       /*Initializer=*/name_val, 
-      /*name=*/"", 
-      /*InsertInto=*/lmod
+      /*name=*/"prog_name"
     );
 
     llvm::Constant* index = llvm::ConstantExpr::getPtrPtrFromArrayPtr(name);
@@ -1905,7 +1566,7 @@
     /*Linkage=*/llvm::GlobalValue::AppendingLinkage,
     /*Initializer=*/entry_points_initializer,
     /*Name=*/"hlvm_programs",
-    /*Parent=*/lmod
+    /*Parent=*/em.getModule()
   );
 }
 
@@ -1925,8 +1586,7 @@
     {
       case BundleID:
       {
-        lmod = new llvm::Module(llvm::cast<Bundle>(n)->getName());
-        modules.push_back(lmod);
+        em.StartModule(llvm::cast<Bundle>(n)->getName());
         lvars.clear();
         gvars.clear();
         funcs.clear();
@@ -1945,12 +1605,22 @@
         getConstant(llvm::cast<ConstantString>(n));
         break;
       case ConstantAnyID:
+        getConstant(llvm::cast<ConstantAny>(n));
+        break;
       case ConstantStructureID:
+        getConstant(llvm::cast<ConstantStructure>(n));
+        break;
       case ConstantArrayID:
+        getConstant(llvm::cast<ConstantArray>(n));
+        break;
       case ConstantVectorID:
+        getConstant(llvm::cast<ConstantVector>(n));
+        break;
       case ConstantContinuationID:
+        getConstant(llvm::cast<ConstantContinuation>(n));
+        break;
       case ConstantPointerID:
-        hlvmAssert(!"Not implemented yet");
+        getConstant(llvm::cast<ConstantPointer>(n));
         break;
       case VariableID:              
         getVariable(llvm::cast<Variable>(n)); 
@@ -1959,41 +1629,34 @@
       {
         // Get/Create the function
         function = llvm::cast<hlvm::Function>(n);
-        lfunc = getFunction(function);
-        startNewFunction(lfunc);
+        startNewFunction(getFunction(function));
         break;
       }
       case ProgramID:
       {
         // Create a new function for the program based on the signature
         function = llvm::cast<hlvm::Program>(n);
-        lfunc = new llvm::Function(
-            /*Type=*/ get_hlvm_program_signature(),
+        llvm::Function* F = em.NewFunction(
+            /*Type=*/ em.get_hlvm_program_signature(),
             /*Linkage=*/llvm::GlobalValue::InternalLinkage,
-            /*Name=*/ getLinkageName(function),
-            /*Module=*/ lmod
+            /*Name=*/ getLinkageName(function)
         );
-        startNewFunction(lfunc);
+        startNewFunction(F);
         // Save the program so it can be generated into the list of program 
         // entry points.
-        progs.push_back(lfunc);
+        progs.push_back(F);
         break;
       }
       case BlockID:
       {
         Block* B = llvm::cast<Block>(n);
         std::string name = B->getLabel().empty() ? "block" : B->getLabel();
-        enters[B] = pushBlock(name);
+        enters[B] = em.pushBlock(name);
         if (B->getResult()) {
           const llvm::Type* Ty = getType(B->getType());
-          llvm::AllocaInst* result = new llvm::AllocaInst(
-            /*Ty=*/ Ty,
-            /*ArraySize=*/ llvm::ConstantUInt::get(llvm::Type::UIntTy,1),
-            /*Name=*/ name + "_var",
-            /*InsertAtEnd=*/ &lfunc->front()
-          ); 
+          llvm::AllocaInst* result = em.NewAutoVar(Ty, name+"_var");
           // Initialize the autovar to null
-          new llvm::StoreInst(llvm::Constant::getNullValue(Ty),result,lblk);
+          em.emitStore(em.getNullValue(Ty),result);
           pushOperand(result,B); 
         }
         break;
@@ -2025,7 +1688,7 @@
       case VectorTypeID:
       {
         Type* t = llvm::cast<Type>(n);
-        lmod->addTypeName(t->getName(), getType(t));
+        em.AddType(getType(t), t->getName());
         break;
       }
       case NegateOpID:              gen(llvm::cast<NegateOp>(n)); break;
@@ -2076,34 +1739,36 @@
 
       case BundleID:
         genProgramLinkage();
-        lmod = 0;
+        modules.push_back(em.FinishModule());
         break;
       case ConstantBooleanID:       
-        /* FALL THROUGH */
       case ConstantIntegerID:      
-        /* FALL THROUGH */
       case ConstantRealID:        
-        /* FALL THROUGH */
       case ConstantStringID:     
+      case ConstantAnyID:
+      case ConstantStructureID:
+      case ConstantArrayID:
+      case ConstantVectorID:
+      case ConstantContinuationID:
+      case ConstantPointerID:
         /* FALL THROUGH */
       case VariableID: 
         break;
       case ProgramID:
         /* FALL THROUGH */
       case FunctionID:
+        em.FinishFunction();
         // The entry block was created to hold the automatic variables. We now
         // need to terminate the block by branching it to the first active block
         // in the function.
-        new llvm::BranchInst(lfunc->front().getNext(),&lfunc->front());
         function = 0;
-        lfunc = 0;
         break;
       case BlockID:
       {
         Block* B = llvm::cast<Block>(n);
-        exits[B] = lblk;
+        exits[B] = em.getBlock();
         getBlockResult(B);
-        popBlock(lblk);
+        em.popBlock();
         break;
       }
 





More information about the llvm-commits mailing list