LLVM: lib/Target/X86/GISel/X86CallLowering.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

46#include

47#include

48

49using namespace llvm;

50

53

54namespace {

55

57private:

59 unsigned NumXMMRegs = 0;

60

61public:

62 uint64_t getStackSize() { return StackSize; }

63 unsigned getNumXmmRegs() { return NumXMMRegs; }

64

65 X86OutgoingValueAssigner(CCAssignFn *AssignFn_)

66 : CallLowering::OutgoingValueAssigner(AssignFn_) {}

67

68 bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT,

70 const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags,

71 CCState &State) override {

72 bool Res = AssignFn(ValNo, ValVT, LocVT, LocInfo, Flags, Info.Ty, State);

74

75 static const MCPhysReg XMMArgRegs[] = {X86::XMM0, X86::XMM1, X86::XMM2,

76 X86::XMM3, X86::XMM4, X86::XMM5,

77 X86::XMM6, X86::XMM7};

78 if (Flags.isVarArg())

80

81 return Res;

82 }

83};

84

86 X86OutgoingValueHandler(MachineIRBuilder &MIRBuilder,

87 MachineRegisterInfo &MRI, MachineInstrBuilder &MIB)

88 : OutgoingValueHandler(MIRBuilder, MRI), MIB(MIB),

89 DL(MIRBuilder.getMF().getDataLayout()),

90 STI(MIRBuilder.getMF().getSubtarget()) {}

91

93 MachinePointerInfo &MPO,

94 ISD::ArgFlagsTy Flags) override {

96 LLT SType = LLT::scalar(DL.getPointerSizeInBits(0));

98 MIRBuilder.buildCopy(p0, STI.getRegisterInfo()->getStackRegister());

99

100 auto OffsetReg = MIRBuilder.buildConstant(SType, Offset);

101

102 auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg);

103

105 return AddrReg.getReg(0);

106 }

107

109 const CCValAssign &VA) override {

111 Register ExtReg = extendRegister(ValVReg, VA);

112 MIRBuilder.buildCopy(PhysReg, ExtReg);

113 }

114

115 void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,

116 const MachinePointerInfo &MPO,

117 const CCValAssign &VA) override {

118 MachineFunction &MF = MIRBuilder.getMF();

119 Register ExtReg = extendRegister(ValVReg, VA);

120

123 MIRBuilder.buildStore(ExtReg, Addr, *MMO);

124 }

125

126protected:

127 MachineInstrBuilder &MIB;

128 const DataLayout &DL;

129 const X86Subtarget &STI;

130};

131

132}

133

139 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);

141}

142

146 assert(((Val && !VRegs.empty()) || (!Val && VRegs.empty())) &&

147 "Return value without a vreg");

152 Register RetReg = STI.is64Bit() ? X86::RAX : X86::EAX;

153

158 } else if (Register Reg = FuncInfo->getSRetReturnReg()) {

159 MIRBuilder.buildCopy(RetReg, Reg);

161 } else if (!VRegs.empty()) {

165

167 setArgFlags(OrigRetInfo, AttributeList::ReturnIndex, DL, F);

168

171

172 X86OutgoingValueAssigner Assigner(RetCC_X86);

173 X86OutgoingValueHandler Handler(MIRBuilder, MRI, MIB);

175 MIRBuilder, F.getCallingConv(),

176 F.isVarArg()))

177 return false;

178 }

179

181 return true;

182}

183

184namespace {

185

189 : IncomingValueHandler(MIRBuilder, MRI),

190 DL(MIRBuilder.getMF().getDataLayout()) {}

191

195 auto &MFI = MIRBuilder.getMF().getFrameInfo();

196

197

198

199 const bool IsImmutable = !Flags.isByVal();

200

201 int FI = MFI.CreateFixedObject(Size, Offset, IsImmutable);

203

204 return MIRBuilder

205 .buildFrameIndex(LLT::pointer(0, DL.getPointerSizeInBits(0)), FI)

206 .getReg(0);

207 }

208

209 void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,

210 const MachinePointerInfo &MPO,

211 const CCValAssign &VA) override {

212 MachineFunction &MF = MIRBuilder.getMF();

216 MIRBuilder.buildLoad(ValVReg, Addr, *MMO);

217 }

218

220 const CCValAssign &VA) override {

221 markPhysRegUsed(PhysReg.asMCReg());

222 IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA);

223 }

224

225

226

227

228 virtual void markPhysRegUsed(MCRegister PhysReg) = 0;

229

230protected:

231 const DataLayout &DL;

232};

233

237

238 void markPhysRegUsed(MCRegister PhysReg) override {

239 MIRBuilder.getMRI()->addLiveIn(PhysReg);

240 MIRBuilder.getMBB().addLiveIn(PhysReg);

241 }

242};

243

244struct CallReturnHandler : public X86IncomingValueHandler {

245 CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,

246 MachineInstrBuilder &MIB)

247 : X86IncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {}

248

249 void markPhysRegUsed(MCRegister PhysReg) override {

251 }

252

253protected:

254 MachineInstrBuilder &MIB;

255};

256

257}

258

267

269

272

273

274 if (F.isVarArg())

275 return false;

276

277 unsigned Idx = 0;

278 for (const auto &Arg : F.args()) {

279

280 if (Arg.hasAttribute(Attribute::ByVal) ||

281 Arg.hasAttribute(Attribute::InReg) ||

282 Arg.hasAttribute(Attribute::SwiftSelf) ||

283 Arg.hasAttribute(Attribute::SwiftError) || VRegs[Idx].size() > 1)

284 return false;

285

286 if (Arg.hasAttribute(Attribute::StructRet)) {

288 "Unexpected amount of registers for sret argument.");

289 FuncInfo->setSRetReturnReg(VRegs[Idx][0]);

290 }

291

292 ArgInfo OrigArg(VRegs[Idx], Arg.getType(), Idx);

293 setArgFlags(OrigArg, Idx + AttributeList::FirstArgIndex, DL, F);

295 Idx++;

296 }

297

298 if (SplitArgs.empty())

299 return true;

300

302 if (MBB.empty())

304

305 X86OutgoingValueAssigner Assigner(CC_X86);

308 F.getCallingConv(), F.isVarArg()))

309 return false;

310

311

313

314 return true;

315}

316

326

327

330 return false;

331

332 unsigned AdjStackDown = TII.getCallFrameSetupOpcode();

333 auto CallSeqStart = MIRBuilder.buildInstr(AdjStackDown);

334

335

336

337 bool Is64Bit = STI.is64Bit();

338 unsigned CallOpc = Info.Callee.isReg()

339 ? (Is64Bit ? X86::CALL64r : X86::CALL32r)

340 : (Is64Bit ? X86::CALL64pcrel32 : X86::CALLpcrel32);

341

343 .add(Info.Callee)

344 .addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv));

345

347 for (const auto &OrigArg : Info.OrigArgs) {

348

349

350 if (OrigArg.Flags[0].isByVal())

351 return false;

352

353 if (OrigArg.Regs.size() > 1)

354 return false;

355

357 }

358

359 X86OutgoingValueAssigner Assigner(CC_X86);

360 X86OutgoingValueHandler Handler(MIRBuilder, MRI, MIB);

362 Info.CallConv, Info.IsVarArg))

363 return false;

364

365 bool IsFixed =

366 Info.OrigArgs.empty() ? true : !Info.OrigArgs.back().Flags[0].isVarArg();

367 if (STI.is64Bit() && !IsFixed && !STI.isCallingConvWin64(Info.CallConv)) {

368

369

370

371

372

373

374

375

378 .addImm(Assigner.getNumXmmRegs());

380 }

381

382

384

385

386

387

388 if (Info.Callee.isReg())

392 0));

393

394

395

396

397

398 if (Info.CanLowerReturn && !Info.OrigRet.Ty->isVoidTy()) {

399 if (Info.OrigRet.Regs.size() > 1)

400 return false;

401

402 SplitArgs.clear();

404

406

407 X86OutgoingValueAssigner Assigner(RetCC_X86);

408 CallReturnHandler Handler(MIRBuilder, MRI, MIB);

410 Info.CallConv, Info.IsVarArg))

411 return false;

412

413 if (!NewRegs.empty())

415 }

416

417 CallSeqStart.addImm(Assigner.getStackSize())

418 .addImm(0 )

419 .addImm(0 );

420

421 unsigned AdjStackUp = TII.getCallFrameDestroyOpcode();

423 .addImm(Assigner.getStackSize())

424 .addImm(0 );

425

426 if (!Info.CanLowerReturn)

427 insertSRetLoads(MIRBuilder, Info.OrigRet.Ty, Info.OrigRet.Regs,

428 Info.DemoteRegister, Info.DemoteStackIndex);

429

430 return true;

431}

unsigned const MachineRegisterInfo * MRI

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

const TargetInstrInfo & TII

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

This file contains the simple types necessary to represent the attributes associated with functions a...

Analysis containing CSE Info

Implement a low-level type suitable for MachineInstr level instruction selection.

Implement a low-level type suitable for MachineInstr level instruction selection.

This file declares the MachineIRBuilder class.

Register const TargetRegisterInfo * TRI

Promote Memory to Register

static constexpr MCPhysReg SPReg

This file defines the SmallVector class.

This file describes how to lower LLVM calls to machine code calls.

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

bool empty() const

empty - Check if the array is empty.

CCState - This class holds information needed while lowering arguments and return values.

unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const

getFirstUnallocated - Return the index of the first unallocated register in the set,...

uint64_t getStackSize() const

Returns the size of the currently allocated portion of the stack.

void insertSRetLoads(MachineIRBuilder &MIRBuilder, Type *RetTy, ArrayRef< Register > VRegs, Register DemoteReg, int FI) const

Load the returned value from the stack into virtual registers in VRegs.

void splitToValueTypes(const ArgInfo &OrigArgInfo, SmallVectorImpl< ArgInfo > &SplitArgs, const DataLayout &DL, CallingConv::ID CallConv, SmallVectorImpl< uint64_t > *Offsets=nullptr) const

Break OrigArgInfo into one or more pieces the calling convention can process, returned in SplitArgs.

void insertSRetIncomingArgument(const Function &F, SmallVectorImpl< ArgInfo > &SplitArgs, Register &DemoteReg, MachineRegisterInfo &MRI, const DataLayout &DL) const

Insert the hidden sret ArgInfo to the beginning of SplitArgs.

bool determineAndHandleAssignments(ValueHandler &Handler, ValueAssigner &Assigner, SmallVectorImpl< ArgInfo > &Args, MachineIRBuilder &MIRBuilder, CallingConv::ID CallConv, bool IsVarArg, ArrayRef< Register > ThisReturnRegs={}) const

Invoke ValueAssigner::assignArg on each of the given Args and then use Handler to move them to the as...

void insertSRetStores(MachineIRBuilder &MIRBuilder, Type *RetTy, ArrayRef< Register > VRegs, Register DemoteReg) const

Store the return value given by VRegs into stack starting at the offset specified in DemoteReg.

bool checkReturn(CCState &CCInfo, SmallVectorImpl< BaseArgInfo > &Outs, CCAssignFn *Fn) const

CallLowering(const TargetLowering *TLI)

void setArgFlags(ArgInfo &Arg, unsigned OpIdx, const DataLayout &DL, const FuncInfoTy &FuncInfo) const

A parsed version of the target data layout string in and methods for querying it.

FormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)

FunctionLoweringInfo - This contains information that is global to a function that is used when lower...

Register DemoteRegister

DemoteRegister - if CanLowerReturn is false, DemoteRegister is a vreg allocated to hold a pointer to ...

bool CanLowerReturn

CanLowerReturn - true iff the function's return value can be lowered to registers.

LLVMContext & getContext() const

getContext - Return a reference to the LLVMContext associated with this function.

static constexpr LLT scalar(unsigned SizeInBits)

Get a low-level scalar or aggregate "bag of bits".

static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)

Get a low-level pointer in the given address space.

This is an important class for using LLVM in a threaded context.

const TargetSubtargetInfo & getSubtarget() const

getSubtarget - Return the subtarget for which this machine code is being compiled.

MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)

getMachineMemOperand - Allocate a new MachineMemOperand.

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

const DataLayout & getDataLayout() const

Return the DataLayout attached to the Module associated to this MF.

Function & getFunction()

Return the LLVM function that this machine code represents.

Ty * getInfo()

getInfo - Keep track of various per-function pieces of information for backends that would like to do...

Helper class to build MachineInstr.

MachineInstrBuilder insertInstr(MachineInstrBuilder MIB)

Insert an existing instruction at the insertion point.

void setInstr(MachineInstr &MI)

Set the insertion point to before MI.

MachineInstrBuilder buildMergeLikeInstr(const DstOp &Res, ArrayRef< Register > Ops)

Build and insert Res = G_MERGE_VALUES Op0, ... or Res = G_BUILD_VECTOR Op0, ... or Res = G_CONCAT_VEC...

MachineInstrBuilder buildInstr(unsigned Opcode)

Build and insert = Opcode .

MachineFunction & getMF()

Getter for the function we currently build.

const MachineBasicBlock & getMBB() const

Getter for the basic block we currently build.

void setMBB(MachineBasicBlock &MBB)

Set the insertion point to the end of MBB.

MachineInstrBuilder buildInstrNoInsert(unsigned Opcode)

Build but don't insert = Opcode .

MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)

Build and insert Res = COPY Op.

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

const MachineInstrBuilder & add(const MachineOperand &MO) const

const MachineInstrBuilder & addRegMask(const uint32_t *Mask) const

const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const

Add a new virtual register operand.

const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const

Add a virtual register use operand.

const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const

Add a virtual register definition operand.

const MachineOperand & getOperand(unsigned i) const

@ MOLoad

The memory access reads data.

@ MOInvariant

The memory access always returns the same value (or traps).

@ MOStore

The memory access writes data.

LLVM_ABI void setReg(Register Reg)

Change the register this operand corresponds to.

MachineRegisterInfo - Keep track of information for virtual and physical registers,...

Wrapper class representing virtual and physical registers.

MCRegister asMCReg() const

Utility to check-convert this value to a MCRegister.

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

TargetInstrInfo - Interface to description of machine instruction set.

virtual const RegisterBankInfo * getRegBankInfo() const

If the information for the register banks is available, return it.

virtual const TargetInstrInfo * getInstrInfo() const

LLVM Value Representation.

Type * getType() const

All values are typed, get the type of this value.

X86CallLowering(const X86TargetLowering &TLI)

Definition X86CallLowering.cpp:51

bool lowerCall(MachineIRBuilder &MIRBuilder, CallLoweringInfo &Info) const override

This hook must be implemented to lower the given call instruction, including argument and return valu...

Definition X86CallLowering.cpp:317

bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, ArrayRef< Register > VRegs, FunctionLoweringInfo &FLI) const override

This hook behaves as the extended lowerReturn function, but for targets that do not support swifterro...

Definition X86CallLowering.cpp:143

bool canLowerReturn(MachineFunction &MF, CallingConv::ID CallConv, SmallVectorImpl< BaseArgInfo > &Outs, bool IsVarArg) const override

This hook must be implemented to check whether the return values described by Outs can fit into the r...

Definition X86CallLowering.cpp:134

bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, ArrayRef< ArrayRef< Register > > VRegs, FunctionLoweringInfo &FLI) const override

This hook must be implemented to lower the incoming (formal) arguments, described by VRegs,...

Definition X86CallLowering.cpp:259

X86MachineFunctionInfo - This class is derived from MachineFunction and contains private X86 target-s...

const X86InstrInfo * getInstrInfo() const override

bool isCallingConvWin64(CallingConv::ID CC) const

const X86RegisterInfo * getRegisterInfo() const override

bool isTargetLinux() const

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

@ X86_64_SysV

The C convention as specified in the x86-64 supplement to the System V ABI, used on most non-Windows ...

@ C

The default llvm calling convention, compatible with C.

@ Implicit

Not emitted register (e.g. carry, or temporary result).

This is an optimization pass for GlobalISel generic memory operations.

LLVM_ABI Register constrainOperandRegClass(const MachineFunction &MF, const TargetRegisterInfo &TRI, MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const TargetRegisterClass &RegClass, MachineOperand &RegMO)

Constrain the Register operand OpIdx, so that it is now constrained to the TargetRegisterClass passed...

auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)

Get the size of a range.

bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)

CCAssignFn - This function assigns a location for Val, updating State to reflect the change.

uint16_t MCPhysReg

An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...

bool CC_X86(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)

bool RetCC_X86(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)

LLVM_ABI Align inferAlignFromPtrInfo(MachineFunction &MF, const MachinePointerInfo &MPO)

Base class for ValueHandlers used for arguments coming into the current function, or for return value...

Base class for ValueHandlers used for arguments passed to a function call, or for return values.

MachineIRBuilder & MIRBuilder

MachineRegisterInfo & MRI

This class contains a discriminated union of information about pointers in memory operands,...

static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)

Stack pointer relative access.

static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)

Return a MachinePointerInfo record that refers to the specified FrameIndex.