[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