comparison gen/toir.cpp @ 215:a58d8f4b84df trunk

[svn r231] Changed: warnings are no longer treated as an error. Added some comments and cleaned up CallExp::toElem a tiny bit. Fixed: struct literals always reported inplace assignment even if they allocated a temporary. Fixed: passing stuff to a D-style vararg which did inplace assignment was generated suboptimal code.
author lindquist
date Tue, 03 Jun 2008 13:51:09 +0200
parents 7816aafeea3c
children 0806379a5eca
comparison
equal deleted inserted replaced
214:629cfc1e7b77 215:a58d8f4b84df
865 return l; 865 return l;
866 } 866 }
867 867
868 ////////////////////////////////////////////////////////////////////////////////////////// 868 //////////////////////////////////////////////////////////////////////////////////////////
869 869
870 // TODO: the method below could really use a cleanup/splitup
871
870 DValue* CallExp::toElem(IRState* p) 872 DValue* CallExp::toElem(IRState* p)
871 { 873 {
872 Logger::print("CallExp::toElem: %s | %s\n", toChars(), type->toChars()); 874 Logger::print("CallExp::toElem: %s | %s\n", toChars(), type->toChars());
873 LOG_SCOPE; 875 LOG_SCOPE;
874 876
909 // invalid 911 // invalid
910 else { 912 else {
911 assert(tf); 913 assert(tf);
912 } 914 }
913 915
914 // magic stuff 916 // handling of special intrinsics
915 bool va_magic = false; 917 bool va_magic = false;
916 bool va_intrinsic = false; 918 bool va_intrinsic = false;
917 DFuncValue* dfv = fn->isFunc(); 919 DFuncValue* dfv = fn->isFunc();
918 if (dfv && dfv->func) { 920 if (dfv && dfv->func) {
919 FuncDeclaration* fndecl = dfv->func; 921 FuncDeclaration* fndecl = dfv->func;
922 // vararg intrinsic
920 if (fndecl->llvmInternal == LLVMva_intrinsic) { 923 if (fndecl->llvmInternal == LLVMva_intrinsic) {
921 va_magic = true; 924 va_magic = true;
922 va_intrinsic = true; 925 va_intrinsic = true;
923 } 926 }
927 // va_start instruction
924 else if (fndecl->llvmInternal == LLVMva_start) { 928 else if (fndecl->llvmInternal == LLVMva_start) {
925 va_magic = true; 929 va_magic = true;
926 } 930 }
931 // va_arg instruction
927 else if (fndecl->llvmInternal == LLVMva_arg) { 932 else if (fndecl->llvmInternal == LLVMva_arg) {
928 //Argument* fnarg = Argument::getNth(tf->parameters, 0); 933 //Argument* fnarg = Argument::getNth(tf->parameters, 0);
929 Expression* exp = (Expression*)arguments->data[0]; 934 Expression* exp = (Expression*)arguments->data[0];
930 DValue* expelem = exp->toElem(p); 935 DValue* expelem = exp->toElem(p);
931 Type* t = DtoDType(type); 936 Type* t = DtoDType(type);
932 const LLType* llt = DtoType(type); 937 const LLType* llt = DtoType(type);
933 if (DtoIsPassedByRef(t)) 938 if (DtoIsPassedByRef(t))
934 llt = getPtrToType(llt); 939 llt = getPtrToType(llt);
935 // TODO 940 // TODO
941 // issue a warning for broken va_arg instruction.
936 if (strcmp(global.params.llvmArch, "x86") != 0) { 942 if (strcmp(global.params.llvmArch, "x86") != 0) {
937 warning("%s: va_arg for C variadic functions is broken for anything but x86", loc.toChars()); 943 warning("%s: va_arg for C variadic functions is probably broken for anything but x86", loc.toChars());
938 } 944 }
945 // done
939 return new DImValue(type, p->ir->CreateVAArg(expelem->getLVal(),llt,"tmp")); 946 return new DImValue(type, p->ir->CreateVAArg(expelem->getLVal(),llt,"tmp"));
940 } 947 }
948 // alloca
941 else if (fndecl->llvmInternal == LLVMalloca) { 949 else if (fndecl->llvmInternal == LLVMalloca) {
942 //Argument* fnarg = Argument::getNth(tf->parameters, 0); 950 //Argument* fnarg = Argument::getNth(tf->parameters, 0);
943 Expression* exp = (Expression*)arguments->data[0]; 951 Expression* exp = (Expression*)arguments->data[0];
944 DValue* expv = exp->toElem(p); 952 DValue* expv = exp->toElem(p);
945 if (expv->getType()->toBasetype()->ty != Tint32) 953 if (expv->getType()->toBasetype()->ty != Tint32)
946 expv = DtoCast(expv, Type::tint32); 954 expv = DtoCast(expv, Type::tint32);
947 LLValue* alloc = new llvm::AllocaInst(llvm::Type::Int8Ty, expv->getRVal(), "alloca", p->scopebb()); 955 LLValue* alloc = new llvm::AllocaInst(llvm::Type::Int8Ty, expv->getRVal(), "alloca", p->scopebb());
956 // done
948 return new DImValue(type, alloc); 957 return new DImValue(type, alloc);
949 } 958 }
950 } 959 }
951 960
952 // args 961 // args
963 assert(funcval != 0); 972 assert(funcval != 0);
964 std::vector<LLValue*> llargs(n, 0); 973 std::vector<LLValue*> llargs(n, 0);
965 974
966 const llvm::FunctionType* llfnty = 0; 975 const llvm::FunctionType* llfnty = 0;
967 976
977 // TODO: review the stuff below, using the llvm type to choose seem like a bad idea. the D type should be used.
978 //
968 // normal function call 979 // normal function call
969 if (llvm::isa<llvm::FunctionType>(funcval->getType())) { 980 if (llvm::isa<llvm::FunctionType>(funcval->getType())) {
970 llfnty = llvm::cast<llvm::FunctionType>(funcval->getType()); 981 llfnty = llvm::cast<llvm::FunctionType>(funcval->getType());
971 } 982 }
972 // pointer to something 983 // pointer to something
1080 Expression* exp = (Expression*)arguments->data[i]; 1091 Expression* exp = (Expression*)arguments->data[i];
1081 DValue* expelem = exp->toElem(p); 1092 DValue* expelem = exp->toElem(p);
1082 llargs[j] = DtoBitCast(expelem->getLVal(), getPtrToType(llvm::Type::Int8Ty)); 1093 llargs[j] = DtoBitCast(expelem->getLVal(), getPtrToType(llvm::Type::Int8Ty));
1083 } 1094 }
1084 } 1095 }
1085 // regular arguments 1096 // d variadic function
1097 else if (tf->linkage == LINKd && tf->varargs == 1)
1098 {
1099 Logger::println("doing d-style variadic arguments");
1100
1101 size_t nimplicit = j;
1102
1103 std::vector<const LLType*> vtypes;
1104
1105 // number of non variadic args
1106 int begin = tf->parameters->dim;
1107 Logger::println("num non vararg params = %d", begin);
1108
1109 // build struct with argument types
1110 for (int i=begin; i<arguments->dim; i++)
1111 {
1112 Argument* argu = Argument::getNth(tf->parameters, i);
1113 Expression* argexp = (Expression*)arguments->data[i];
1114 vtypes.push_back(DtoType(argexp->type));
1115 }
1116 const llvm::StructType* vtype = llvm::StructType::get(vtypes);
1117 Logger::cout() << "d-variadic argument struct type:\n" << *vtype << '\n';
1118 LLValue* mem = new llvm::AllocaInst(vtype,"_argptr_storage",p->topallocapoint());
1119
1120 // store arguments in the struct
1121 for (int i=begin,k=0; i<arguments->dim; i++,k++)
1122 {
1123 Expression* argexp = (Expression*)arguments->data[i];
1124 if (global.params.llvmAnnotate)
1125 DtoAnnotation(argexp->toChars());
1126 DtoVariadicArgument(argexp, DtoGEPi(mem,0,k,"tmp"));
1127 }
1128
1129 // build type info array
1130 assert(Type::typeinfo->ir.irStruct->constInit);
1131 const LLType* typeinfotype = DtoType(Type::typeinfo->type);
1132 const llvm::ArrayType* typeinfoarraytype = llvm::ArrayType::get(typeinfotype,vtype->getNumElements());
1133
1134 llvm::GlobalVariable* typeinfomem =
1135 new llvm::GlobalVariable(typeinfoarraytype, true, llvm::GlobalValue::InternalLinkage, NULL, "._arguments.storage", gIR->module);
1136 Logger::cout() << "_arguments storage: " << *typeinfomem << '\n';
1137
1138 std::vector<LLConstant*> vtypeinfos;
1139 for (int i=begin,k=0; i<arguments->dim; i++,k++)
1140 {
1141 Expression* argexp = (Expression*)arguments->data[i];
1142 vtypeinfos.push_back(DtoTypeInfoOf(argexp->type));
1143 }
1144
1145 // apply initializer
1146 LLConstant* tiinits = llvm::ConstantArray::get(typeinfoarraytype, vtypeinfos);
1147 typeinfomem->setInitializer(tiinits);
1148
1149 // put data in d-array
1150 std::vector<LLConstant*> pinits;
1151 pinits.push_back(DtoConstSize_t(vtype->getNumElements()));
1152 pinits.push_back(llvm::ConstantExpr::getBitCast(typeinfomem, getPtrToType(typeinfotype)));
1153 const LLType* tiarrty = llfnty->getParamType(j)->getContainedType(0);
1154 tiinits = llvm::ConstantStruct::get(pinits);
1155 LLValue* typeinfoarrayparam = new llvm::GlobalVariable(tiarrty,
1156 true, llvm::GlobalValue::InternalLinkage, tiinits, "._arguments.array", gIR->module);
1157
1158 // specify arguments
1159 llargs[j] = typeinfoarrayparam;;
1160 j++;
1161 llargs[j] = p->ir->CreateBitCast(mem, getPtrToType(llvm::Type::Int8Ty), "tmp");
1162 j++;
1163
1164 // pass non variadic args
1165 for (int i=0; i<begin; i++)
1166 {
1167 Argument* fnarg = Argument::getNth(tf->parameters, i);
1168 DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
1169 llargs[j] = argval->getRVal();
1170 j++;
1171 }
1172
1173 // make sure arg vector has the right size
1174 llargs.resize(nimplicit+begin+2);
1175 }
1176 // normal function call
1086 else 1177 else
1087 { 1178 {
1088 // d variadic function? 1179 Logger::println("doing normal arguments");
1089 if (tf->linkage == LINKd && tf->varargs == 1) 1180 for (int i=0; i<arguments->dim; i++,j++) {
1090 { 1181 Argument* fnarg = Argument::getNth(tf->parameters, i);
1091 Logger::println("doing d-style variadic arguments"); 1182 if (global.params.llvmAnnotate)
1092 1183 DtoAnnotation(((Expression*)arguments->data[i])->toChars());
1093 size_t nimplicit = j; 1184 DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
1094 1185 llargs[j] = argval->getRVal();
1095 std::vector<const LLType*> vtypes; 1186 if (fnarg && llargs[j]->getType() != llfnty->getParamType(j)) {
1096 1187 llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j));
1097 // number of non variadic args 1188 }
1098 int begin = tf->parameters->dim; 1189
1099 Logger::println("num non vararg params = %d", begin); 1190 // this hack is necessary :/
1100 1191 if (dfn && dfn->func && dfn->func->runTimeHack) {
1101 // build struct with argument types 1192 if (llfnty->getParamType(j) != NULL) {
1102 for (int i=begin; i<arguments->dim; i++) 1193 if (llargs[j]->getType() != llfnty->getParamType(j)) {
1103 { 1194 Logger::println("llvmRunTimeHack==true - force casting argument");
1104 Argument* argu = Argument::getNth(tf->parameters, i); 1195 Logger::cout() << "casting: " << *llargs[j] << " to type: " << *llfnty->getParamType(j) << '\n';
1105 Expression* argexp = (Expression*)arguments->data[i]; 1196 llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j));
1106 vtypes.push_back(DtoType(argexp->type));
1107 }
1108 const llvm::StructType* vtype = llvm::StructType::get(vtypes);
1109 Logger::cout() << "d-variadic argument struct type:\n" << *vtype << '\n';
1110 LLValue* mem = new llvm::AllocaInst(vtype,"_argptr_storage",p->topallocapoint());
1111
1112 // store arguments in the struct
1113 for (int i=begin,k=0; i<arguments->dim; i++,k++)
1114 {
1115 Expression* argexp = (Expression*)arguments->data[i];
1116 if (global.params.llvmAnnotate)
1117 DtoAnnotation(argexp->toChars());
1118 DtoVariadicArgument(argexp, DtoGEPi(mem,0,k,"tmp"));
1119 }
1120
1121 // build type info array
1122 assert(Type::typeinfo->ir.irStruct->constInit);
1123 const LLType* typeinfotype = DtoType(Type::typeinfo->type);
1124 const llvm::ArrayType* typeinfoarraytype = llvm::ArrayType::get(typeinfotype,vtype->getNumElements());
1125
1126 llvm::GlobalVariable* typeinfomem =
1127 new llvm::GlobalVariable(typeinfoarraytype, true, llvm::GlobalValue::InternalLinkage, NULL, "._arguments.storage", gIR->module);
1128 Logger::cout() << "_arguments storage: " << *typeinfomem << '\n';
1129
1130 std::vector<LLConstant*> vtypeinfos;
1131 for (int i=begin,k=0; i<arguments->dim; i++,k++)
1132 {
1133 Expression* argexp = (Expression*)arguments->data[i];
1134 vtypeinfos.push_back(DtoTypeInfoOf(argexp->type));
1135 }
1136
1137 // apply initializer
1138 LLConstant* tiinits = llvm::ConstantArray::get(typeinfoarraytype, vtypeinfos);
1139 typeinfomem->setInitializer(tiinits);
1140
1141 // put data in d-array
1142 std::vector<LLConstant*> pinits;
1143 pinits.push_back(DtoConstSize_t(vtype->getNumElements()));
1144 pinits.push_back(llvm::ConstantExpr::getBitCast(typeinfomem, getPtrToType(typeinfotype)));
1145 const LLType* tiarrty = llfnty->getParamType(j)->getContainedType(0);
1146 tiinits = llvm::ConstantStruct::get(pinits);
1147 LLValue* typeinfoarrayparam = new llvm::GlobalVariable(tiarrty,
1148 true, llvm::GlobalValue::InternalLinkage, tiinits, "._arguments.array", gIR->module);
1149
1150 // specify arguments
1151 llargs[j] = typeinfoarrayparam;;
1152 j++;
1153 llargs[j] = p->ir->CreateBitCast(mem, getPtrToType(llvm::Type::Int8Ty), "tmp");
1154 j++;
1155
1156 // pass non variadic args
1157 for (int i=0; i<begin; i++)
1158 {
1159 Argument* fnarg = Argument::getNth(tf->parameters, i);
1160 DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
1161 llargs[j] = argval->getRVal();
1162 j++;
1163 }
1164
1165 // make sure arg vector has the right size
1166 llargs.resize(nimplicit+begin+2);
1167 }
1168 // normal function
1169 else {
1170 Logger::println("doing normal arguments");
1171 for (int i=0; i<arguments->dim; i++,j++) {
1172 Argument* fnarg = Argument::getNth(tf->parameters, i);
1173 if (global.params.llvmAnnotate)
1174 DtoAnnotation(((Expression*)arguments->data[i])->toChars());
1175 DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
1176 llargs[j] = argval->getRVal();
1177 if (fnarg && llargs[j]->getType() != llfnty->getParamType(j)) {
1178 llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j));
1179 }
1180
1181 // this hack is necessary :/
1182 if (dfn && dfn->func && dfn->func->runTimeHack) {
1183 if (llfnty->getParamType(j) != NULL) {
1184 if (llargs[j]->getType() != llfnty->getParamType(j)) {
1185 Logger::println("llvmRunTimeHack==true - force casting argument");
1186 Logger::cout() << "casting: " << *llargs[j] << " to type: " << *llfnty->getParamType(j) << '\n';
1187 llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j));
1188 }
1189 } 1197 }
1190 } 1198 }
1191 } 1199 }
1192 } 1200 }
1193 } 1201 }
2718 2726
2719 LLValue* sptr; 2727 LLValue* sptr;
2720 const LLType* llt = DtoType(type); 2728 const LLType* llt = DtoType(type);
2721 2729
2722 LLValue* mem = 0; 2730 LLValue* mem = 0;
2731 bool isinplace = true;
2723 2732
2724 // temporary struct literal 2733 // temporary struct literal
2725 if (!p->topexp() || p->topexp()->e2 != this) 2734 if (!p->topexp() || p->topexp()->e2 != this)
2726 { 2735 {
2727 sptr = new llvm::AllocaInst(llt,"tmpstructliteral",p->topallocapoint()); 2736 sptr = new llvm::AllocaInst(llt,"tmpstructliteral",p->topallocapoint());
2737 isinplace = false;
2728 } 2738 }
2729 // already has memory 2739 // already has memory
2730 else 2740 else
2731 { 2741 {
2732 assert(p->topexp()->e2 == this); 2742 assert(p->topexp()->e2 == this);
2775 DtoAssign(darrptr, ve); 2785 DtoAssign(darrptr, ve);
2776 2786
2777 j++; 2787 j++;
2778 } 2788 }
2779 2789
2780 return new DImValue(type, sptr, true); 2790 return new DImValue(type, sptr, isinplace);
2781 } 2791 }
2782 2792
2783 ////////////////////////////////////////////////////////////////////////////////////////// 2793 //////////////////////////////////////////////////////////////////////////////////////////
2784 2794
2785 LLConstant* StructLiteralExp::toConstElem(IRState* p) 2795 LLConstant* StructLiteralExp::toConstElem(IRState* p)