llvm.org GIT mirror llvm / 0c58340
Significant refactoring of the inline asm stuff, to support future changes. No functionality change. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36544 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Lattner 13 years ago
1 changed file(s) with 115 addition(s) and 90 deletion(s). Raw diff Collapse all Expand all
31713171 return *Current;
31723172 }
31733173
3174 namespace {
3175 /// AsmOperandInfo - This contains information for each constraint that we are
3176 /// lowering.
3177 struct AsmOperandInfo : public InlineAsm::ConstraintInfo {
3178 /// ConstraintCode - This contains the actual string for the code, like "m".
3179 std::string ConstraintCode;
3180
3181 /// CallOperand/CallOperandval - If this is the result output operand or a
3182 /// clobber, this is null, otherwise it is the incoming operand to the
3183 /// CallInst. This gets modified as the asm is processed.
3184 SDOperand CallOperand;
3185 Value *CallOperandVal;
3186
3187 /// ConstraintVT - The ValueType for the operand value.
3188 MVT::ValueType ConstraintVT;
3189
3190 AsmOperandInfo(const InlineAsm::ConstraintInfo &info)
3191 : InlineAsm::ConstraintInfo(info),
3192 CallOperand(0,0), CallOperandVal(0), ConstraintVT(MVT::Other) {
3193 }
3194 };
3195 } // end anon namespace.
31743196
31753197 /// visitInlineAsm - Handle a call to an InlineAsm object.
31763198 ///
31773199 void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
31783200 InlineAsm *IA = cast(I.getOperand(0));
3179
3180 SDOperand AsmStr = DAG.getTargetExternalSymbol(IA->getAsmString().c_str(),
3181 MVT::Other);
3182
3183 std::vector Constraints = IA->ParseConstraints();
3184 std::vector ConstraintVTs;
3185
3186 /// AsmNodeOperands - A list of pairs. The first element is a register, the
3187 /// second is a bitfield where bit #0 is set if it is a use and bit #1 is set
3188 /// if it is a def of that register.
3189 std::vector AsmNodeOperands;
3190 AsmNodeOperands.push_back(SDOperand()); // reserve space for input chain
3191 AsmNodeOperands.push_back(AsmStr);
3201
3202 /// ConstraintOperands - Information about all of the constraints.
3203 std::vector ConstraintOperands;
31923204
31933205 SDOperand Chain = getRoot();
31943206 SDOperand Flag;
31953207
3196 // We fully assign registers here at isel time. This is not optimal, but
3197 // should work. For register classes that correspond to LLVM classes, we
3198 // could let the LLVM RA do its thing, but we currently don't. Do a prepass
3199 // over the constraints, collecting fixed registers that we know we can't use.
32003208 std::set OutputRegs, InputRegs;
3201 unsigned OpNum = 1;
3202 for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
3203 std::string ConstraintCode =
3204 GetMostGeneralConstraint(Constraints[i].Codes, TLI);
3205
3206 MVT::ValueType OpVT;
3207
3208 // Compute the value type for each operand and add it to ConstraintVTs.
3209 switch (Constraints[i].Type) {
3209
3210 // Do a prepass over the constraints, canonicalizing them, and building up the
3211 // ConstraintOperands list.
3212 std::vector
3213 ConstraintInfos = IA->ParseConstraints();
3214 unsigned OpNo = 1;
3215 for (unsigned i = 0, e = ConstraintInfos.size(); i != e; ++i) {
3216 ConstraintOperands.push_back(AsmOperandInfo(ConstraintInfos[i]));
3217 AsmOperandInfo &OpInfo = ConstraintOperands.back();
3218
3219 // Compute the constraint code to use.
3220 OpInfo.ConstraintCode = GetMostGeneralConstraint(OpInfo.Codes, TLI);
3221
3222 MVT::ValueType OpVT = MVT::Other;
3223
3224 // Compute the value type for each operand.
3225 switch (OpInfo.Type) {
32103226 case InlineAsm::isOutput:
3211 if (!Constraints[i].isIndirect) {
3212 // The return value of the call is this value.
3227 if (!OpInfo.isIndirect) {
3228 // The return value of the call is this value. As such, there is no
3229 // corresponding argument.
32133230 assert(I.getType() != Type::VoidTy && "Bad inline asm!");
32143231 OpVT = TLI.getValueType(I.getType());
32153232 } else {
3216 const Type *OpTy = I.getOperand(OpNum)->getType();
3217 OpVT = TLI.getValueType(cast(OpTy)->getElementType(),true);
3218 OpNum++; // Consumes a call operand.
3233 OpInfo.CallOperandVal = I.getOperand(OpNo++);
32193234 }
32203235 break;
32213236 case InlineAsm::isInput:
3222 if (!Constraints[i].isIndirect) {
3223 OpVT = TLI.getValueType(I.getOperand(OpNum)->getType());
3237 OpInfo.CallOperandVal = I.getOperand(OpNo++);
3238 break;
3239 case InlineAsm::isClobber:
3240 // Nothing to do.
3241 break;
3242 }
3243
3244 // If this is an input or an indirect output, process the call argument.
3245 if (OpInfo.CallOperandVal) {
3246 OpInfo.CallOperand = getValue(OpInfo.CallOperandVal);
3247 const Type *OpTy = OpInfo.CallOperandVal->getType();
3248 if (!OpInfo.isIndirect) {
3249 // Must be an input.
3250 OpVT = TLI.getValueType(OpTy);
32243251 } else {
3225 const Type *OpTy = I.getOperand(OpNum)->getType();
32263252 OpVT = TLI.getValueType(cast(OpTy)->getElementType(),true);
32273253 }
3228 OpNum++; // Consumes a call operand.
3229 break;
3230 case InlineAsm::isClobber:
3231 OpVT = MVT::Other;
3232 break;
3233 }
3234
3235 ConstraintVTs.push_back(OpVT);
3236
3237 if (TLI.getRegForInlineAsmConstraint(ConstraintCode, OpVT).first == 0)
3254 }
3255
3256 OpInfo.ConstraintVT = OpVT;
3257
3258 if (TLI.getRegForInlineAsmConstraint(OpInfo.ConstraintCode, OpVT).first ==0)
32383259 continue; // Not assigned a fixed reg.
3260
3261 // For GCC register classes where we don't have a direct match, we fully
3262 // assign registers at isel time. This is not optimal, but works.
32393263
32403264 // Build a list of regs that this operand uses. This always has a single
32413265 // element for promoted/expanded operands.
3242 RegsForValue Regs = GetRegistersForValue(ConstraintCode, OpVT,
3266 RegsForValue Regs = GetRegistersForValue(OpInfo.ConstraintCode, OpVT,
32433267 false, false,
32443268 OutputRegs, InputRegs);
32453269
3246 switch (Constraints[i].Type) {
3270 switch (OpInfo.Type) {
32473271 case InlineAsm::isOutput:
32483272 // We can't assign any other output to this register.
32493273 OutputRegs.insert(Regs.Regs.begin(), Regs.Regs.end());
32503274 // If this is an early-clobber output, it cannot be assigned to the same
32513275 // value as the input reg.
3252 if (Constraints[i].isEarlyClobber || Constraints[i].hasMatchingInput)
3276 if (OpInfo.isEarlyClobber || OpInfo.hasMatchingInput)
32533277 InputRegs.insert(Regs.Regs.begin(), Regs.Regs.end());
32543278 break;
32553279 case InlineAsm::isInput:
32623286 OutputRegs.insert(Regs.Regs.begin(), Regs.Regs.end());
32633287 break;
32643288 }
3265 }
3289 }
3290
3291 ConstraintInfos.clear();
3292
3293
3294 // AsmNodeOperands - The operands for the ISD::INLINEASM node.
3295 std::vector AsmNodeOperands;
3296 AsmNodeOperands.push_back(SDOperand()); // reserve space for input chain
3297 AsmNodeOperands.push_back(
3298 DAG.getTargetExternalSymbol(IA->getAsmString().c_str(), MVT::Other));
3299
32663300
32673301 // Loop over all of the inputs, copying the operand values into the
32683302 // appropriate registers and processing the output regs.
32693303 RegsForValue RetValRegs;
3304
3305 // IndirectStoresToEmit - The set of stores to emit after the inline asm node.
32703306 std::vector > IndirectStoresToEmit;
3271 OpNum = 1;
3272
3273 for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
3274 std::string ConstraintCode =
3275 GetMostGeneralConstraint(Constraints[i].Codes, TLI);
3276
3277 switch (Constraints[i].Type) {
3307
3308 for (unsigned i = 0, e = ConstraintOperands.size(); i != e; ++i) {
3309 AsmOperandInfo &OpInfo = ConstraintOperands[i];
3310
3311 switch (OpInfo.Type) {
32783312 case InlineAsm::isOutput: {
32793313 TargetLowering::ConstraintType CTy = TargetLowering::C_RegisterClass;
3280 if (ConstraintCode.size() == 1) // not a physreg name.
3281 CTy = TLI.getConstraintType(ConstraintCode);
3314 if (OpInfo.ConstraintCode.size() == 1) // not a physreg name.
3315 CTy = TLI.getConstraintType(OpInfo.ConstraintCode);
32823316
32833317 if (CTy != TargetLowering::C_RegisterClass) {
32843318 // Memory output, or 'other' output (e.g. 'X' constraint).
3285 SDOperand InOperandVal = getValue(I.getOperand(OpNum));
3319 SDOperand InOperandVal = OpInfo.CallOperand;
32863320
32873321 // Check that the operand (the address to store to) isn't a float.
32883322 if (!MVT::isInteger(InOperandVal.getValueType()))
32893323 assert(0 && "MATCH FAIL!");
32903324
3291 if (!Constraints[i].isIndirect)
3325 if (!OpInfo.isIndirect)
32923326 assert(0 && "MATCH FAIL!");
32933327
3294 OpNum++; // Consumes a call operand.
3295
3296 // Extend/truncate to the right pointer type if needed.
3297 MVT::ValueType PtrType = TLI.getPointerTy();
3298 if (InOperandVal.getValueType() < PtrType)
3299 InOperandVal = DAG.getNode(ISD::ZERO_EXTEND, PtrType, InOperandVal);
3300 else if (InOperandVal.getValueType() > PtrType)
3301 InOperandVal = DAG.getNode(ISD::TRUNCATE, PtrType, InOperandVal);
3302
33033328 // Add information to the INLINEASM node to know about this output.
33043329 unsigned ResOpType = 4/*MEM*/ | (1 << 3);
33053330 AsmNodeOperands.push_back(DAG.getConstant(ResOpType, MVT::i32));
33143339 // constraint that matches this, we need to reserve the input register
33153340 // so no other inputs allocate to it.
33163341 bool UsesInputRegister = false;
3317 if (Constraints[i].isEarlyClobber || Constraints[i].hasMatchingInput)
3342 if (OpInfo.isEarlyClobber || OpInfo.hasMatchingInput)
33183343 UsesInputRegister = true;
33193344
33203345 // Copy the output from the appropriate register. Find a register that
33213346 // we can use.
33223347 RegsForValue Regs =
3323 GetRegistersForValue(ConstraintCode, ConstraintVTs[i],
3348 GetRegistersForValue(OpInfo.ConstraintCode, OpInfo.ConstraintVT,
33243349 true, UsesInputRegister,
33253350 OutputRegs, InputRegs);
33263351 if (Regs.Regs.empty()) {
33273352 cerr << "Couldn't allocate output reg for contraint '"
3328 << ConstraintCode << "'!\n";
3353 << OpInfo.ConstraintCode << "'!\n";
33293354 exit(1);
33303355 }
33313356
3332 if (!Constraints[i].isIndirect) {
3357 if (!OpInfo.isIndirect) {
3358 // This is the result value of the call.
33333359 assert(RetValRegs.Regs.empty() &&
33343360 "Cannot have multiple output constraints yet!");
33353361 assert(I.getType() != Type::VoidTy && "Bad inline asm!");
33363362 RetValRegs = Regs;
33373363 } else {
3338 IndirectStoresToEmit.push_back(std::make_pair(Regs,
3339 I.getOperand(OpNum)));
3340 OpNum++; // Consumes a call operand.
3364 IndirectStoresToEmit.push_back(std::make_pair(Regs,
3365 OpInfo.CallOperandVal));
33413366 }
33423367
33433368 // Add information to the INLINEASM node to know that this register is
33463371 break;
33473372 }
33483373 case InlineAsm::isInput: {
3349 SDOperand InOperandVal = getValue(I.getOperand(OpNum));
3350 OpNum++; // Consumes a call operand.
3374 SDOperand InOperandVal = OpInfo.CallOperand;
33513375
3352 if (isdigit(ConstraintCode[0])) { // Matching constraint?
3376 if (isdigit(OpInfo.ConstraintCode[0])) { // Matching constraint?
33533377 // If this is required to match an output register we have already set,
33543378 // just use its register.
3355 unsigned OperandNo = atoi(ConstraintCode.c_str());
3379 unsigned OperandNo = atoi(OpInfo.ConstraintCode.c_str());
33563380
33573381 // Scan until we find the definition we already emitted of this operand.
33583382 // When we find it, create a RegsForValue operand.
33923416 }
33933417
33943418 TargetLowering::ConstraintType CTy = TargetLowering::C_RegisterClass;
3395 if (ConstraintCode.size() == 1) // not a physreg name.
3396 CTy = TLI.getConstraintType(ConstraintCode);
3419 if (OpInfo.ConstraintCode.size() == 1) // not a physreg name.
3420 CTy = TLI.getConstraintType(OpInfo.ConstraintCode);
33973421
33983422 if (CTy == TargetLowering::C_Other) {
3399 assert(!Constraints[i].isIndirect &&
3423 assert(!OpInfo.isIndirect &&
34003424 "Don't know how to handle indirect other inputs yet!");
34013425
34023426 InOperandVal = TLI.isOperandValidForConstraint(InOperandVal,
3403 ConstraintCode[0], DAG);
3427 OpInfo.ConstraintCode[0],
3428 DAG);
34043429 if (!InOperandVal.Val) {
34053430 cerr << "Invalid operand for inline asm constraint '"
3406 << ConstraintCode << "'!\n";
3431 << OpInfo.ConstraintCode << "'!\n";
34073432 exit(1);
34083433 }
34093434
34173442 // so we want an indirect input. If we don't have an indirect input,
34183443 // spill the value somewhere if we can, otherwise spill it to a stack
34193444 // slot.
3420 if (!Constraints[i].isIndirect) {
3445 if (!OpInfo.isIndirect) {
34213446 // If the operand is a float, integer, or vector constant, spill to a
34223447 // constant pool entry to get its address.
3423 Value *OpVal = I.getOperand(OpNum-1);
3448 Value *OpVal = OpInfo.CallOperandVal;
34243449 if (isa(OpVal) || isa(OpVal) ||
34253450 isa(OpVal)) {
34263451 InOperandVal = DAG.getConstantPool(cast(OpVal),
34503475 }
34513476
34523477 assert(CTy == TargetLowering::C_RegisterClass && "Unknown op type!");
3453 assert(!Constraints[i].isIndirect &&
3478 assert(!OpInfo.isIndirect &&
34543479 "Don't know how to handle indirect register inputs yet!");
34553480
34563481 // Copy the input into the appropriate registers.
34573482 RegsForValue InRegs =
3458 GetRegistersForValue(ConstraintCode, ConstraintVTs[i],
3483 GetRegistersForValue(OpInfo.ConstraintCode, OpInfo.ConstraintVT,
34593484 false, true, OutputRegs, InputRegs);
34603485 // FIXME: should be match fail.
34613486 assert(!InRegs.Regs.empty() && "Couldn't allocate input reg!");
34673492 }
34683493 case InlineAsm::isClobber: {
34693494 RegsForValue ClobberedRegs =
3470 GetRegistersForValue(ConstraintCode, MVT::Other, false, false,
3495 GetRegistersForValue(OpInfo.ConstraintCode, MVT::Other, false, false,
34713496 OutputRegs, InputRegs);
34723497 // Add the clobbered value to the operand list, so that the register
34733498 // allocator is aware that the physreg got clobbered.
35223547 // Emit the non-flagged stores from the physregs.
35233548 SmallVector OutChains;
35243549 for (unsigned i = 0, e = StoresToEmit.size(); i != e; ++i)
3525 OutChains.push_back(DAG.getStore(Chain, StoresToEmit[i].first,
3550 OutChains.push_back(DAG.getStore(Chain, StoresToEmit[i].first,
35263551 getValue(StoresToEmit[i].second),
35273552 StoresToEmit[i].second, 0));
35283553 if (!OutChains.empty())