| 1 |
#include "gen/llvm.h" |
|---|
| 2 |
|
|---|
| 3 |
#include "aggregate.h" |
|---|
| 4 |
#include "mtype.h" |
|---|
| 5 |
|
|---|
| 6 |
#include "gen/arrays.h" |
|---|
| 7 |
#include "gen/irstate.h" |
|---|
| 8 |
#include "gen/linkage.h" |
|---|
| 9 |
#include "gen/llvmhelpers.h" |
|---|
| 10 |
#include "gen/rttibuilder.h" |
|---|
| 11 |
#include "gen/tollvm.h" |
|---|
| 12 |
|
|---|
| 13 |
#include "ir/irstruct.h" |
|---|
| 14 |
|
|---|
| 15 |
RTTIBuilder::RTTIBuilder(ClassDeclaration* base_class) |
|---|
| 16 |
{ |
|---|
| 17 |
// make sure the base typeinfo class has been processed |
|---|
| 18 |
base_class->codegen(Type::sir); |
|---|
| 19 |
|
|---|
| 20 |
base = base_class; |
|---|
| 21 |
basetype = (TypeClass*)base->type; |
|---|
| 22 |
|
|---|
| 23 |
baseir = base->ir.irStruct; |
|---|
| 24 |
assert(baseir && "no IrStruct for TypeInfo base class"); |
|---|
| 25 |
|
|---|
| 26 |
// just start with adding the vtbl |
|---|
| 27 |
inits.push_back(baseir->getVtblSymbol()); |
|---|
| 28 |
// and monitor |
|---|
| 29 |
push_null_vp(); |
|---|
| 30 |
} |
|---|
| 31 |
|
|---|
| 32 |
void RTTIBuilder::push(llvm::Constant* C) |
|---|
| 33 |
{ |
|---|
| 34 |
inits.push_back(C); |
|---|
| 35 |
} |
|---|
| 36 |
|
|---|
| 37 |
void RTTIBuilder::push_null(Type* T) |
|---|
| 38 |
{ |
|---|
| 39 |
inits.push_back(getNullValue(DtoType(T))); |
|---|
| 40 |
} |
|---|
| 41 |
|
|---|
| 42 |
void RTTIBuilder::push_null_vp() |
|---|
| 43 |
{ |
|---|
| 44 |
inits.push_back(getNullValue(getVoidPtrType())); |
|---|
| 45 |
} |
|---|
| 46 |
|
|---|
| 47 |
void RTTIBuilder::push_typeinfo(Type* t) |
|---|
| 48 |
{ |
|---|
| 49 |
inits.push_back(DtoTypeInfoOf(t, true)); |
|---|
| 50 |
} |
|---|
| 51 |
|
|---|
| 52 |
void RTTIBuilder::push_classinfo(ClassDeclaration* cd) |
|---|
| 53 |
{ |
|---|
| 54 |
inits.push_back(cd->ir.irStruct->getClassInfoSymbol()); |
|---|
| 55 |
} |
|---|
| 56 |
|
|---|
| 57 |
void RTTIBuilder::push_string(const char* str) |
|---|
| 58 |
{ |
|---|
| 59 |
inits.push_back(DtoConstString(str)); |
|---|
| 60 |
} |
|---|
| 61 |
|
|---|
| 62 |
void RTTIBuilder::push_null_void_array() |
|---|
| 63 |
{ |
|---|
| 64 |
const llvm::Type* T = DtoType(Type::tvoid->arrayOf()); |
|---|
| 65 |
inits.push_back(getNullValue(T)); |
|---|
| 66 |
} |
|---|
| 67 |
|
|---|
| 68 |
void RTTIBuilder::push_void_array(uint64_t dim, llvm::Constant* ptr) |
|---|
| 69 |
{ |
|---|
| 70 |
inits.push_back(DtoConstSlice( |
|---|
| 71 |
DtoConstSize_t(dim), |
|---|
| 72 |
DtoBitCast(ptr, getVoidPtrType()) |
|---|
| 73 |
)); |
|---|
| 74 |
} |
|---|
| 75 |
|
|---|
| 76 |
void RTTIBuilder::push_void_array(llvm::Constant* CI, Type* valtype, Dsymbol* mangle_sym) |
|---|
| 77 |
{ |
|---|
| 78 |
std::string initname(mangle_sym->mangle()); |
|---|
| 79 |
initname.append(".rtti.voidarr.data"); |
|---|
| 80 |
|
|---|
| 81 |
LLGlobalVariable* G = new llvm::GlobalVariable( |
|---|
| 82 |
*gIR->module, CI->getType(), true, TYPEINFO_LINKAGE_TYPE, CI, initname); |
|---|
| 83 |
G->setAlignment(valtype->alignsize()); |
|---|
| 84 |
|
|---|
| 85 |
push_void_array(getTypePaddedSize(CI->getType()), G); |
|---|
| 86 |
} |
|---|
| 87 |
|
|---|
| 88 |
void RTTIBuilder::push_array(llvm::Constant * CI, uint64_t dim, Type* valtype, Dsymbol * mangle_sym) |
|---|
| 89 |
{ |
|---|
| 90 |
std::string tmpStr(valtype->arrayOf()->toChars()); |
|---|
| 91 |
tmpStr.erase( remove( tmpStr.begin(), tmpStr.end(), '[' ), tmpStr.end() ); |
|---|
| 92 |
tmpStr.erase( remove( tmpStr.begin(), tmpStr.end(), ']' ), tmpStr.end() ); |
|---|
| 93 |
tmpStr.append("arr"); |
|---|
| 94 |
|
|---|
| 95 |
std::string initname(mangle_sym?mangle_sym->mangle():".ldc"); |
|---|
| 96 |
initname.append(".rtti."); |
|---|
| 97 |
initname.append(tmpStr); |
|---|
| 98 |
initname.append(".data"); |
|---|
| 99 |
|
|---|
| 100 |
LLGlobalVariable* G = new llvm::GlobalVariable( |
|---|
| 101 |
*gIR->module, CI->getType(), true, TYPEINFO_LINKAGE_TYPE, CI, initname); |
|---|
| 102 |
G->setAlignment(valtype->alignsize()); |
|---|
| 103 |
|
|---|
| 104 |
push_array(dim, DtoBitCast(G, DtoType(valtype->pointerTo()))); |
|---|
| 105 |
} |
|---|
| 106 |
|
|---|
| 107 |
void RTTIBuilder::push_array(uint64_t dim, llvm::Constant * ptr) |
|---|
| 108 |
{ |
|---|
| 109 |
inits.push_back(DtoConstSlice(DtoConstSize_t(dim), ptr)); |
|---|
| 110 |
} |
|---|
| 111 |
|
|---|
| 112 |
void RTTIBuilder::push_uint(unsigned u) |
|---|
| 113 |
{ |
|---|
| 114 |
inits.push_back(DtoConstUint(u)); |
|---|
| 115 |
} |
|---|
| 116 |
|
|---|
| 117 |
void RTTIBuilder::push_size(uint64_t s) |
|---|
| 118 |
{ |
|---|
| 119 |
inits.push_back(DtoConstSize_t(s)); |
|---|
| 120 |
} |
|---|
| 121 |
|
|---|
| 122 |
void RTTIBuilder::push_funcptr(FuncDeclaration* fd, Type* castto) |
|---|
| 123 |
{ |
|---|
| 124 |
if (fd) |
|---|
| 125 |
{ |
|---|
| 126 |
fd->codegen(Type::sir); |
|---|
| 127 |
LLConstant* F = fd->ir.irFunc->func; |
|---|
| 128 |
if (castto) |
|---|
| 129 |
F = DtoBitCast(F, DtoType(castto)); |
|---|
| 130 |
inits.push_back(F); |
|---|
| 131 |
} |
|---|
| 132 |
else if (castto) |
|---|
| 133 |
{ |
|---|
| 134 |
push_null(castto); |
|---|
| 135 |
} |
|---|
| 136 |
else |
|---|
| 137 |
{ |
|---|
| 138 |
push_null_vp(); |
|---|
| 139 |
} |
|---|
| 140 |
} |
|---|
| 141 |
|
|---|
| 142 |
void RTTIBuilder::finalize(IrGlobal* tid) |
|---|
| 143 |
{ |
|---|
| 144 |
// create the inititalizer |
|---|
| 145 |
LLConstant* tiInit = LLConstantStruct::get(gIR->context(), &inits[0], inits.size(), false); |
|---|
| 146 |
|
|---|
| 147 |
// refine global type |
|---|
| 148 |
llvm::cast<llvm::OpaqueType>(tid->type.get())->refineAbstractTypeTo(tiInit->getType()); |
|---|
| 149 |
|
|---|
| 150 |
// set the initializer |
|---|
| 151 |
isaGlobalVar(tid->value)->setInitializer(tiInit); |
|---|
| 152 |
} |
|---|
| 153 |
|
|---|
| 154 |
LLConstant* RTTIBuilder::get_constant() |
|---|
| 155 |
{ |
|---|
| 156 |
// just return the inititalizer |
|---|
| 157 |
return LLConstantStruct::get(gIR->context(), &inits[0], inits.size(), false); |
|---|
| 158 |
} |
|---|