mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-12 02:43:14 +01:00
More CRLF->LF line ending conversion.
This commit is contained in:
350
gen/irstate.cpp
350
gen/irstate.cpp
@@ -1,175 +1,175 @@
|
||||
/* DMDFE backend stubs
|
||||
* This file contains the implementations of the backend routines.
|
||||
* For dmdfe these do nothing but print a message saying the module
|
||||
* has been parsed. Substitute your own behaviors for these routimes.
|
||||
*/
|
||||
|
||||
#include <cstdarg>
|
||||
|
||||
#include "gen/llvm.h"
|
||||
|
||||
#include "mtype.h"
|
||||
#include "declaration.h"
|
||||
#include "statement.h"
|
||||
|
||||
#include "gen/irstate.h"
|
||||
#include "tollvm.h"
|
||||
|
||||
IRState* gIR = 0;
|
||||
llvm::TargetMachine* gTargetMachine = 0;
|
||||
const llvm::TargetData* gTargetData = 0;
|
||||
TargetABI* gABI = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
IRScope::IRScope()
|
||||
: builder(gIR->context())
|
||||
{
|
||||
begin = end = NULL;
|
||||
}
|
||||
|
||||
IRScope::IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e)
|
||||
: builder(b)
|
||||
{
|
||||
begin = b;
|
||||
end = e;
|
||||
}
|
||||
|
||||
const IRScope& IRScope::operator=(const IRScope& rhs)
|
||||
{
|
||||
begin = rhs.begin;
|
||||
end = rhs.end;
|
||||
builder.SetInsertPoint(begin);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
IRTargetScope::IRTargetScope()
|
||||
{
|
||||
}
|
||||
|
||||
IRTargetScope::IRTargetScope(Statement* s, EnclosingHandler* enclosinghandler, llvm::BasicBlock* continueTarget, llvm::BasicBlock* breakTarget)
|
||||
{
|
||||
this->s = s;
|
||||
this->enclosinghandler = enclosinghandler;
|
||||
this->breakTarget = breakTarget;
|
||||
this->continueTarget = continueTarget;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
IRState::IRState(llvm::Module* m)
|
||||
: module(m), dibuilder(*m)
|
||||
{
|
||||
interfaceInfoType = NULL;
|
||||
mutexType = NULL;
|
||||
moduleRefType = NULL;
|
||||
|
||||
dmodule = 0;
|
||||
emitMain = false;
|
||||
mainFunc = 0;
|
||||
ir.state = this;
|
||||
asmBlock = NULL;
|
||||
}
|
||||
|
||||
IrFunction* IRState::func()
|
||||
{
|
||||
assert(!functions.empty() && "Function stack is empty!");
|
||||
return functions.back();
|
||||
}
|
||||
|
||||
llvm::Function* IRState::topfunc()
|
||||
{
|
||||
assert(!functions.empty() && "Function stack is empty!");
|
||||
return functions.back()->func;
|
||||
}
|
||||
|
||||
TypeFunction* IRState::topfunctype()
|
||||
{
|
||||
assert(!functions.empty() && "Function stack is empty!");
|
||||
return functions.back()->type;
|
||||
}
|
||||
|
||||
llvm::Instruction* IRState::topallocapoint()
|
||||
{
|
||||
assert(!functions.empty() && "AllocaPoint stack is empty!");
|
||||
return functions.back()->allocapoint;
|
||||
}
|
||||
|
||||
IrStruct* IRState::topstruct()
|
||||
{
|
||||
assert(!structs.empty() && "Struct vector is empty!");
|
||||
return structs.back();
|
||||
}
|
||||
|
||||
IRScope& IRState::scope()
|
||||
{
|
||||
assert(!scopes.empty());
|
||||
return scopes.back();
|
||||
}
|
||||
|
||||
llvm::BasicBlock* IRState::scopebb()
|
||||
{
|
||||
IRScope& s = scope();
|
||||
assert(s.begin);
|
||||
return s.begin;
|
||||
}
|
||||
llvm::BasicBlock* IRState::scopeend()
|
||||
{
|
||||
IRScope& s = scope();
|
||||
assert(s.end);
|
||||
return s.end;
|
||||
}
|
||||
bool IRState::scopereturned()
|
||||
{
|
||||
//return scope().returned;
|
||||
return !scopebb()->empty() && scopebb()->back().isTerminator();
|
||||
}
|
||||
|
||||
LLCallSite IRState::CreateCallOrInvoke(LLValue* Callee, const char* Name)
|
||||
{
|
||||
LLSmallVector<LLValue*, 1> args;
|
||||
return CreateCallOrInvoke(Callee, args, Name);
|
||||
}
|
||||
|
||||
LLCallSite IRState::CreateCallOrInvoke(LLValue* Callee, LLValue* Arg1, const char* Name)
|
||||
{
|
||||
LLSmallVector<LLValue*, 1> args;
|
||||
args.push_back(Arg1);
|
||||
return CreateCallOrInvoke(Callee, args, Name);
|
||||
}
|
||||
|
||||
LLCallSite IRState::CreateCallOrInvoke2(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, const char* Name)
|
||||
{
|
||||
LLSmallVector<LLValue*, 2> args;
|
||||
args.push_back(Arg1);
|
||||
args.push_back(Arg2);
|
||||
return CreateCallOrInvoke(Callee, args, Name);
|
||||
}
|
||||
|
||||
LLCallSite IRState::CreateCallOrInvoke3(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, LLValue* Arg3, const char* Name)
|
||||
{
|
||||
LLSmallVector<LLValue*, 3> args;
|
||||
args.push_back(Arg1);
|
||||
args.push_back(Arg2);
|
||||
args.push_back(Arg3);
|
||||
return CreateCallOrInvoke(Callee, args, Name);
|
||||
}
|
||||
|
||||
LLCallSite IRState::CreateCallOrInvoke4(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, LLValue* Arg3, LLValue* Arg4, const char* Name)
|
||||
{
|
||||
LLSmallVector<LLValue*, 4> args;
|
||||
args.push_back(Arg1);
|
||||
args.push_back(Arg2);
|
||||
args.push_back(Arg3);
|
||||
args.push_back(Arg4);
|
||||
return CreateCallOrInvoke(Callee, args, Name);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IRBuilder<>* IRBuilderHelper::operator->()
|
||||
{
|
||||
IRBuilder<>& b = state->scope().builder;
|
||||
assert(b.GetInsertBlock() != NULL);
|
||||
return &b;
|
||||
}
|
||||
/* DMDFE backend stubs
|
||||
* This file contains the implementations of the backend routines.
|
||||
* For dmdfe these do nothing but print a message saying the module
|
||||
* has been parsed. Substitute your own behaviors for these routimes.
|
||||
*/
|
||||
|
||||
#include <cstdarg>
|
||||
|
||||
#include "gen/llvm.h"
|
||||
|
||||
#include "mtype.h"
|
||||
#include "declaration.h"
|
||||
#include "statement.h"
|
||||
|
||||
#include "gen/irstate.h"
|
||||
#include "tollvm.h"
|
||||
|
||||
IRState* gIR = 0;
|
||||
llvm::TargetMachine* gTargetMachine = 0;
|
||||
const llvm::TargetData* gTargetData = 0;
|
||||
TargetABI* gABI = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
IRScope::IRScope()
|
||||
: builder(gIR->context())
|
||||
{
|
||||
begin = end = NULL;
|
||||
}
|
||||
|
||||
IRScope::IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e)
|
||||
: builder(b)
|
||||
{
|
||||
begin = b;
|
||||
end = e;
|
||||
}
|
||||
|
||||
const IRScope& IRScope::operator=(const IRScope& rhs)
|
||||
{
|
||||
begin = rhs.begin;
|
||||
end = rhs.end;
|
||||
builder.SetInsertPoint(begin);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
IRTargetScope::IRTargetScope()
|
||||
{
|
||||
}
|
||||
|
||||
IRTargetScope::IRTargetScope(Statement* s, EnclosingHandler* enclosinghandler, llvm::BasicBlock* continueTarget, llvm::BasicBlock* breakTarget)
|
||||
{
|
||||
this->s = s;
|
||||
this->enclosinghandler = enclosinghandler;
|
||||
this->breakTarget = breakTarget;
|
||||
this->continueTarget = continueTarget;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
IRState::IRState(llvm::Module* m)
|
||||
: module(m), dibuilder(*m)
|
||||
{
|
||||
interfaceInfoType = NULL;
|
||||
mutexType = NULL;
|
||||
moduleRefType = NULL;
|
||||
|
||||
dmodule = 0;
|
||||
emitMain = false;
|
||||
mainFunc = 0;
|
||||
ir.state = this;
|
||||
asmBlock = NULL;
|
||||
}
|
||||
|
||||
IrFunction* IRState::func()
|
||||
{
|
||||
assert(!functions.empty() && "Function stack is empty!");
|
||||
return functions.back();
|
||||
}
|
||||
|
||||
llvm::Function* IRState::topfunc()
|
||||
{
|
||||
assert(!functions.empty() && "Function stack is empty!");
|
||||
return functions.back()->func;
|
||||
}
|
||||
|
||||
TypeFunction* IRState::topfunctype()
|
||||
{
|
||||
assert(!functions.empty() && "Function stack is empty!");
|
||||
return functions.back()->type;
|
||||
}
|
||||
|
||||
llvm::Instruction* IRState::topallocapoint()
|
||||
{
|
||||
assert(!functions.empty() && "AllocaPoint stack is empty!");
|
||||
return functions.back()->allocapoint;
|
||||
}
|
||||
|
||||
IrStruct* IRState::topstruct()
|
||||
{
|
||||
assert(!structs.empty() && "Struct vector is empty!");
|
||||
return structs.back();
|
||||
}
|
||||
|
||||
IRScope& IRState::scope()
|
||||
{
|
||||
assert(!scopes.empty());
|
||||
return scopes.back();
|
||||
}
|
||||
|
||||
llvm::BasicBlock* IRState::scopebb()
|
||||
{
|
||||
IRScope& s = scope();
|
||||
assert(s.begin);
|
||||
return s.begin;
|
||||
}
|
||||
llvm::BasicBlock* IRState::scopeend()
|
||||
{
|
||||
IRScope& s = scope();
|
||||
assert(s.end);
|
||||
return s.end;
|
||||
}
|
||||
bool IRState::scopereturned()
|
||||
{
|
||||
//return scope().returned;
|
||||
return !scopebb()->empty() && scopebb()->back().isTerminator();
|
||||
}
|
||||
|
||||
LLCallSite IRState::CreateCallOrInvoke(LLValue* Callee, const char* Name)
|
||||
{
|
||||
LLSmallVector<LLValue*, 1> args;
|
||||
return CreateCallOrInvoke(Callee, args, Name);
|
||||
}
|
||||
|
||||
LLCallSite IRState::CreateCallOrInvoke(LLValue* Callee, LLValue* Arg1, const char* Name)
|
||||
{
|
||||
LLSmallVector<LLValue*, 1> args;
|
||||
args.push_back(Arg1);
|
||||
return CreateCallOrInvoke(Callee, args, Name);
|
||||
}
|
||||
|
||||
LLCallSite IRState::CreateCallOrInvoke2(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, const char* Name)
|
||||
{
|
||||
LLSmallVector<LLValue*, 2> args;
|
||||
args.push_back(Arg1);
|
||||
args.push_back(Arg2);
|
||||
return CreateCallOrInvoke(Callee, args, Name);
|
||||
}
|
||||
|
||||
LLCallSite IRState::CreateCallOrInvoke3(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, LLValue* Arg3, const char* Name)
|
||||
{
|
||||
LLSmallVector<LLValue*, 3> args;
|
||||
args.push_back(Arg1);
|
||||
args.push_back(Arg2);
|
||||
args.push_back(Arg3);
|
||||
return CreateCallOrInvoke(Callee, args, Name);
|
||||
}
|
||||
|
||||
LLCallSite IRState::CreateCallOrInvoke4(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, LLValue* Arg3, LLValue* Arg4, const char* Name)
|
||||
{
|
||||
LLSmallVector<LLValue*, 4> args;
|
||||
args.push_back(Arg1);
|
||||
args.push_back(Arg2);
|
||||
args.push_back(Arg3);
|
||||
args.push_back(Arg4);
|
||||
return CreateCallOrInvoke(Callee, args, Name);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IRBuilder<>* IRBuilderHelper::operator->()
|
||||
{
|
||||
IRBuilder<>& b = state->scope().builder;
|
||||
assert(b.GetInsertBlock() != NULL);
|
||||
return &b;
|
||||
}
|
||||
|
||||
468
gen/irstate.h
468
gen/irstate.h
@@ -1,234 +1,234 @@
|
||||
#ifndef LDC_GEN_IRSTATE_H
|
||||
#define LDC_GEN_IRSTATE_H
|
||||
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <sstream>
|
||||
|
||||
#include "root.h"
|
||||
#include "aggregate.h"
|
||||
|
||||
#include "ir/irfunction.h"
|
||||
#include "ir/irstruct.h"
|
||||
#include "ir/irvar.h"
|
||||
|
||||
#if LDC_LLVM_VER >= 302
|
||||
#include "llvm/DIBuilder.h"
|
||||
#else
|
||||
#include "llvm/Analysis/DIBuilder.h"
|
||||
#endif
|
||||
#include "llvm/Support/CallSite.h"
|
||||
|
||||
namespace llvm {
|
||||
class LLVMContext;
|
||||
class TargetMachine;
|
||||
}
|
||||
|
||||
// global ir state for current module
|
||||
struct IRState;
|
||||
struct TargetABI;
|
||||
|
||||
extern IRState* gIR;
|
||||
extern llvm::TargetMachine* gTargetMachine;
|
||||
extern const llvm::TargetData* gTargetData;
|
||||
extern TargetABI* gABI;
|
||||
|
||||
struct TypeFunction;
|
||||
struct TypeStruct;
|
||||
struct ClassDeclaration;
|
||||
struct FuncDeclaration;
|
||||
struct Module;
|
||||
struct TypeStruct;
|
||||
struct BaseClass;
|
||||
struct AnonDeclaration;
|
||||
|
||||
struct IrModule;
|
||||
|
||||
// represents a scope
|
||||
struct IRScope
|
||||
{
|
||||
llvm::BasicBlock* begin;
|
||||
llvm::BasicBlock* end;
|
||||
IRBuilder<> builder;
|
||||
|
||||
IRScope();
|
||||
IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e);
|
||||
|
||||
const IRScope& operator=(const IRScope& rhs);
|
||||
|
||||
#if DMDV2
|
||||
// list of variables needing destruction
|
||||
std::vector<VarDeclaration*> varsInScope;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct IRBuilderHelper
|
||||
{
|
||||
IRState* state;
|
||||
IRBuilder<>* operator->();
|
||||
};
|
||||
|
||||
struct IRAsmStmt
|
||||
{
|
||||
IRAsmStmt()
|
||||
: isBranchToLabel(NULL) {}
|
||||
|
||||
std::string code;
|
||||
std::string out_c;
|
||||
std::string in_c;
|
||||
std::vector<LLValue*> out;
|
||||
std::vector<LLValue*> in;
|
||||
|
||||
// if this is nonzero, it contains the target label
|
||||
Identifier* isBranchToLabel;
|
||||
};
|
||||
|
||||
struct IRAsmBlock
|
||||
{
|
||||
std::deque<IRAsmStmt*> s;
|
||||
std::set<std::string> clobs;
|
||||
size_t outputcount;
|
||||
|
||||
// stores the labels within the asm block
|
||||
std::vector<Identifier*> internalLabels;
|
||||
|
||||
AsmBlockStatement* asmBlock;
|
||||
LLType* retty;
|
||||
unsigned retn;
|
||||
bool retemu; // emulate abi ret with a temporary
|
||||
LLValue* (*retfixup)(IRBuilderHelper b, LLValue* orig); // Modifies retval
|
||||
|
||||
IRAsmBlock(AsmBlockStatement* b)
|
||||
: outputcount(0), asmBlock(b), retty(NULL), retn(0), retemu(false),
|
||||
retfixup(NULL)
|
||||
{}
|
||||
};
|
||||
|
||||
// represents the module
|
||||
struct IRState
|
||||
{
|
||||
IRState(llvm::Module* m);
|
||||
|
||||
// module
|
||||
Module* dmodule;
|
||||
llvm::Module* module;
|
||||
|
||||
// interface info type, used in DtoInterfaceInfoType
|
||||
LLStructType* interfaceInfoType;
|
||||
LLStructType* mutexType;
|
||||
LLStructType* moduleRefType;
|
||||
|
||||
// helper to get the LLVMContext of the module
|
||||
llvm::LLVMContext& context() const { return module->getContext(); }
|
||||
|
||||
// functions
|
||||
typedef std::vector<IrFunction*> FunctionVector;
|
||||
FunctionVector functions;
|
||||
IrFunction* func();
|
||||
|
||||
llvm::Function* topfunc();
|
||||
TypeFunction* topfunctype();
|
||||
llvm::Instruction* topallocapoint();
|
||||
|
||||
// structs
|
||||
typedef std::vector<IrStruct*> StructVector;
|
||||
StructVector structs;
|
||||
IrStruct* topstruct();
|
||||
|
||||
// D main function
|
||||
bool emitMain;
|
||||
llvm::Function* mainFunc;
|
||||
|
||||
// basic block scopes
|
||||
std::vector<IRScope> scopes;
|
||||
IRScope& scope();
|
||||
#if DMDV2
|
||||
std::vector<VarDeclaration*> &varsInScope() { return scope().varsInScope; }
|
||||
#endif
|
||||
llvm::BasicBlock* scopebb();
|
||||
llvm::BasicBlock* scopeend();
|
||||
bool scopereturned();
|
||||
|
||||
// create a call or invoke, depending on the landing pad info
|
||||
// the template function is defined further down in this file
|
||||
template <typename T>
|
||||
llvm::CallSite CreateCallOrInvoke(LLValue* Callee, const T& args, const char* Name="");
|
||||
llvm::CallSite CreateCallOrInvoke(LLValue* Callee, const char* Name="");
|
||||
llvm::CallSite CreateCallOrInvoke(LLValue* Callee, LLValue* Arg1, const char* Name="");
|
||||
llvm::CallSite CreateCallOrInvoke2(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, const char* Name="");
|
||||
llvm::CallSite CreateCallOrInvoke3(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, LLValue* Arg3, const char* Name="");
|
||||
llvm::CallSite CreateCallOrInvoke4(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, LLValue* Arg3, LLValue* Arg4, const char* Name="");
|
||||
|
||||
// this holds the array being indexed or sliced so $ will work
|
||||
// might be a better way but it works. problem is I only get a
|
||||
// VarDeclaration for __dollar, but I can't see how to get the
|
||||
// array pointer from this :(
|
||||
std::vector<DValue*> arrays;
|
||||
|
||||
// builder helper
|
||||
IRBuilderHelper ir;
|
||||
|
||||
// debug info helper
|
||||
llvm::DIBuilder dibuilder;
|
||||
|
||||
// static ctors/dtors/unittests
|
||||
typedef std::list<FuncDeclaration*> FuncDeclList;
|
||||
typedef std::list<VarDeclaration*> GatesList;
|
||||
FuncDeclList ctors;
|
||||
FuncDeclList dtors;
|
||||
#if DMDV2
|
||||
FuncDeclList sharedCtors;
|
||||
FuncDeclList sharedDtors;
|
||||
GatesList gates;
|
||||
GatesList sharedGates;
|
||||
#endif
|
||||
FuncDeclList unitTests;
|
||||
|
||||
// all template instances that had members emitted
|
||||
// currently only filled for singleobj
|
||||
// used to make sure the complete template instance gets emitted in the
|
||||
// first file that touches a member, see #318
|
||||
typedef std::set<TemplateInstance*> TemplateInstanceSet;
|
||||
TemplateInstanceSet seenTemplateInstances;
|
||||
|
||||
// for inline asm
|
||||
IRAsmBlock* asmBlock;
|
||||
std::ostringstream nakedAsm;
|
||||
|
||||
// 'used' array solely for keeping a reference to globals
|
||||
std::vector<LLConstant*> usedArray;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
llvm::CallSite IRState::CreateCallOrInvoke(LLValue* Callee, const T &args, const char* Name)
|
||||
{
|
||||
llvm::BasicBlock* pad = func()->gen->landingPad;
|
||||
if(pad)
|
||||
{
|
||||
// intrinsics don't support invoking and 'nounwind' functions don't need it.
|
||||
LLFunction* funcval = llvm::dyn_cast<LLFunction>(Callee);
|
||||
if (funcval && (funcval->isIntrinsic() || funcval->doesNotThrow()))
|
||||
{
|
||||
llvm::CallInst* call = ir->CreateCall(Callee, args, Name);
|
||||
call->setAttributes(funcval->getAttributes());
|
||||
return call;
|
||||
}
|
||||
|
||||
llvm::BasicBlock* postinvoke = llvm::BasicBlock::Create(gIR->context(), "postinvoke", topfunc(), scopeend());
|
||||
llvm::InvokeInst* invoke = ir->CreateInvoke(Callee, postinvoke, pad, args, Name);
|
||||
if (LLFunction* fn = llvm::dyn_cast<LLFunction>(Callee))
|
||||
invoke->setAttributes(fn->getAttributes());
|
||||
scope() = IRScope(postinvoke, scopeend());
|
||||
return invoke;
|
||||
}
|
||||
else
|
||||
{
|
||||
llvm::CallInst* call = ir->CreateCall(Callee, args, Name);
|
||||
if (LLFunction* fn = llvm::dyn_cast<LLFunction>(Callee))
|
||||
call->setAttributes(fn->getAttributes());
|
||||
return call;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // LDC_GEN_IRSTATE_H
|
||||
#ifndef LDC_GEN_IRSTATE_H
|
||||
#define LDC_GEN_IRSTATE_H
|
||||
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <sstream>
|
||||
|
||||
#include "root.h"
|
||||
#include "aggregate.h"
|
||||
|
||||
#include "ir/irfunction.h"
|
||||
#include "ir/irstruct.h"
|
||||
#include "ir/irvar.h"
|
||||
|
||||
#if LDC_LLVM_VER >= 302
|
||||
#include "llvm/DIBuilder.h"
|
||||
#else
|
||||
#include "llvm/Analysis/DIBuilder.h"
|
||||
#endif
|
||||
#include "llvm/Support/CallSite.h"
|
||||
|
||||
namespace llvm {
|
||||
class LLVMContext;
|
||||
class TargetMachine;
|
||||
}
|
||||
|
||||
// global ir state for current module
|
||||
struct IRState;
|
||||
struct TargetABI;
|
||||
|
||||
extern IRState* gIR;
|
||||
extern llvm::TargetMachine* gTargetMachine;
|
||||
extern const llvm::TargetData* gTargetData;
|
||||
extern TargetABI* gABI;
|
||||
|
||||
struct TypeFunction;
|
||||
struct TypeStruct;
|
||||
struct ClassDeclaration;
|
||||
struct FuncDeclaration;
|
||||
struct Module;
|
||||
struct TypeStruct;
|
||||
struct BaseClass;
|
||||
struct AnonDeclaration;
|
||||
|
||||
struct IrModule;
|
||||
|
||||
// represents a scope
|
||||
struct IRScope
|
||||
{
|
||||
llvm::BasicBlock* begin;
|
||||
llvm::BasicBlock* end;
|
||||
IRBuilder<> builder;
|
||||
|
||||
IRScope();
|
||||
IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e);
|
||||
|
||||
const IRScope& operator=(const IRScope& rhs);
|
||||
|
||||
#if DMDV2
|
||||
// list of variables needing destruction
|
||||
std::vector<VarDeclaration*> varsInScope;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct IRBuilderHelper
|
||||
{
|
||||
IRState* state;
|
||||
IRBuilder<>* operator->();
|
||||
};
|
||||
|
||||
struct IRAsmStmt
|
||||
{
|
||||
IRAsmStmt()
|
||||
: isBranchToLabel(NULL) {}
|
||||
|
||||
std::string code;
|
||||
std::string out_c;
|
||||
std::string in_c;
|
||||
std::vector<LLValue*> out;
|
||||
std::vector<LLValue*> in;
|
||||
|
||||
// if this is nonzero, it contains the target label
|
||||
Identifier* isBranchToLabel;
|
||||
};
|
||||
|
||||
struct IRAsmBlock
|
||||
{
|
||||
std::deque<IRAsmStmt*> s;
|
||||
std::set<std::string> clobs;
|
||||
size_t outputcount;
|
||||
|
||||
// stores the labels within the asm block
|
||||
std::vector<Identifier*> internalLabels;
|
||||
|
||||
AsmBlockStatement* asmBlock;
|
||||
LLType* retty;
|
||||
unsigned retn;
|
||||
bool retemu; // emulate abi ret with a temporary
|
||||
LLValue* (*retfixup)(IRBuilderHelper b, LLValue* orig); // Modifies retval
|
||||
|
||||
IRAsmBlock(AsmBlockStatement* b)
|
||||
: outputcount(0), asmBlock(b), retty(NULL), retn(0), retemu(false),
|
||||
retfixup(NULL)
|
||||
{}
|
||||
};
|
||||
|
||||
// represents the module
|
||||
struct IRState
|
||||
{
|
||||
IRState(llvm::Module* m);
|
||||
|
||||
// module
|
||||
Module* dmodule;
|
||||
llvm::Module* module;
|
||||
|
||||
// interface info type, used in DtoInterfaceInfoType
|
||||
LLStructType* interfaceInfoType;
|
||||
LLStructType* mutexType;
|
||||
LLStructType* moduleRefType;
|
||||
|
||||
// helper to get the LLVMContext of the module
|
||||
llvm::LLVMContext& context() const { return module->getContext(); }
|
||||
|
||||
// functions
|
||||
typedef std::vector<IrFunction*> FunctionVector;
|
||||
FunctionVector functions;
|
||||
IrFunction* func();
|
||||
|
||||
llvm::Function* topfunc();
|
||||
TypeFunction* topfunctype();
|
||||
llvm::Instruction* topallocapoint();
|
||||
|
||||
// structs
|
||||
typedef std::vector<IrStruct*> StructVector;
|
||||
StructVector structs;
|
||||
IrStruct* topstruct();
|
||||
|
||||
// D main function
|
||||
bool emitMain;
|
||||
llvm::Function* mainFunc;
|
||||
|
||||
// basic block scopes
|
||||
std::vector<IRScope> scopes;
|
||||
IRScope& scope();
|
||||
#if DMDV2
|
||||
std::vector<VarDeclaration*> &varsInScope() { return scope().varsInScope; }
|
||||
#endif
|
||||
llvm::BasicBlock* scopebb();
|
||||
llvm::BasicBlock* scopeend();
|
||||
bool scopereturned();
|
||||
|
||||
// create a call or invoke, depending on the landing pad info
|
||||
// the template function is defined further down in this file
|
||||
template <typename T>
|
||||
llvm::CallSite CreateCallOrInvoke(LLValue* Callee, const T& args, const char* Name="");
|
||||
llvm::CallSite CreateCallOrInvoke(LLValue* Callee, const char* Name="");
|
||||
llvm::CallSite CreateCallOrInvoke(LLValue* Callee, LLValue* Arg1, const char* Name="");
|
||||
llvm::CallSite CreateCallOrInvoke2(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, const char* Name="");
|
||||
llvm::CallSite CreateCallOrInvoke3(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, LLValue* Arg3, const char* Name="");
|
||||
llvm::CallSite CreateCallOrInvoke4(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, LLValue* Arg3, LLValue* Arg4, const char* Name="");
|
||||
|
||||
// this holds the array being indexed or sliced so $ will work
|
||||
// might be a better way but it works. problem is I only get a
|
||||
// VarDeclaration for __dollar, but I can't see how to get the
|
||||
// array pointer from this :(
|
||||
std::vector<DValue*> arrays;
|
||||
|
||||
// builder helper
|
||||
IRBuilderHelper ir;
|
||||
|
||||
// debug info helper
|
||||
llvm::DIBuilder dibuilder;
|
||||
|
||||
// static ctors/dtors/unittests
|
||||
typedef std::list<FuncDeclaration*> FuncDeclList;
|
||||
typedef std::list<VarDeclaration*> GatesList;
|
||||
FuncDeclList ctors;
|
||||
FuncDeclList dtors;
|
||||
#if DMDV2
|
||||
FuncDeclList sharedCtors;
|
||||
FuncDeclList sharedDtors;
|
||||
GatesList gates;
|
||||
GatesList sharedGates;
|
||||
#endif
|
||||
FuncDeclList unitTests;
|
||||
|
||||
// all template instances that had members emitted
|
||||
// currently only filled for singleobj
|
||||
// used to make sure the complete template instance gets emitted in the
|
||||
// first file that touches a member, see #318
|
||||
typedef std::set<TemplateInstance*> TemplateInstanceSet;
|
||||
TemplateInstanceSet seenTemplateInstances;
|
||||
|
||||
// for inline asm
|
||||
IRAsmBlock* asmBlock;
|
||||
std::ostringstream nakedAsm;
|
||||
|
||||
// 'used' array solely for keeping a reference to globals
|
||||
std::vector<LLConstant*> usedArray;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
llvm::CallSite IRState::CreateCallOrInvoke(LLValue* Callee, const T &args, const char* Name)
|
||||
{
|
||||
llvm::BasicBlock* pad = func()->gen->landingPad;
|
||||
if(pad)
|
||||
{
|
||||
// intrinsics don't support invoking and 'nounwind' functions don't need it.
|
||||
LLFunction* funcval = llvm::dyn_cast<LLFunction>(Callee);
|
||||
if (funcval && (funcval->isIntrinsic() || funcval->doesNotThrow()))
|
||||
{
|
||||
llvm::CallInst* call = ir->CreateCall(Callee, args, Name);
|
||||
call->setAttributes(funcval->getAttributes());
|
||||
return call;
|
||||
}
|
||||
|
||||
llvm::BasicBlock* postinvoke = llvm::BasicBlock::Create(gIR->context(), "postinvoke", topfunc(), scopeend());
|
||||
llvm::InvokeInst* invoke = ir->CreateInvoke(Callee, postinvoke, pad, args, Name);
|
||||
if (LLFunction* fn = llvm::dyn_cast<LLFunction>(Callee))
|
||||
invoke->setAttributes(fn->getAttributes());
|
||||
scope() = IRScope(postinvoke, scopeend());
|
||||
return invoke;
|
||||
}
|
||||
else
|
||||
{
|
||||
llvm::CallInst* call = ir->CreateCall(Callee, args, Name);
|
||||
if (LLFunction* fn = llvm::dyn_cast<LLFunction>(Callee))
|
||||
call->setAttributes(fn->getAttributes());
|
||||
return call;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // LDC_GEN_IRSTATE_H
|
||||
|
||||
1848
gen/typinf.cpp
1848
gen/typinf.cpp
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user