Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(372)

Side by Side Diff: src/IceTargetLoweringMIPS32.cpp

Issue 2021033002: [Subzero][MIPS32] Add argument handling in LowerCall (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Addressing review comments Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // 1 //
2 // The Subzero Code Generator 2 // The Subzero Code Generator
3 // 3 //
4 // This file is distributed under the University of Illinois Open Source 4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details. 5 // License. See LICENSE.TXT for details.
6 // 6 //
7 //===----------------------------------------------------------------------===// 7 //===----------------------------------------------------------------------===//
8 /// 8 ///
9 /// \file 9 /// \file
10 /// \brief Implements the TargetLoweringMIPS32 class, which consists almost 10 /// \brief Implements the TargetLoweringMIPS32 class, which consists almost
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 namespace Ice { 57 namespace Ice {
58 namespace MIPS32 { 58 namespace MIPS32 {
59 59
60 using llvm::isInt; 60 using llvm::isInt;
61 61
62 namespace { 62 namespace {
63 63
64 // The maximum number of arguments to pass in GPR registers. 64 // The maximum number of arguments to pass in GPR registers.
65 constexpr uint32_t MIPS32_MAX_GPR_ARG = 4; 65 constexpr uint32_t MIPS32_MAX_GPR_ARG = 4;
66 66
67 std::array<RegNumT, MIPS32_MAX_GPR_ARG> GPRArgInitializer;
68 std::array<RegNumT, MIPS32_MAX_GPR_ARG / 2> I64ArgInitializer;
69
67 const char *getRegClassName(RegClass C) { 70 const char *getRegClassName(RegClass C) {
68 auto ClassNum = static_cast<RegClassMIPS32>(C); 71 auto ClassNum = static_cast<RegClassMIPS32>(C);
69 assert(ClassNum < RCMIPS32_NUM); 72 assert(ClassNum < RCMIPS32_NUM);
70 switch (ClassNum) { 73 switch (ClassNum) {
71 default: 74 default:
72 assert(C < RC_Target); 75 assert(C < RC_Target);
73 return regClassString(C); 76 return regClassString(C);
74 // Add handling of new register classes below. 77 // Add handling of new register classes below.
75 } 78 }
76 } 79 }
77 80
81 // Stack alignment
82 constexpr uint32_t MIPS32_STACK_ALIGNMENT_BYTES = 16;
83
84 // Value is in bytes. Return Value adjusted to the next highest multiple of the
85 // stack alignment.
86 uint32_t applyStackAlignment(uint32_t Value) {
87 return Utils::applyAlignment(Value, MIPS32_STACK_ALIGNMENT_BYTES);
88 }
89
90 // Value is in bytes. Return Value adjusted to the next highest multiple of the
91 // stack alignment required for the given type.
92 uint32_t applyStackAlignmentTy(uint32_t Value, Type Ty) {
93 size_t typeAlignInBytes = typeWidthInBytes(Ty);
94 if (isVectorType(Ty))
95 typeAlignInBytes = 8;
96 return Utils::applyAlignment(Value, typeAlignInBytes);
97 }
98
78 } // end of anonymous namespace 99 } // end of anonymous namespace
79 100
80 TargetMIPS32::TargetMIPS32(Cfg *Func) : TargetLowering(Func) {} 101 TargetMIPS32::TargetMIPS32(Cfg *Func) : TargetLowering(Func) {}
81 102
82 void TargetMIPS32::staticInit(GlobalContext *Ctx) { 103 void TargetMIPS32::staticInit(GlobalContext *Ctx) {
83 (void)Ctx; 104 (void)Ctx;
84 RegNumT::setLimit(RegMIPS32::Reg_NUM); 105 RegNumT::setLimit(RegMIPS32::Reg_NUM);
85 SmallBitVector IntegerRegisters(RegMIPS32::Reg_NUM); 106 SmallBitVector IntegerRegisters(RegMIPS32::Reg_NUM);
86 SmallBitVector I64PairRegisters(RegMIPS32::Reg_NUM); 107 SmallBitVector I64PairRegisters(RegMIPS32::Reg_NUM);
87 SmallBitVector Float32Registers(RegMIPS32::Reg_NUM); 108 SmallBitVector Float32Registers(RegMIPS32::Reg_NUM);
(...skipping 10 matching lines...) Expand all
98 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ 119 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \
99 for (SizeT RegAlias : alias_init) { \ 120 for (SizeT RegAlias : alias_init) { \
100 assert(!RegisterAliases[RegMIPS32::val][RegAlias] && \ 121 assert(!RegisterAliases[RegMIPS32::val][RegAlias] && \
101 "Duplicate alias for " #val); \ 122 "Duplicate alias for " #val); \
102 RegisterAliases[RegMIPS32::val].set(RegAlias); \ 123 RegisterAliases[RegMIPS32::val].set(RegAlias); \
103 } \ 124 } \
104 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ 125 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \
105 assert(RegisterAliases[RegMIPS32::val][RegMIPS32::val]); 126 assert(RegisterAliases[RegMIPS32::val][RegMIPS32::val]);
106 REGMIPS32_TABLE; 127 REGMIPS32_TABLE;
107 #undef X 128 #undef X
129
130 for (size_t i = 0; i < MIPS32_MAX_GPR_ARG; i++)
131 GPRArgInitializer[i] = RegNumT::fixme(RegMIPS32::Reg_A0 + i);
132
133 for (size_t i = 0; i < MIPS32_MAX_GPR_ARG / 2; i++)
134 I64ArgInitializer[i] = RegNumT::fixme(RegMIPS32::Reg_A0A1 + i);
135
108 TypeToRegisterSet[IceType_void] = InvalidRegisters; 136 TypeToRegisterSet[IceType_void] = InvalidRegisters;
109 TypeToRegisterSet[IceType_i1] = IntegerRegisters; 137 TypeToRegisterSet[IceType_i1] = IntegerRegisters;
110 TypeToRegisterSet[IceType_i8] = IntegerRegisters; 138 TypeToRegisterSet[IceType_i8] = IntegerRegisters;
111 TypeToRegisterSet[IceType_i16] = IntegerRegisters; 139 TypeToRegisterSet[IceType_i16] = IntegerRegisters;
112 TypeToRegisterSet[IceType_i32] = IntegerRegisters; 140 TypeToRegisterSet[IceType_i32] = IntegerRegisters;
113 TypeToRegisterSet[IceType_i64] = IntegerRegisters; 141 TypeToRegisterSet[IceType_i64] = IntegerRegisters;
114 TypeToRegisterSet[IceType_f32] = Float32Registers; 142 TypeToRegisterSet[IceType_f32] = Float32Registers;
115 TypeToRegisterSet[IceType_f64] = Float64Registers; 143 TypeToRegisterSet[IceType_f64] = Float64Registers;
116 TypeToRegisterSet[IceType_v4i1] = VectorRegisters; 144 TypeToRegisterSet[IceType_v4i1] = VectorRegisters;
117 TypeToRegisterSet[IceType_v8i1] = VectorRegisters; 145 TypeToRegisterSet[IceType_v8i1] = VectorRegisters;
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
382 return; 410 return;
383 } else { 411 } else {
384 int32_t Offset = Var->getStackOffset(); 412 int32_t Offset = Var->getStackOffset();
385 Str << Offset; 413 Str << Offset;
386 Str << "($" << getRegName(getFrameOrStackReg(), FrameSPTy); 414 Str << "($" << getRegName(getFrameOrStackReg(), FrameSPTy);
387 Str << ")"; 415 Str << ")";
388 } 416 }
389 UnimplementedError(getFlags()); 417 UnimplementedError(getFlags());
390 } 418 }
391 419
420 TargetMIPS32::CallingConv::CallingConv()
421 : GPRegsUsed(RegMIPS32::Reg_NUM),
422 GPRArgs(GPRArgInitializer.rbegin(), GPRArgInitializer.rend()),
423 I64Args(I64ArgInitializer.rbegin(), I64ArgInitializer.rend()) {}
424
425 bool TargetMIPS32::CallingConv::argInGPR(Type Ty, RegNumT *Reg) {
426 CfgVector<RegNumT> *Source;
427
428 switch (Ty) {
429 default: {
430 assert(isScalarIntegerType(Ty));
431 Source = &GPRArgs;
432 } break;
433 case IceType_i64: {
434 Source = &I64Args;
435 } break;
436 }
437
438 discardUnavailableGPRsAndTheirAliases(Source);
439
440 if (Source->empty()) {
441 GPRegsUsed.set();
442 return false;
443 }
444
445 *Reg = Source->back();
446 // Note that we don't Source->pop_back() here. This is intentional. Notice how
447 // we mark all of Reg's aliases as Used. So, for the next argument,
448 // Source->back() is marked as unavailable, and it is thus implicitly popped
449 // from the stack.
450 GPRegsUsed |= RegisterAliases[*Reg];
451 return true;
452 }
453
454 // GPR are not packed when passing parameters. Thus, a function foo(i32, i64,
455 // i32) will have the first argument in r0, the second in r2-r3, and the third
456 // on the stack. To model this behavior, whenever we pop a register from Regs,
457 // we remove all of its aliases from the pool of available GPRs. This has the
458 // effect of computing the "closure" on the GPR registers.
459 void TargetMIPS32::CallingConv::discardUnavailableGPRsAndTheirAliases(
460 CfgVector<RegNumT> *Regs) {
461 while (!Regs->empty() && GPRegsUsed[Regs->back()]) {
462 GPRegsUsed |= RegisterAliases[Regs->back()];
463 Regs->pop_back();
464 }
465 }
466
392 void TargetMIPS32::lowerArguments() { 467 void TargetMIPS32::lowerArguments() {
393 VarList &Args = Func->getArgs(); 468 VarList &Args = Func->getArgs();
394 // We are only handling integer registers for now. The Mips o32 ABI is 469 // We are only handling integer registers for now. The Mips o32 ABI is
395 // somewhat complex but will be implemented in its totality through follow 470 // somewhat complex but will be implemented in its totality through follow
396 // on patches. 471 // on patches.
397 // 472 //
398 unsigned NumGPRRegsUsed = 0; 473 unsigned NumGPRRegsUsed = 0;
399 // For each register argument, replace Arg in the argument list with the 474 // For each register argument, replace Arg in the argument list with the
400 // home register. Then generate an instruction in the prolog to copy the 475 // home register. Then generate an instruction in the prolog to copy the
401 // home register to the assigned location of Arg. 476 // home register to the assigned location of Arg.
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after
909 case InstIcmp::Sle: { 984 case InstIcmp::Sle: {
910 _slt(DestT, Src1R, Src0R); 985 _slt(DestT, Src1R, Src0R);
911 _br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ); 986 _br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ);
912 break; 987 break;
913 } 988 }
914 } 989 }
915 } 990 }
916 } 991 }
917 992
918 void TargetMIPS32::lowerCall(const InstCall *Instr) { 993 void TargetMIPS32::lowerCall(const InstCall *Instr) {
919 // TODO(rkotler): assign arguments to registers and stack. Also reserve stack. 994 NeedsStackAlignment = true;
920 if (Instr->getNumArgs()) { 995
921 UnimplementedLoweringError(this, Instr); 996 // Assign arguments to registers and stack. Also reserve stack.
922 return; 997 TargetMIPS32::CallingConv CC;
998
999 // Pair of Arg Operand -> GPR number assignments.
1000 llvm::SmallVector<std::pair<Operand *, RegNumT>, MIPS32_MAX_GPR_ARG> GPRArgs;
1001
1002 // Pair of Arg Operand -> stack offset.
1003 llvm::SmallVector<std::pair<Operand *, int32_t>, 8> StackArgs;
1004 size_t ParameterAreaSizeBytes = 16;
1005
1006 // Classify each argument operand according to the location where the
1007 // argument is passed.
1008
1009 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) {
1010 Operand *Arg = legalizeUndef(Instr->getArg(i));
1011 const Type Ty = Arg->getType();
1012 bool InReg = false;
1013 RegNumT Reg;
1014 if (isScalarIntegerType(Ty)) {
1015 InReg = CC.argInGPR(Ty, &Reg);
1016 } else {
1017 // TODO(mohit.bhakkad) : Handle arguments of type other than
1018 // ScalarIntegerType
1019 UnimplementedLoweringError(this, Instr);
1020 return;
1021 }
1022
1023 if (!InReg) {
1024 ParameterAreaSizeBytes =
1025 applyStackAlignmentTy(ParameterAreaSizeBytes, Ty);
1026 StackArgs.push_back(std::make_pair(Arg, ParameterAreaSizeBytes));
1027 ParameterAreaSizeBytes += typeWidthInBytesOnStack(Ty);
1028 continue;
1029 }
1030
1031 if (Ty == IceType_i64) {
1032 Operand *Lo = loOperand(Arg);
1033 Operand *Hi = hiOperand(Arg);
1034 GPRArgs.push_back(
1035 std::make_pair(Lo, RegMIPS32::getI64PairFirstGPRNum(Reg)));
1036 GPRArgs.push_back(
1037 std::make_pair(Hi, RegMIPS32::getI64PairSecondGPRNum(Reg)));
1038 } else if (isScalarIntegerType(Ty)) {
1039 GPRArgs.push_back(std::make_pair(Arg, Reg));
1040 } else {
1041 // TODO(mohit.bhakkad) : Handle arguments of type other than
1042 // ScalarIntegerType
1043 UnimplementedLoweringError(this, Instr);
1044 return;
1045 }
923 } 1046 }
1047
1048 // Adjust the parameter area so that the stack is aligned. It is assumed that
1049 // the stack is already aligned at the start of the calling sequence.
1050 ParameterAreaSizeBytes = applyStackAlignment(ParameterAreaSizeBytes);
1051
1052 // Copy arguments that are passed on the stack to the appropriate stack
1053 // locations.
1054 Variable *SP = getPhysicalRegister(RegMIPS32::Reg_SP);
1055 for (auto &StackArg : StackArgs) {
1056 ConstantInteger32 *Loc =
1057 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(StackArg.second));
1058 Type Ty = StackArg.first->getType();
1059 OperandMIPS32Mem *Addr;
1060 constexpr bool SignExt = false;
1061 if (OperandMIPS32Mem::canHoldOffset(Ty, SignExt, StackArg.second)) {
1062 Addr = OperandMIPS32Mem::create(Func, Ty, SP, Loc);
1063 } else {
1064 Variable *NewBase = Func->makeVariable(SP->getType());
1065 lowerArithmetic(
1066 InstArithmetic::create(Func, InstArithmetic::Add, NewBase, SP, Loc));
1067 Addr = formMemoryOperand(NewBase, Ty);
1068 }
1069 lowerStore(InstStore::create(Func, StackArg.first, Addr));
1070 }
1071
924 // Generate the call instruction. Assign its result to a temporary with high 1072 // Generate the call instruction. Assign its result to a temporary with high
925 // register allocation weight. 1073 // register allocation weight.
926 Variable *Dest = Instr->getDest(); 1074 Variable *Dest = Instr->getDest();
927 // ReturnReg doubles as ReturnRegLo as necessary. 1075 // ReturnReg doubles as ReturnRegLo as necessary.
928 Variable *ReturnReg = nullptr; 1076 Variable *ReturnReg = nullptr;
929 Variable *ReturnRegHi = nullptr; 1077 Variable *ReturnRegHi = nullptr;
930 if (Dest) { 1078 if (Dest) {
931 switch (Dest->getType()) { 1079 switch (Dest->getType()) {
932 case IceType_NUM: 1080 case IceType_NUM:
933 llvm_unreachable("Invalid Call dest type"); 1081 llvm_unreachable("Invalid Call dest type");
(...skipping 25 matching lines...) Expand all
959 return; 1107 return;
960 } 1108 }
961 } 1109 }
962 Operand *CallTarget = Instr->getCallTarget(); 1110 Operand *CallTarget = Instr->getCallTarget();
963 // Allow ConstantRelocatable to be left alone as a direct call, 1111 // Allow ConstantRelocatable to be left alone as a direct call,
964 // but force other constants like ConstantInteger32 to be in 1112 // but force other constants like ConstantInteger32 to be in
965 // a register and make it an indirect call. 1113 // a register and make it an indirect call.
966 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { 1114 if (!llvm::isa<ConstantRelocatable>(CallTarget)) {
967 CallTarget = legalize(CallTarget, Legal_Reg); 1115 CallTarget = legalize(CallTarget, Legal_Reg);
968 } 1116 }
1117
1118 // Copy arguments to be passed in registers to the appropriate registers.
1119 CfgVector<Variable *> RegArgs;
1120 for (auto &GPRArg : GPRArgs) {
1121 RegArgs.emplace_back(legalizeToReg(GPRArg.first, GPRArg.second));
1122 }
1123
1124 // Generate a FakeUse of register arguments so that they do not get dead code
1125 // eliminated as a result of the FakeKill of scratch registers after the call.
1126 // These fake-uses need to be placed here to avoid argument registers from
1127 // being used during the legalizeToReg() calls above.
1128 for (auto *RegArg : RegArgs) {
1129 Context.insert<InstFakeUse>(RegArg);
1130 }
1131
969 Inst *NewCall = InstMIPS32Call::create(Func, ReturnReg, CallTarget); 1132 Inst *NewCall = InstMIPS32Call::create(Func, ReturnReg, CallTarget);
970 Context.insert(NewCall); 1133 Context.insert(NewCall);
971 if (ReturnRegHi) 1134 if (ReturnRegHi)
972 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); 1135 Context.insert(InstFakeDef::create(Func, ReturnRegHi));
973 // Insert a register-kill pseudo instruction. 1136 // Insert a register-kill pseudo instruction.
974 Context.insert(InstFakeKill::create(Func, NewCall)); 1137 Context.insert(InstFakeKill::create(Func, NewCall));
975 // Generate a FakeUse to keep the call live if necessary. 1138 // Generate a FakeUse to keep the call live if necessary.
976 if (Instr->hasSideEffects() && ReturnReg) { 1139 if (Instr->hasSideEffects() && ReturnReg) {
977 Context.insert<InstFakeDef>(ReturnReg); 1140 Context.insert<InstFakeDef>(ReturnReg);
978 } 1141 }
(...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after
1646 Str << "\t.set\t" 1809 Str << "\t.set\t"
1647 << "nomips16\n"; 1810 << "nomips16\n";
1648 } 1811 }
1649 1812
1650 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; 1813 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM];
1651 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; 1814 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM];
1652 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; 1815 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM];
1653 1816
1654 } // end of namespace MIPS32 1817 } // end of namespace MIPS32
1655 } // end of namespace Ice 1818 } // end of namespace Ice
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698