comparison gen/functions.cpp @ 445:cc40db549aea

Changed the handling of variadic intrinsics a bit. Removed the -fp80 option and made real be 80bit floats on X86, this is what the D spec really says it should be and fixes a bunch of issues. Changed the handling of parameter attributes to a bit more generalized approach. Added sext/zext attributes for byte/short/ubyte/ushort parameters, fixes #60 . Parameter attribs now properly set for intrinsic calls if necessary. Made the tango.math.Math patch less intrusive. Fixed/added some mini tests.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Fri, 01 Aug 2008 17:59:58 +0200
parents 44f08170f4ef
children 7a67dedbf933
comparison
equal deleted inserted replaced
444:f2b5f86348ef 445:cc40db549aea
1 #include "gen/llvm.h" 1 #include "gen/llvm.h"
2 #include "llvm/Support/CFG.h" 2 #include "llvm/Support/CFG.h"
3 #include "llvm/Intrinsics.h"
3 4
4 #include "mtype.h" 5 #include "mtype.h"
5 #include "aggregate.h" 6 #include "aggregate.h"
6 #include "init.h" 7 #include "init.h"
7 #include "declaration.h" 8 #include "declaration.h"
60 paramvec.push_back(getPtrToType(arrArrTy)); 61 paramvec.push_back(getPtrToType(arrArrTy));
61 } 62 }
62 } 63 }
63 else{ 64 else{
64 assert(rt); 65 assert(rt);
65 Type* rtfin = DtoDType(rt);
66 if (DtoIsReturnedInArg(rt)) { 66 if (DtoIsReturnedInArg(rt)) {
67 rettype = getPtrToType(DtoType(rt)); 67 rettype = getPtrToType(DtoType(rt));
68 actualRettype = LLType::VoidTy; 68 actualRettype = LLType::VoidTy;
69 f->llvmRetInPtr = retinptr = true; 69 f->llvmRetInPtr = retinptr = true;
70 } 70 }
71 else { 71 else {
72 rettype = DtoType(rt); 72 rettype = DtoType(rt);
73 actualRettype = rettype; 73 actualRettype = rettype;
74 }
75
76 if (unsigned ea = DtoShouldExtend(rt))
77 {
78 f->llvmRetAttrs |= ea;
74 } 79 }
75 } 80 }
76 81
77 if (retinptr) { 82 if (retinptr) {
78 //Logger::cout() << "returning through pointer parameter: " << *rettype << '\n'; 83 //Logger::cout() << "returning through pointer parameter: " << *rettype << '\n';
101 // do nothing? 106 // do nothing?
102 } 107 }
103 108
104 size_t n = Argument::dim(f->parameters); 109 size_t n = Argument::dim(f->parameters);
105 110
106 int nbyval = 0;
107
108 for (int i=0; i < n; ++i) { 111 for (int i=0; i < n; ++i) {
109 Argument* arg = Argument::getNth(f->parameters, i); 112 Argument* arg = Argument::getNth(f->parameters, i);
110 // ensure scalar 113 // ensure scalar
111 Type* argT = DtoDType(arg->type); 114 Type* argT = DtoDType(arg->type);
112 assert(argT); 115 assert(argT);
115 118
116 const LLType* at = DtoType(argT); 119 const LLType* at = DtoType(argT);
117 if (isaStruct(at)) { 120 if (isaStruct(at)) {
118 Logger::println("struct param"); 121 Logger::println("struct param");
119 paramvec.push_back(getPtrToType(at)); 122 paramvec.push_back(getPtrToType(at));
120 arg->llvmByVal = !refOrOut; 123 if (!refOrOut)
124 arg->llvmAttrs |= llvm::ParamAttr::ByVal;
121 } 125 }
122 else if (isaArray(at)) { 126 else if (isaArray(at)) {
123 // static array are passed by reference 127 // static array are passed by reference
124 Logger::println("sarray param"); 128 Logger::println("sarray param");
125 assert(argT->ty == Tsarray); 129 assert(argT->ty == Tsarray);
135 Logger::println("by ref param"); 139 Logger::println("by ref param");
136 at = getPtrToType(at); 140 at = getPtrToType(at);
137 } 141 }
138 else { 142 else {
139 Logger::println("in param"); 143 Logger::println("in param");
144 if (unsigned ea = DtoShouldExtend(argT))
145 {
146 arg->llvmAttrs |= ea;
147 }
140 } 148 }
141 paramvec.push_back(at); 149 paramvec.push_back(at);
142 } 150 }
143 151
144 // handle lazy args 152 // handle lazy args
149 TypeDelegate *ltd = new TypeDelegate(ltf); 157 TypeDelegate *ltd = new TypeDelegate(ltf);
150 at = getPtrToType(DtoType(ltd)); 158 at = getPtrToType(DtoType(ltd));
151 Logger::cout() << "lazy updated to: " << *at << '\n'; 159 Logger::cout() << "lazy updated to: " << *at << '\n';
152 paramvec.back() = at; 160 paramvec.back() = at;
153 } 161 }
154
155 if (arg->llvmByVal)
156 nbyval++;
157 } 162 }
158 163
159 //warning("set %d byval args for type: %s", nbyval, f->toChars()); 164 //warning("set %d byval args for type: %s", nbyval, f->toChars());
160 165
161 // construct function type 166 // construct function type
178 if (fdecl->type->ir.type != 0) { 183 if (fdecl->type->ir.type != 0) {
179 return llvm::cast<llvm::FunctionType>(fdecl->type->ir.type->get()); 184 return llvm::cast<llvm::FunctionType>(fdecl->type->ir.type->get());
180 } 185 }
181 186
182 TypeFunction* f = (TypeFunction*)fdecl->type; 187 TypeFunction* f = (TypeFunction*)fdecl->type;
183 assert(f != 0); 188 const llvm::FunctionType* fty = 0;
184 189
185 const llvm::PointerType* i8pty = getPtrToType(LLType::Int8Ty); 190 if (fdecl->llvmInternal == LLVMva_start)
186 std::vector<const LLType*> args; 191 fty = GET_INTRINSIC_DECL(vastart)->getFunctionType();
187 192 else if (fdecl->llvmInternal == LLVMva_copy)
188 if (fdecl->llvmInternal == LLVMva_start) { 193 fty = GET_INTRINSIC_DECL(vacopy)->getFunctionType();
189 args.push_back(i8pty); 194 else if (fdecl->llvmInternal == LLVMva_end)
190 } 195 fty = GET_INTRINSIC_DECL(vaend)->getFunctionType();
191 else if (fdecl->llvmInternal == LLVMva_intrinsic) { 196 assert(fty);
192 size_t n = Argument::dim(f->parameters);
193 for (size_t i=0; i<n; ++i) {
194 args.push_back(i8pty);
195 }
196 }
197 else
198 assert(0);
199
200 const llvm::FunctionType* fty = llvm::FunctionType::get(LLType::VoidTy, args, false);
201 197
202 f->ir.type = new llvm::PATypeHolder(fty); 198 f->ir.type = new llvm::PATypeHolder(fty);
203
204 return fty; 199 return fty;
205 } 200 }
206 201
207 ////////////////////////////////////////////////////////////////////////////////////////// 202 //////////////////////////////////////////////////////////////////////////////////////////
208 203
209 const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl) 204 const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl)
210 { 205 {
211 if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) { 206 // handle for C vararg intrinsics
207 if (fdecl->isVaIntrinsic())
212 return DtoVaFunctionType(fdecl); 208 return DtoVaFunctionType(fdecl);
213 }
214 209
215 // type has already been resolved 210 // type has already been resolved
216 if (fdecl->type->ir.type != 0) { 211 if (fdecl->type->ir.type != 0)
217 return llvm::cast<llvm::FunctionType>(fdecl->type->ir.type->get()); 212 return llvm::cast<llvm::FunctionType>(fdecl->type->ir.type->get());
218 }
219 213
220 const LLType* thisty = NULL; 214 const LLType* thisty = NULL;
221 if (fdecl->needThis()) { 215 if (fdecl->needThis()) {
222 if (AggregateDeclaration* ad = fdecl->isMember2()) { 216 if (AggregateDeclaration* ad = fdecl->isMember2()) {
223 Logger::println("isMember = this is: %s", ad->type->toChars()); 217 Logger::println("isMember = this is: %s", ad->type->toChars());
244 238
245 static llvm::Function* DtoDeclareVaFunction(FuncDeclaration* fdecl) 239 static llvm::Function* DtoDeclareVaFunction(FuncDeclaration* fdecl)
246 { 240 {
247 TypeFunction* f = (TypeFunction*)DtoDType(fdecl->type); 241 TypeFunction* f = (TypeFunction*)DtoDType(fdecl->type);
248 const llvm::FunctionType* fty = DtoVaFunctionType(fdecl); 242 const llvm::FunctionType* fty = DtoVaFunctionType(fdecl);
249 LLConstant* fn = 0; 243 llvm::Function* func = 0;
250 244
251 if (fdecl->llvmInternal == LLVMva_start) { 245 if (fdecl->llvmInternal == LLVMva_start)
252 fn = gIR->module->getOrInsertFunction("llvm.va_start", fty); 246 func = GET_INTRINSIC_DECL(vastart);
253 assert(fn); 247 else if (fdecl->llvmInternal == LLVMva_copy)
254 } 248 func = GET_INTRINSIC_DECL(vacopy);
255 else if (fdecl->llvmInternal == LLVMva_intrinsic) { 249 else if (fdecl->llvmInternal == LLVMva_end)
256 fn = gIR->module->getOrInsertFunction(fdecl->intrinsicName, fty); 250 func = GET_INTRINSIC_DECL(vaend);
257 assert(fn);
258 }
259 else
260 assert(0);
261
262 llvm::Function* func = llvm::dyn_cast<llvm::Function>(fn);
263 assert(func); 251 assert(func);
264 assert(func->isIntrinsic()); 252
265 fdecl->ir.irFunc->func = func; 253 fdecl->ir.irFunc->func = func;
266 return func; 254 return func;
267 } 255 }
268 256
269 ////////////////////////////////////////////////////////////////////////////////////////// 257 //////////////////////////////////////////////////////////////////////////////////////////
328 316
329 int funcNumArgs = func->getArgumentList().size(); 317 int funcNumArgs = func->getArgumentList().size();
330 std::vector<llvm::ParamAttrsWithIndex> attrs; 318 std::vector<llvm::ParamAttrsWithIndex> attrs;
331 int k = 0; 319 int k = 0;
332 320
333 int nbyval = 0; 321 llvm::ParamAttrsWithIndex PAWI;
334 322
323 // set zext/sext attr on return value if necessary
324 if (f->next->isintegral() && f->next->size() < PTRSIZE)
325 {
326 PAWI.Index = 0;
327 if (f->next->isunsigned())
328 PAWI.Attrs = llvm::ParamAttr::ZExt;
329 else
330 PAWI.Attrs = llvm::ParamAttr::SExt;
331 attrs.push_back(PAWI);
332 }
333
334 // set byval attrs on implicit main arg
335 if (fdecl->isMain() && Argument::dim(f->parameters) == 0) 335 if (fdecl->isMain() && Argument::dim(f->parameters) == 0)
336 { 336 {
337 llvm::ParamAttrsWithIndex PAWI;
338 PAWI.Index = llidx; 337 PAWI.Index = llidx;
339 PAWI.Attrs = llvm::ParamAttr::ByVal; 338 PAWI.Attrs = llvm::ParamAttr::ByVal;
340 attrs.push_back(PAWI); 339 attrs.push_back(PAWI);
341 llidx++; 340 llidx++;
342 nbyval++; 341 }
343 } 342
344 343 // set attrs on the rest of the arguments
345 for (; llidx <= funcNumArgs && f->parameters->dim > k; ++llidx,++k) 344 for (; llidx <= funcNumArgs && f->parameters->dim > k; ++llidx,++k)
346 { 345 {
347 Argument* fnarg = (Argument*)f->parameters->data[k]; 346 Argument* fnarg = (Argument*)f->parameters->data[k];
348 assert(fnarg); 347 assert(fnarg);
349 if (fnarg->llvmByVal) 348
350 { 349 PAWI.Index = llidx;
351 llvm::ParamAttrsWithIndex PAWI; 350 PAWI.Attrs = fnarg->llvmAttrs;
352 PAWI.Index = llidx; 351
353 PAWI.Attrs = llvm::ParamAttr::ByVal; 352 if (PAWI.Attrs)
354 attrs.push_back(PAWI); 353 attrs.push_back(PAWI);
355 nbyval++; 354 }
356 } 355
357 } 356 llvm::PAListPtr palist = llvm::PAListPtr::get(attrs.begin(), attrs.end());
358 357 func->setParamAttrs(palist);
359 if (nbyval) {
360 llvm::PAListPtr palist = llvm::PAListPtr::get(attrs.begin(), attrs.end());
361 func->setParamAttrs(palist);
362 }
363 } 358 }
364 359
365 ////////////////////////////////////////////////////////////////////////////////////////// 360 //////////////////////////////////////////////////////////////////////////////////////////
366 361
367 void DtoDeclareFunction(FuncDeclaration* fdecl) 362 void DtoDeclareFunction(FuncDeclaration* fdecl)
410 mangled_name = fdecl->intrinsicName.c_str(); 405 mangled_name = fdecl->intrinsicName.c_str();
411 else 406 else
412 mangled_name = fdecl->mangle(); 407 mangled_name = fdecl->mangle();
413 408
414 llvm::Function* vafunc = 0; 409 llvm::Function* vafunc = 0;
415 if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) { 410 if (fdecl->isVaIntrinsic())
416 vafunc = DtoDeclareVaFunction(fdecl); 411 vafunc = DtoDeclareVaFunction(fdecl);
417 }
418 412
419 // construct function 413 // construct function
420 const llvm::FunctionType* functype = DtoFunctionType(fdecl); 414 const llvm::FunctionType* functype = DtoFunctionType(fdecl);
421 llvm::Function* func = vafunc ? vafunc : gIR->module->getFunction(mangled_name); 415 llvm::Function* func = vafunc ? vafunc : gIR->module->getFunction(mangled_name);
422 if (!func) 416 if (!func)
435 429
436 fdecl->ir.irFunc->func = func; 430 fdecl->ir.irFunc->func = func;
437 assert(llvm::isa<llvm::FunctionType>(f->ir.type->get())); 431 assert(llvm::isa<llvm::FunctionType>(f->ir.type->get()));
438 432
439 // parameter attributes 433 // parameter attributes
440 if (f->parameters) { 434 if (f->parameters && !fdecl->isIntrinsic()) {
441 set_param_attrs(f, func, fdecl); 435 set_param_attrs(f, func, fdecl);
442 } 436 }
443 437
444 // main 438 // main
445 if (fdecl->isMain()) { 439 if (fdecl->isMain()) {
810 DVarValue vv(argexp->type, dst, true); 804 DVarValue vv(argexp->type, dst, true);
811 DtoAssign(argexp->loc, &vv, argexp->toElem(gIR)); 805 DtoAssign(argexp->loc, &vv, argexp->toElem(gIR));
812 } 806 }
813 807
814 ////////////////////////////////////////////////////////////////////////////////////////// 808 //////////////////////////////////////////////////////////////////////////////////////////
809
810 bool FuncDeclaration::isIntrinsic()
811 {
812 return (llvmInternal == LLVMintrinsic || isVaIntrinsic());
813 }
814
815 bool FuncDeclaration::isVaIntrinsic()
816 {
817 return (llvmInternal == LLVMva_start ||
818 llvmInternal == LLVMva_copy ||
819 llvmInternal == LLVMva_end);
820 }