comparison gen/toir.cpp @ 414:ac1fcc138e42

Fixed issue with internal real representation, incorrect for non x86-32 architectures. Cleaned up CallExp::toElem, moved implementation to tocall.cpp providing a single procedure to call arbitrary D functions fairly easily.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Mon, 28 Jul 2008 02:11:34 +0200
parents 0e6b4d65d3f8
children fa91b03d9cd7
comparison
equal deleted inserted replaced
413:1a9bdbd4ac60 414:ac1fcc138e42
849 return res; 849 return res;
850 } 850 }
851 851
852 ////////////////////////////////////////////////////////////////////////////////////////// 852 //////////////////////////////////////////////////////////////////////////////////////////
853 853
854 // TODO: the method below could really use a cleanup/splitup
855
856 DValue* CallExp::toElem(IRState* p) 854 DValue* CallExp::toElem(IRState* p)
857 { 855 {
858 Logger::print("CallExp::toElem: %s | %s\n", toChars(), type->toChars()); 856 Logger::print("CallExp::toElem: %s | %s\n", toChars(), type->toChars());
859 LOG_SCOPE; 857 LOG_SCOPE;
860 858
861 DValue* fn = e1->toElem(p); 859 // get the callee value
862 860 DValue* fnval = e1->toElem(p);
863 TypeFunction* tf = 0; 861
864 Type* e1type = DtoDType(e1->type); 862 // get func value if any
865 863 DFuncValue* dfnval = fnval->isFunc();
866 bool delegateCall = false; 864
867 LINK dlink = LINKd; 865 // handle magic intrinsics (mapping to instructions)
868
869 // hidden struct return parameter handling
870 bool retinptr = false;
871
872 // regular functions
873 if (e1type->ty == Tfunction) {
874 tf = (TypeFunction*)e1type;
875 if (tf->llvmRetInPtr) {
876 retinptr = true;
877 }
878 dlink = tf->linkage;
879 }
880
881 // delegates
882 else if (e1type->ty == Tdelegate) {
883 Logger::println("delegateTy = %s\n", e1type->toChars());
884 assert(e1type->next->ty == Tfunction);
885 tf = (TypeFunction*)e1type->next;
886 if (tf->llvmRetInPtr) {
887 retinptr = true;
888 }
889 dlink = tf->linkage;
890 delegateCall = true;
891 }
892
893 // invalid
894 else {
895 assert(tf);
896 }
897
898 // handling of special intrinsics
899 bool va_magic = false;
900 bool va_intrinsic = false; 866 bool va_intrinsic = false;
901 DFuncValue* dfv = fn->isFunc(); 867 if (dfnval && dfnval->func)
902 if (dfv && dfv->func) { 868 {
903 FuncDeclaration* fndecl = dfv->func; 869 FuncDeclaration* fndecl = dfnval->func;
904 // vararg intrinsic
905 if (fndecl->llvmInternal == LLVMva_intrinsic) {
906 va_magic = true;
907 va_intrinsic = true;
908 }
909 // va_start instruction 870 // va_start instruction
910 else if (fndecl->llvmInternal == LLVMva_start) { 871 if (fndecl->llvmInternal == LLVMva_start) {
911 va_magic = true; 872 // TODO
873 assert(0 && "va_start not yet implemented");
912 } 874 }
913 // va_arg instruction 875 // va_arg instruction
914 else if (fndecl->llvmInternal == LLVMva_arg) { 876 else if (fndecl->llvmInternal == LLVMva_arg) {
915 //Argument* fnarg = Argument::getNth(tf->parameters, 0); 877 return DtoVaArg(loc, type, (Expression*)arguments->data[0]);
916 Expression* exp = (Expression*)arguments->data[0]; 878 }
917 DValue* expelem = exp->toElem(p); 879 // C alloca
918 Type* t = DtoDType(type);
919 const LLType* llt = DtoType(type);
920 if (DtoIsPassedByRef(t))
921 llt = getPtrToType(llt);
922 // TODO
923 // issue a warning for broken va_arg instruction.
924 if (strcmp(global.params.llvmArch, "x86") != 0) {
925 warning("%s: va_arg for C variadic functions is probably broken for anything but x86", loc.toChars());
926 }
927 // done
928 return new DImValue(type, p->ir->CreateVAArg(expelem->getLVal(),llt,"tmp"));
929 }
930 // alloca
931 else if (fndecl->llvmInternal == LLVMalloca) { 880 else if (fndecl->llvmInternal == LLVMalloca) {
932 //Argument* fnarg = Argument::getNth(tf->parameters, 0);
933 Expression* exp = (Expression*)arguments->data[0]; 881 Expression* exp = (Expression*)arguments->data[0];
934 DValue* expv = exp->toElem(p); 882 DValue* expv = exp->toElem(p);
935 if (expv->getType()->toBasetype()->ty != Tint32) 883 if (expv->getType()->toBasetype()->ty != Tint32)
936 expv = DtoCast(loc, expv, Type::tint32); 884 expv = DtoCast(loc, expv, Type::tint32);
937 LLValue* alloc = new llvm::AllocaInst(LLType::Int8Ty, expv->getRVal(), "alloca", p->scopebb()); 885 return new DImValue(type, gIR->ir->CreateAlloca(LLType::Int8Ty, expv->getRVal(), ".alloca"));
938 // done 886 }
939 return new DImValue(type, alloc); 887 }
940 } 888
941 } 889 return DtoCallFunction(type, fnval, arguments);
942
943 // args
944 size_t n = arguments->dim;
945 DFuncValue* dfn = fn->isFunc();
946 if (dfn && dfn->func && dfn->func->llvmInternal == LLVMva_start)
947 n = 1;
948 if (delegateCall || (dfn && dfn->vthis)) n++;
949 if (retinptr) n++;
950 if (tf->linkage == LINKd && tf->varargs == 1) n+=2;
951 if (dfn && dfn->func && dfn->func->isNested()) n++;
952
953 LLValue* funcval = fn->getRVal();
954 assert(funcval != 0);
955 std::vector<LLValue*> llargs(n, 0);
956
957 const LLFunctionType* llfnty = 0;
958
959 // TODO: review the stuff below, using the llvm type to choose seem like a bad idea. the D type should be used.
960 //
961 // normal function call
962 if (llvm::isa<LLFunctionType>(funcval->getType())) {
963 llfnty = llvm::cast<LLFunctionType>(funcval->getType());
964 }
965 // pointer to something
966 else if (isaPointer(funcval->getType())) {
967 // pointer to function pointer - I think this not really supposed to happen, but does :/
968 // seems like sometimes we get a func* other times a func**
969 if (isaPointer(funcval->getType()->getContainedType(0))) {
970 funcval = DtoLoad(funcval);
971 }
972 // function pointer
973 if (llvm::isa<LLFunctionType>(funcval->getType()->getContainedType(0))) {
974 //Logger::cout() << "function pointer type:\n" << *funcval << '\n';
975 llfnty = llvm::cast<LLFunctionType>(funcval->getType()->getContainedType(0));
976 }
977 // struct pointer - delegate
978 else if (isaStruct(funcval->getType()->getContainedType(0))) {
979 funcval = DtoGEPi(funcval,0,1);
980 funcval = DtoLoad(funcval);
981 const LLType* ty = funcval->getType()->getContainedType(0);
982 llfnty = llvm::cast<LLFunctionType>(ty);
983 }
984 // unknown
985 else {
986 Logger::cout() << "what kind of pointer are we calling? : " << *funcval->getType() << '\n';
987 }
988 }
989 else {
990 Logger::cout() << "what are we calling? : " << *funcval << '\n';
991 }
992 assert(llfnty);
993 //Logger::cout() << "Function LLVM type: " << *llfnty << '\n';
994
995 // argument handling
996 LLFunctionType::param_iterator argiter = llfnty->param_begin();
997 int j = 0;
998
999 // attrs
1000 llvm::PAListPtr palist;
1001
1002 // hidden struct return arguments
1003 // TODO: use sret param attr
1004 if (retinptr) {
1005 llargs[j] = new llvm::AllocaInst(argiter->get()->getContainedType(0),"rettmp",p->topallocapoint());
1006 ++j;
1007 ++argiter;
1008 }
1009
1010 // this arguments
1011 if (dfn && dfn->vthis) {
1012 Logger::cout() << "This Call" << '\n';// func val:" << *funcval << '\n';
1013 if (dfn->vthis->getType() != argiter->get()) {
1014 //Logger::cout() << "value: " << *dfn->vthis << " totype: " << *argiter->get() << '\n';
1015 llargs[j] = DtoBitCast(dfn->vthis, argiter->get());
1016 }
1017 else {
1018 llargs[j] = dfn->vthis;
1019 }
1020 ++j;
1021 ++argiter;
1022 }
1023 // delegate context arguments
1024 else if (delegateCall) {
1025 Logger::println("Delegate Call");
1026 LLValue* contextptr = DtoGEPi(fn->getRVal(),0,0);
1027 llargs[j] = DtoLoad(contextptr);
1028 ++j;
1029 ++argiter;
1030 }
1031 // nested call
1032 else if (dfn && dfn->func && dfn->func->isNested()) {
1033 Logger::println("Nested Call");
1034 LLValue* contextptr = DtoNestedContext(dfn->func->toParent2()->isFuncDeclaration());
1035 if (!contextptr)
1036 contextptr = llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty));
1037 llargs[j] = DtoBitCast(contextptr, getPtrToType(LLType::Int8Ty));
1038 ++j;
1039 ++argiter;
1040 }
1041
1042 // va arg function special argument passing
1043 if (va_magic)
1044 {
1045 size_t n = va_intrinsic ? arguments->dim : 1;
1046 for (int i=0; i<n; i++,j++)
1047 {
1048 Argument* fnarg = Argument::getNth(tf->parameters, i);
1049 Expression* exp = (Expression*)arguments->data[i];
1050 DValue* expelem = exp->toElem(p);
1051 llargs[j] = DtoBitCast(expelem->getLVal(), getPtrToType(LLType::Int8Ty));
1052 }
1053 }
1054 // d variadic function
1055 else if (tf->linkage == LINKd && tf->varargs == 1)
1056 {
1057 Logger::println("doing d-style variadic arguments");
1058
1059 size_t nimplicit = j;
1060
1061 std::vector<const LLType*> vtypes;
1062
1063 // number of non variadic args
1064 int begin = tf->parameters->dim;
1065 Logger::println("num non vararg params = %d", begin);
1066
1067 // build struct with argument types
1068 for (int i=begin; i<arguments->dim; i++)
1069 {
1070 Argument* argu = Argument::getNth(tf->parameters, i);
1071 Expression* argexp = (Expression*)arguments->data[i];
1072 vtypes.push_back(DtoType(argexp->type));
1073 size_t sz = getABITypeSize(vtypes.back());
1074 if (sz < PTRSIZE)
1075 vtypes.back() = DtoSize_t();
1076 }
1077 const LLStructType* vtype = LLStructType::get(vtypes);
1078 Logger::cout() << "d-variadic argument struct type:\n" << *vtype << '\n';
1079 LLValue* mem = new llvm::AllocaInst(vtype,"_argptr_storage",p->topallocapoint());
1080
1081 // store arguments in the struct
1082 for (int i=begin,k=0; i<arguments->dim; i++,k++)
1083 {
1084 Expression* argexp = (Expression*)arguments->data[i];
1085 if (global.params.llvmAnnotate)
1086 DtoAnnotation(argexp->toChars());
1087 LLValue* argdst = DtoGEPi(mem,0,k);
1088 argdst = DtoBitCast(argdst, getPtrToType(DtoType(argexp->type)));
1089 DtoVariadicArgument(argexp, argdst);
1090 }
1091
1092 // build type info array
1093 assert(Type::typeinfo->ir.irStruct->constInit);
1094 const LLType* typeinfotype = DtoType(Type::typeinfo->type);
1095 const LLArrayType* typeinfoarraytype = LLArrayType::get(typeinfotype,vtype->getNumElements());
1096
1097 llvm::GlobalVariable* typeinfomem =
1098 new llvm::GlobalVariable(typeinfoarraytype, true, llvm::GlobalValue::InternalLinkage, NULL, "._arguments.storage", gIR->module);
1099 Logger::cout() << "_arguments storage: " << *typeinfomem << '\n';
1100
1101 std::vector<LLConstant*> vtypeinfos;
1102 for (int i=begin,k=0; i<arguments->dim; i++,k++)
1103 {
1104 Expression* argexp = (Expression*)arguments->data[i];
1105 vtypeinfos.push_back(DtoTypeInfoOf(argexp->type));
1106 }
1107
1108 // apply initializer
1109 LLConstant* tiinits = llvm::ConstantArray::get(typeinfoarraytype, vtypeinfos);
1110 typeinfomem->setInitializer(tiinits);
1111
1112 // put data in d-array
1113 std::vector<LLConstant*> pinits;
1114 pinits.push_back(DtoConstSize_t(vtype->getNumElements()));
1115 pinits.push_back(llvm::ConstantExpr::getBitCast(typeinfomem, getPtrToType(typeinfotype)));
1116 const LLType* tiarrty = llfnty->getParamType(j)->getContainedType(0);
1117 tiinits = llvm::ConstantStruct::get(pinits);
1118 LLValue* typeinfoarrayparam = new llvm::GlobalVariable(tiarrty,
1119 true, llvm::GlobalValue::InternalLinkage, tiinits, "._arguments.array", gIR->module);
1120
1121 // specify arguments
1122 llargs[j] = typeinfoarrayparam;;
1123 j++;
1124 llargs[j] = p->ir->CreateBitCast(mem, getPtrToType(LLType::Int8Ty), "tmp");
1125 j++;
1126
1127 // pass non variadic args
1128 for (int i=0; i<begin; i++)
1129 {
1130 Argument* fnarg = Argument::getNth(tf->parameters, i);
1131 DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
1132 llargs[j] = argval->getRVal();
1133
1134 if (fnarg->llvmByVal)
1135 palist = palist.addAttr(j, llvm::ParamAttr::ByVal);
1136
1137 j++;
1138 }
1139
1140 // make sure arg vector has the right size
1141 llargs.resize(nimplicit+begin+2);
1142 }
1143 // normal function call
1144 else
1145 {
1146 Logger::println("doing normal arguments");
1147 for (int i=0; i<arguments->dim; i++,j++) {
1148 Argument* fnarg = Argument::getNth(tf->parameters, i);
1149 if (global.params.llvmAnnotate)
1150 DtoAnnotation(((Expression*)arguments->data[i])->toChars());
1151 DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
1152 llargs[j] = argval->getRVal();
1153 if (fnarg && llargs[j]->getType() != llfnty->getParamType(j)) {
1154 llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j));
1155 }
1156
1157 if (fnarg && fnarg->llvmByVal)
1158 palist = palist.addAttr(j+1, llvm::ParamAttr::ByVal);
1159 }
1160 }
1161
1162 #if 0
1163 Logger::println("%d params passed", n);
1164 for (int i=0; i<llargs.size(); ++i) {
1165 assert(llargs[i]);
1166 Logger::cout() << "arg["<<i<<"] = " << *llargs[i] << '\n';
1167 }
1168 #endif
1169
1170 // void returns cannot not be named
1171 const char* varname = "";
1172 if (llfnty->getReturnType() != LLType::VoidTy)
1173 varname = "tmp";
1174
1175 //Logger::cout() << "Calling: " << *funcval << '\n';
1176
1177 // call the function
1178 CallOrInvoke* call = gIR->CreateCallOrInvoke(funcval, llargs.begin(), llargs.end(), varname);
1179
1180 LLValue* retllval = (retinptr) ? llargs[0] : call->get();
1181
1182 // if the type of retllval is abstract, refine to concrete
1183 if(retllval->getType()->isAbstract())
1184 retllval = DtoBitCast(retllval, getPtrToType(DtoType(type)), "retval");
1185
1186 // set calling convention
1187 if (dfn && dfn->func) {
1188 int li = dfn->func->llvmInternal;
1189 if (li != LLVMintrinsic && li != LLVMva_start && li != LLVMva_intrinsic) {
1190 call->setCallingConv(DtoCallingConv(dlink));
1191 }
1192 }
1193 else {
1194 call->setCallingConv(DtoCallingConv(dlink));
1195 }
1196
1197 // param attrs
1198 call->setParamAttrs(palist);
1199
1200 return new DImValue(type, retllval, false);
1201 } 890 }
1202 891
1203 ////////////////////////////////////////////////////////////////////////////////////////// 892 //////////////////////////////////////////////////////////////////////////////////////////
1204 893
1205 DValue* CastExp::toElem(IRState* p) 894 DValue* CastExp::toElem(IRState* p)