comparison gen/toir.c @ 57:a9d29e9f1fed trunk

[svn r61] Added support for D-style variadic functions :)
author lindquist
date Thu, 25 Oct 2007 02:39:53 +0200
parents 0ccfae271c45
children 2c3cd3596187
comparison
equal deleted inserted replaced
56:3a784f7790d6 57:a9d29e9f1fed
108 elem* e = new elem; 108 elem* e = new elem;
109 109
110 assert(var); 110 assert(var);
111 if (VarDeclaration* vd = var->isVarDeclaration()) 111 if (VarDeclaration* vd = var->isVarDeclaration())
112 { 112 {
113 Logger::println("VarDeclaration"); 113 Logger::println("VarDeclaration %s", vd->toChars());
114 114
115 if (vd->nestedref) { 115 if (vd->nestedref) {
116 Logger::println("has nested ref"); 116 Logger::println("has nested ref");
117 }
118
119 // _arguments
120 if (vd->ident == Id::_arguments)
121 {
122 vd->llvmValue = p->func().decl->llvmArguments;
123 assert(vd->llvmValue);
124 e->mem = vd->llvmValue;
125 e->type = elem::VAR;
126 return e;
127 }
128 // _argptr
129 else if (vd->ident == Id::_argptr)
130 {
131 vd->llvmValue = p->func().decl->llvmArgPtr;
132 assert(vd->llvmValue);
133 e->mem = vd->llvmValue;
134 e->type = elem::VAR;
135 return e;
117 } 136 }
118 137
119 // needed to take care of forward references of global variables 138 // needed to take care of forward references of global variables
120 if (!vd->llvmTouched && vd->isDataseg()) 139 if (!vd->llvmTouched && vd->isDataseg())
121 vd->toObjFile(); 140 vd->toObjFile();
145 { 164 {
146 assert(0); 165 assert(0);
147 } 166 }
148 // global forward ref 167 // global forward ref
149 else { 168 else {
150 Logger::println("unsupported: %s\n", vd->toChars()); 169 Logger::println("unsupported magic: %s\n", vd->toChars());
151 assert(0 && "only magic supported is typeinfo"); 170 assert(0 && "only magic supported is $, _arguments, _argptr");
152 } 171 }
153 return e; 172 return e;
154 } 173 }
155 174
156 // function parameter 175 // function parameter
445 464
446 ////////////////////////////////////////////////////////////////////////////////////////// 465 //////////////////////////////////////////////////////////////////////////////////////////
447 466
448 elem* AssignExp::toElem(IRState* p) 467 elem* AssignExp::toElem(IRState* p)
449 { 468 {
450 Logger::print("AssignExp::toElem: %s | %s = %s\n", toChars(), e1->type->toChars(), e2->type->toChars()); 469 Logger::print("AssignExp::toElem: %s | %s = %s\n", toChars(), e1->type->toChars(), e2->type ? e2->type->toChars() : 0);
451 LOG_SCOPE; 470 LOG_SCOPE;
452 471
453 p->exps.push_back(IRExp(e1,e2,NULL)); 472 p->exps.push_back(IRExp(e1,e2,NULL));
454 473
455 elem* l = e1->toElem(p); 474 elem* l = e1->toElem(p);
1044 size_t n = arguments->dim; 1063 size_t n = arguments->dim;
1045 if (fn->funcdecl && fn->funcdecl->llvmInternal == LLVMva_start) 1064 if (fn->funcdecl && fn->funcdecl->llvmInternal == LLVMva_start)
1046 n = 1; 1065 n = 1;
1047 if (fn->arg || delegateCall) n++; 1066 if (fn->arg || delegateCall) n++;
1048 if (retinptr) n++; 1067 if (retinptr) n++;
1068 if (tf->linkage == LINKd && tf->varargs == 1) n+=2;
1049 1069
1050 llvm::Value* funcval = fn->getValue(); 1070 llvm::Value* funcval = fn->getValue();
1051 assert(funcval != 0); 1071 assert(funcval != 0);
1052 std::vector<llvm::Value*> llargs(n, 0); 1072 std::vector<llvm::Value*> llargs(n, 0);
1053 1073
1088 //Logger::cout() << "Function LLVM type: " << *llfnty << '\n'; 1108 //Logger::cout() << "Function LLVM type: " << *llfnty << '\n';
1089 1109
1090 // argument handling 1110 // argument handling
1091 llvm::FunctionType::param_iterator argiter = llfnty->param_begin(); 1111 llvm::FunctionType::param_iterator argiter = llfnty->param_begin();
1092 int j = 0; 1112 int j = 0;
1093
1094 Logger::println("hidden struct return");
1095 1113
1096 IRExp* topexp = p->topexp(); 1114 IRExp* topexp = p->topexp();
1097 1115
1098 // hidden struct return arguments 1116 // hidden struct return arguments
1099 if (retinptr) { 1117 if (retinptr) {
1116 } 1134 }
1117 else { 1135 else {
1118 e->type = elem::VAL; 1136 e->type = elem::VAL;
1119 } 1137 }
1120 1138
1121 Logger::println("this arguments");
1122
1123 // this arguments 1139 // this arguments
1124 if (fn->arg) { 1140 if (fn->arg) {
1125 Logger::println("This Call"); 1141 Logger::println("This Call");
1126 if (fn->arg->getType() != argiter->get()) { 1142 if (fn->arg->getType() != argiter->get()) {
1127 //Logger::cout() << *fn->thisparam << '|' << *argiter->get() << '\n'; 1143 //Logger::cout() << *fn->thisparam << '|' << *argiter->get() << '\n';
1139 llvm::Value* contextptr = LLVM_DtoGEP(fn->mem,zero,zero,"tmp",p->scopebb()); 1155 llvm::Value* contextptr = LLVM_DtoGEP(fn->mem,zero,zero,"tmp",p->scopebb());
1140 llargs[j] = new llvm::LoadInst(contextptr,"tmp",p->scopebb()); 1156 llargs[j] = new llvm::LoadInst(contextptr,"tmp",p->scopebb());
1141 ++j; 1157 ++j;
1142 ++argiter; 1158 ++argiter;
1143 } 1159 }
1144
1145 Logger::println("regular arguments");
1146 1160
1147 // va arg function special argument passing 1161 // va arg function special argument passing
1148 if (va_magic) { 1162 if (va_magic) {
1149 size_t n = va_intrinsic ? arguments->dim : 1; 1163 size_t n = va_intrinsic ? arguments->dim : 1;
1150 for (int i=0; i<n; i++,j++) 1164 for (int i=0; i<n; i++,j++)
1157 delete expelem; 1171 delete expelem;
1158 } 1172 }
1159 } 1173 }
1160 // regular arguments 1174 // regular arguments
1161 else { 1175 else {
1162 for (int i=0; i<arguments->dim; i++,j++) 1176 if (tf->linkage == LINKd && tf->varargs == 1)
1163 { 1177 {
1164 Argument* fnarg = Argument::getNth(tf->parameters, i); 1178 Logger::println("doing d-style variadic arguments");
1165 llargs[j] = LLVM_DtoArgument(llfnty->getParamType(j), fnarg, (Expression*)arguments->data[i]); 1179
1180 std::vector<const llvm::Type*> vtypes;
1181 std::vector<llvm::Value*> vvalues;
1182 std::vector<llvm::Value*> vtypeinfos;
1183
1184 for (int i=0; i<arguments->dim; i++) {
1185 Argument* fnarg = Argument::getNth(tf->parameters, i);
1186 Expression* argexp = (Expression*)arguments->data[i];
1187 vvalues.push_back(LLVM_DtoArgument(NULL, fnarg, argexp));
1188 vtypes.push_back(vvalues.back()->getType());
1189
1190 TypeInfoDeclaration* tidecl = argexp->type->getTypeInfoDeclaration();
1191 tidecl->toObjFile();
1192 assert(tidecl->llvmValue);
1193 vtypeinfos.push_back(tidecl->llvmValue);
1194 }
1195
1196 const llvm::StructType* vtype = llvm::StructType::get(vtypes);
1197 llvm::Value* mem = new llvm::AllocaInst(vtype,"_argptr_storage",p->topallocapoint());
1198 for (unsigned i=0; i<vtype->getNumElements(); ++i)
1199 p->ir->CreateStore(vvalues[i], LLVM_DtoGEPi(mem,0,i,"tmp"));
1200
1201 //llvm::Constant* typeinfoparam = llvm::ConstantPointerNull::get(llvm::cast<llvm::PointerType>(llfnty->getParamType(j)));
1202 assert(Type::typeinfo->llvmInitZ);
1203 const llvm::Type* typeinfotype = llvm::PointerType::get(Type::typeinfo->llvmInitZ->getType());
1204 Logger::cout() << "typeinfo ptr type: " << *typeinfotype << '\n';
1205 const llvm::ArrayType* typeinfoarraytype = llvm::ArrayType::get(typeinfotype,vtype->getNumElements());
1206 llvm::Value* typeinfomem = new llvm::AllocaInst(typeinfoarraytype,"_arguments_storage",p->topallocapoint());
1207 for (unsigned i=0; i<vtype->getNumElements(); ++i) {
1208 llvm::Value* v = p->ir->CreateBitCast(vtypeinfos[i], typeinfotype, "tmp");
1209 p->ir->CreateStore(v, LLVM_DtoGEPi(typeinfomem,0,i,"tmp"));
1210 }
1211
1212 llvm::Value* typeinfoarrayparam = new llvm::AllocaInst(llfnty->getParamType(j)->getContainedType(0),"_arguments_array",p->topallocapoint());
1213 p->ir->CreateStore(LLVM_DtoConstSize_t(vtype->getNumElements()), LLVM_DtoGEPi(typeinfoarrayparam,0,0,"tmp"));
1214 llvm::Value* casttypeinfomem = p->ir->CreateBitCast(typeinfomem, llvm::PointerType::get(typeinfotype), "tmp");
1215 p->ir->CreateStore(casttypeinfomem, LLVM_DtoGEPi(typeinfoarrayparam,0,1,"tmp"));
1216
1217 llargs[j] = typeinfoarrayparam;;
1218 j++;
1219 llargs[j] = p->ir->CreateBitCast(mem, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp");
1220 j++;
1221 llargs.resize(2);
1222 }
1223 else {
1224 Logger::println("doing normal arguments");
1225 for (int i=0; i<arguments->dim; i++,j++) {
1226 Argument* fnarg = Argument::getNth(tf->parameters, i);
1227 llargs[j] = LLVM_DtoArgument(llfnty->getParamType(j), fnarg, (Expression*)arguments->data[i]);
1228 }
1229 Logger::println("%d params passed", n);
1230 for (int i=0; i<n; ++i) {
1231 Logger::cout() << *llargs[i] << '\n';
1232 }
1166 } 1233 }
1167 } 1234 }
1168 1235
1169 // void returns cannot not be named 1236 // void returns cannot not be named
1170 const char* varname = ""; 1237 const char* varname = "";
1171 if (llfnty->getReturnType() != llvm::Type::VoidTy) 1238 if (llfnty->getReturnType() != llvm::Type::VoidTy)
1172 varname = "tmp"; 1239 varname = "tmp";
1173
1174 Logger::println("%d params passed", n);
1175 for (int i=0; i<n; ++i)
1176 {
1177 Logger::cout() << *llargs[i] << '\n';
1178 }
1179 1240
1180 Logger::cout() << "Calling: " << *funcval->getType() << '\n'; 1241 Logger::cout() << "Calling: " << *funcval->getType() << '\n';
1181 1242
1182 // call the function 1243 // call the function
1183 llvm::CallInst* call = new llvm::CallInst(funcval, llargs.begin(), llargs.end(), varname, p->scopebb()); 1244 llvm::CallInst* call = new llvm::CallInst(funcval, llargs.begin(), llargs.end(), varname, p->scopebb());
1340 } 1401 }
1341 } 1402 }
1342 else if (fromtype->ty == Tpointer) { 1403 else if (fromtype->ty == Tpointer) {
1343 if (totype->ty == Tpointer || totype->ty == Tclass) { 1404 if (totype->ty == Tpointer || totype->ty == Tclass) {
1344 llvm::Value* src = u->getValue(); 1405 llvm::Value* src = u->getValue();
1345 //Logger::cout() << *src << '|' << *totype << '\n'; 1406 Logger::cout() << *src << '|' << *tolltype << '\n';
1346 e->val = new llvm::BitCastInst(src, tolltype, "tmp", p->scopebb()); 1407 e->val = new llvm::BitCastInst(src, tolltype, "tmp", p->scopebb());
1347 } 1408 }
1348 else if (totype->isintegral()) { 1409 else if (totype->isintegral()) {
1349 e->val = new llvm::PtrToIntInst(u->getValue(), tolltype, "tmp", p->scopebb()); 1410 e->val = new llvm::PtrToIntInst(u->getValue(), tolltype, "tmp", p->scopebb());
1350 } 1411 }