| Index: src/IceTargetLoweringARM32.h
|
| diff --git a/src/IceTargetLoweringARM32.h b/src/IceTargetLoweringARM32.h
|
| index cf38fe780e3fe7b4c49b5a8adc7492fd9913bb23..e8f2d1aeb0d38e4312f20235049f0ab4adfb910a 100644
|
| --- a/src/IceTargetLoweringARM32.h
|
| +++ b/src/IceTargetLoweringARM32.h
|
| @@ -99,16 +99,15 @@ public:
|
| }
|
| uint32_t getStackAlignment() const override;
|
| void reserveFixedAllocaArea(size_t Size, size_t Align) override {
|
| - // TODO(sehr,jpp): Implement fixed stack layout.
|
| - (void)Size;
|
| - (void)Align;
|
| - llvm::report_fatal_error("Not yet implemented");
|
| + FixedAllocaSizeBytes = Size;
|
| + assert(llvm::isPowerOf2_32(Align));
|
| + FixedAllocaAlignBytes = Align;
|
| + PrologEmitsFixedAllocas = true;
|
| }
|
| int32_t getFrameFixedAllocaOffset() const override {
|
| - // TODO(sehr,jpp): Implement fixed stack layout.
|
| - llvm::report_fatal_error("Not yet implemented");
|
| - return 0;
|
| + return FixedAllocaSizeBytes - (SpillAreaSizeBytes - MaxOutArgsSizeBytes);
|
| }
|
| + uint32_t maxOutArgsSizeBytes() const override { return MaxOutArgsSizeBytes; }
|
|
|
| bool shouldSplitToVariable64On32(Type Ty) const override {
|
| return Ty == IceType_i64;
|
| @@ -250,7 +249,8 @@ protected:
|
| Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister);
|
| static Type stackSlotType();
|
| Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister);
|
| - void alignRegisterPow2(Variable *Reg, uint32_t Align);
|
| + void alignRegisterPow2(Variable *Reg, uint32_t Align,
|
| + int32_t TmpRegNum = Variable::NoRegister);
|
|
|
| /// Returns a vector in a register with the given constant entries.
|
| Variable *makeVectorOfZeros(Type Ty, int32_t RegNum = Variable::NoRegister);
|
| @@ -811,7 +811,7 @@ protected:
|
| }
|
|
|
| // Iterates over the CFG and determines the maximum outgoing stack arguments
|
| - // bytes. This information is later used during addProlog() do pre-allocate
|
| + // bytes. This information is later used during addProlog() to pre-allocate
|
| // the outargs area.
|
| // TODO(jpp): This could live in the Parser, if we provided a Target-specific
|
| // method that the Parser could call.
|
| @@ -852,6 +852,9 @@ protected:
|
| bool NeedsStackAlignment = false;
|
| bool MaybeLeafFunc = true;
|
| size_t SpillAreaSizeBytes = 0;
|
| + size_t FixedAllocaSizeBytes = 0;
|
| + size_t FixedAllocaAlignBytes = 0;
|
| + bool PrologEmitsFixedAllocas = false;
|
| uint32_t MaxOutArgsSizeBytes = 0;
|
| // TODO(jpp): std::array instead of array.
|
| static llvm::SmallBitVector TypeToRegisterSet[RCARM32_NUM];
|
| @@ -970,6 +973,29 @@ private:
|
| };
|
|
|
| BoolComputationTracker BoolComputations;
|
| +
|
| + // AllowTemporaryWithNoReg indicates if TargetARM32::makeReg() can be invoked
|
| + // without specifying a physical register. This is needed for creating unbound
|
| + // temporaries during Ice -> ARM lowering, but before register allocation.
|
| + // This a safe-guard that, during the legalization post-passes no unbound
|
| + // temporaries are created.
|
| + bool AllowTemporaryWithNoReg = true;
|
| + // ForbidTemporaryWithoutReg is a RAII class that manages
|
| + // AllowTemporaryWithNoReg.
|
| + class ForbidTemporaryWithoutReg {
|
| + ForbidTemporaryWithoutReg() = delete;
|
| + ForbidTemporaryWithoutReg(const ForbidTemporaryWithoutReg&) = delete;
|
| + ForbidTemporaryWithoutReg &operator=(const ForbidTemporaryWithoutReg&) = delete;
|
| +
|
| + public:
|
| + explicit ForbidTemporaryWithoutReg(TargetARM32 *Target) : Target(Target) {
|
| + Target->AllowTemporaryWithNoReg = false;
|
| + }
|
| + ~ForbidTemporaryWithoutReg() { Target->AllowTemporaryWithNoReg = true; }
|
| +
|
| + private:
|
| + TargetARM32 *const Target;
|
| + };
|
| };
|
|
|
| class TargetDataARM32 final : public TargetDataLowering {
|
|
|