2014-02-28 18:00:38 +08:00
|
|
|
//===-- MipsNaClELFStreamer.cpp - ELF Object Output for Mips NaCl ---------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2014-02-28 18:00:38 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements MCELFStreamer for Mips NaCl. It emits .o object files
|
|
|
|
// as required by NaCl's SFI sandbox. It inserts address-masking instructions
|
2014-03-11 04:34:23 +08:00
|
|
|
// before dangerous control-flow and memory access instructions. It inserts
|
|
|
|
// address-masking instructions after instructions that change the stack
|
|
|
|
// pointer. It ensures that the mask and the dangerous instruction are always
|
2014-03-12 05:23:40 +08:00
|
|
|
// emitted in the same bundle. It aligns call + branch delay to the bundle end,
|
|
|
|
// so that return address is always aligned to the start of next bundle.
|
2014-02-28 18:00:38 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "Mips.h"
|
2014-03-27 19:52:20 +08:00
|
|
|
#include "MipsELFStreamer.h"
|
2014-02-28 18:00:38 +08:00
|
|
|
#include "MipsMCNaCl.h"
|
2017-10-11 09:57:21 +08:00
|
|
|
#include "llvm/MC/MCAsmBackend.h"
|
2017-02-01 09:22:51 +08:00
|
|
|
#include "llvm/MC/MCAssembler.h"
|
2017-10-12 07:34:47 +08:00
|
|
|
#include "llvm/MC/MCCodeEmitter.h"
|
2014-02-28 18:00:38 +08:00
|
|
|
#include "llvm/MC/MCELFStreamer.h"
|
2017-02-01 09:22:51 +08:00
|
|
|
#include "llvm/MC/MCInst.h"
|
2018-05-19 02:26:45 +08:00
|
|
|
#include "llvm/MC/MCObjectWriter.h"
|
2017-02-01 09:22:51 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
#include <cassert>
|
2014-02-28 18:00:38 +08:00
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
2014-04-22 10:41:26 +08:00
|
|
|
#define DEBUG_TYPE "mips-mc-nacl"
|
|
|
|
|
2014-02-28 18:00:38 +08:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
const unsigned IndirectBranchMaskReg = Mips::T6;
|
2014-03-11 04:34:23 +08:00
|
|
|
const unsigned LoadStoreStackMaskReg = Mips::T7;
|
2014-02-28 18:00:38 +08:00
|
|
|
|
|
|
|
/// Extend the generic MCELFStreamer class so that it can mask dangerous
|
|
|
|
/// instructions.
|
|
|
|
|
2014-03-27 19:52:20 +08:00
|
|
|
class MipsNaClELFStreamer : public MipsELFStreamer {
|
2014-02-28 18:00:38 +08:00
|
|
|
public:
|
2017-10-11 09:57:21 +08:00
|
|
|
MipsNaClELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
|
2018-05-19 02:26:45 +08:00
|
|
|
std::unique_ptr<MCObjectWriter> OW,
|
2017-10-12 07:34:47 +08:00
|
|
|
std::unique_ptr<MCCodeEmitter> Emitter)
|
2018-05-19 02:26:45 +08:00
|
|
|
: MipsELFStreamer(Context, std::move(TAB), std::move(OW),
|
|
|
|
std::move(Emitter)) {}
|
2014-02-28 18:00:38 +08:00
|
|
|
|
2017-02-01 09:22:51 +08:00
|
|
|
~MipsNaClELFStreamer() override = default;
|
2014-02-28 18:00:38 +08:00
|
|
|
|
|
|
|
private:
|
2014-03-12 05:23:40 +08:00
|
|
|
// Whether we started the sandboxing sequence for calls. Calls are bundled
|
|
|
|
// with branch delays and aligned to the bundle end.
|
2017-02-01 09:22:51 +08:00
|
|
|
bool PendingCall = false;
|
2014-03-12 05:23:40 +08:00
|
|
|
|
2014-02-28 18:00:38 +08:00
|
|
|
bool isIndirectJump(const MCInst &MI) {
|
[mips][mips64r6] Use JALR for returns instead of JR (which is not available on MIPS32r6/MIPS64r6)
Summary:
RET, and RET_MM have been replaced by a pseudo named PseudoReturn.
In addition a version with a 64-bit GPR named PseudoReturn64 has been
added.
Instruction selection for a return matches RetRA, which is expanded post
register allocation to PseudoReturn/PseudoReturn64. During MipsAsmPrinter,
this PseudoReturn/PseudoReturn64 are emitted as:
- (JALR64 $zero, $rs) on MIPS64r6
- (JALR $zero, $rs) on MIPS32r6
- (JR_MM $rs) on microMIPS
- (JR $rs) otherwise
On MIPS32r6/MIPS64r6, 'jr $rs' is an alias for 'jalr $zero, $rs'. To aid
development and review (specifically, to ensure all cases of jr are
updated), these aliases are temporarily named 'r6.jr' instead of 'jr'.
A follow up patch will change them back to the correct mnemonic.
Added (JALR $zero, $rs) to MipsNaClELFStreamer's definition of an indirect
jump, and removed it from its definition of a call.
Note: I haven't accounted for MIPS64 in MipsNaClELFStreamer since it's
doesn't appear to account for any MIPS64-specifics.
The return instruction created as part of eh_return expansion is now expanded
using expandRetRA() so we use the right return instruction on MIPS32r6/MIPS64r6
('jalr $zero, $rs').
Also, fixed a misuse of isABI_N64() to detect 64-bit wide registers in
expandEhReturn().
Reviewers: jkolek, vmedic, mseaborn, zoran.jovanovic, dsanders
Reviewed By: dsanders
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D4268
llvm-svn: 212604
2014-07-09 18:16:07 +08:00
|
|
|
if (MI.getOpcode() == Mips::JALR) {
|
|
|
|
// MIPS32r6/MIPS64r6 doesn't have a JR instruction and uses JALR instead.
|
|
|
|
// JALR is an indirect branch if the link register is $0.
|
|
|
|
assert(MI.getOperand(0).isReg());
|
|
|
|
return MI.getOperand(0).getReg() == Mips::ZERO;
|
|
|
|
}
|
|
|
|
return MI.getOpcode() == Mips::JR;
|
2014-02-28 18:00:38 +08:00
|
|
|
}
|
|
|
|
|
2014-03-11 04:34:23 +08:00
|
|
|
bool isStackPointerFirstOperand(const MCInst &MI) {
|
|
|
|
return (MI.getNumOperands() > 0 && MI.getOperand(0).isReg()
|
|
|
|
&& MI.getOperand(0).getReg() == Mips::SP);
|
|
|
|
}
|
|
|
|
|
[mips][mips64r6] Use JALR for returns instead of JR (which is not available on MIPS32r6/MIPS64r6)
Summary:
RET, and RET_MM have been replaced by a pseudo named PseudoReturn.
In addition a version with a 64-bit GPR named PseudoReturn64 has been
added.
Instruction selection for a return matches RetRA, which is expanded post
register allocation to PseudoReturn/PseudoReturn64. During MipsAsmPrinter,
this PseudoReturn/PseudoReturn64 are emitted as:
- (JALR64 $zero, $rs) on MIPS64r6
- (JALR $zero, $rs) on MIPS32r6
- (JR_MM $rs) on microMIPS
- (JR $rs) otherwise
On MIPS32r6/MIPS64r6, 'jr $rs' is an alias for 'jalr $zero, $rs'. To aid
development and review (specifically, to ensure all cases of jr are
updated), these aliases are temporarily named 'r6.jr' instead of 'jr'.
A follow up patch will change them back to the correct mnemonic.
Added (JALR $zero, $rs) to MipsNaClELFStreamer's definition of an indirect
jump, and removed it from its definition of a call.
Note: I haven't accounted for MIPS64 in MipsNaClELFStreamer since it's
doesn't appear to account for any MIPS64-specifics.
The return instruction created as part of eh_return expansion is now expanded
using expandRetRA() so we use the right return instruction on MIPS32r6/MIPS64r6
('jalr $zero, $rs').
Also, fixed a misuse of isABI_N64() to detect 64-bit wide registers in
expandEhReturn().
Reviewers: jkolek, vmedic, mseaborn, zoran.jovanovic, dsanders
Reviewed By: dsanders
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D4268
llvm-svn: 212604
2014-07-09 18:16:07 +08:00
|
|
|
bool isCall(const MCInst &MI, bool *IsIndirectCall) {
|
|
|
|
unsigned Opcode = MI.getOpcode();
|
|
|
|
|
2014-03-12 05:23:40 +08:00
|
|
|
*IsIndirectCall = false;
|
|
|
|
|
|
|
|
switch (Opcode) {
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
|
|
|
|
case Mips::JAL:
|
2014-06-13 21:02:52 +08:00
|
|
|
case Mips::BAL:
|
2014-03-12 05:23:40 +08:00
|
|
|
case Mips::BAL_BR:
|
|
|
|
case Mips::BLTZAL:
|
|
|
|
case Mips::BGEZAL:
|
|
|
|
return true;
|
|
|
|
|
|
|
|
case Mips::JALR:
|
[mips][mips64r6] Use JALR for returns instead of JR (which is not available on MIPS32r6/MIPS64r6)
Summary:
RET, and RET_MM have been replaced by a pseudo named PseudoReturn.
In addition a version with a 64-bit GPR named PseudoReturn64 has been
added.
Instruction selection for a return matches RetRA, which is expanded post
register allocation to PseudoReturn/PseudoReturn64. During MipsAsmPrinter,
this PseudoReturn/PseudoReturn64 are emitted as:
- (JALR64 $zero, $rs) on MIPS64r6
- (JALR $zero, $rs) on MIPS32r6
- (JR_MM $rs) on microMIPS
- (JR $rs) otherwise
On MIPS32r6/MIPS64r6, 'jr $rs' is an alias for 'jalr $zero, $rs'. To aid
development and review (specifically, to ensure all cases of jr are
updated), these aliases are temporarily named 'r6.jr' instead of 'jr'.
A follow up patch will change them back to the correct mnemonic.
Added (JALR $zero, $rs) to MipsNaClELFStreamer's definition of an indirect
jump, and removed it from its definition of a call.
Note: I haven't accounted for MIPS64 in MipsNaClELFStreamer since it's
doesn't appear to account for any MIPS64-specifics.
The return instruction created as part of eh_return expansion is now expanded
using expandRetRA() so we use the right return instruction on MIPS32r6/MIPS64r6
('jalr $zero, $rs').
Also, fixed a misuse of isABI_N64() to detect 64-bit wide registers in
expandEhReturn().
Reviewers: jkolek, vmedic, mseaborn, zoran.jovanovic, dsanders
Reviewed By: dsanders
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D4268
llvm-svn: 212604
2014-07-09 18:16:07 +08:00
|
|
|
// JALR is only a call if the link register is not $0. Otherwise it's an
|
|
|
|
// indirect branch.
|
|
|
|
assert(MI.getOperand(0).isReg());
|
|
|
|
if (MI.getOperand(0).getReg() == Mips::ZERO)
|
|
|
|
return false;
|
|
|
|
|
2014-03-12 05:23:40 +08:00
|
|
|
*IsIndirectCall = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-28 18:00:38 +08:00
|
|
|
void emitMask(unsigned AddrReg, unsigned MaskReg,
|
|
|
|
const MCSubtargetInfo &STI) {
|
|
|
|
MCInst MaskInst;
|
|
|
|
MaskInst.setOpcode(Mips::AND);
|
2015-05-14 02:37:00 +08:00
|
|
|
MaskInst.addOperand(MCOperand::createReg(AddrReg));
|
|
|
|
MaskInst.addOperand(MCOperand::createReg(AddrReg));
|
|
|
|
MaskInst.addOperand(MCOperand::createReg(MaskReg));
|
2020-02-14 13:58:16 +08:00
|
|
|
MipsELFStreamer::emitInstruction(MaskInst, STI);
|
2014-02-28 18:00:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Sandbox indirect branch or return instruction by inserting mask operation
|
|
|
|
// before it.
|
|
|
|
void sandboxIndirectJump(const MCInst &MI, const MCSubtargetInfo &STI) {
|
|
|
|
unsigned AddrReg = MI.getOperand(0).getReg();
|
|
|
|
|
2020-02-16 00:52:56 +08:00
|
|
|
emitBundleLock(false);
|
2014-02-28 18:00:38 +08:00
|
|
|
emitMask(AddrReg, IndirectBranchMaskReg, STI);
|
2020-02-14 13:58:16 +08:00
|
|
|
MipsELFStreamer::emitInstruction(MI, STI);
|
2020-02-16 00:52:56 +08:00
|
|
|
emitBundleUnlock();
|
2014-02-28 18:00:38 +08:00
|
|
|
}
|
|
|
|
|
2014-03-11 04:34:23 +08:00
|
|
|
// Sandbox memory access or SP change. Insert mask operation before and/or
|
|
|
|
// after the instruction.
|
|
|
|
void sandboxLoadStoreStackChange(const MCInst &MI, unsigned AddrIdx,
|
|
|
|
const MCSubtargetInfo &STI, bool MaskBefore,
|
|
|
|
bool MaskAfter) {
|
2020-02-16 00:52:56 +08:00
|
|
|
emitBundleLock(false);
|
2014-03-11 04:34:23 +08:00
|
|
|
if (MaskBefore) {
|
|
|
|
// Sandbox memory access.
|
|
|
|
unsigned BaseReg = MI.getOperand(AddrIdx).getReg();
|
|
|
|
emitMask(BaseReg, LoadStoreStackMaskReg, STI);
|
|
|
|
}
|
2020-02-14 13:58:16 +08:00
|
|
|
MipsELFStreamer::emitInstruction(MI, STI);
|
2014-03-11 04:34:23 +08:00
|
|
|
if (MaskAfter) {
|
|
|
|
// Sandbox SP change.
|
|
|
|
unsigned SPReg = MI.getOperand(0).getReg();
|
|
|
|
assert((Mips::SP == SPReg) && "Unexpected stack-pointer register.");
|
|
|
|
emitMask(SPReg, LoadStoreStackMaskReg, STI);
|
|
|
|
}
|
2020-02-16 00:52:56 +08:00
|
|
|
emitBundleUnlock();
|
2014-03-11 04:34:23 +08:00
|
|
|
}
|
|
|
|
|
2014-02-28 18:00:38 +08:00
|
|
|
public:
|
|
|
|
/// This function is the one used to emit instruction data into the ELF
|
|
|
|
/// streamer. We override it to mask dangerous instructions.
|
2020-02-14 13:58:16 +08:00
|
|
|
void emitInstruction(const MCInst &Inst,
|
2019-02-04 20:51:26 +08:00
|
|
|
const MCSubtargetInfo &STI) override {
|
2014-03-11 04:34:23 +08:00
|
|
|
// Sandbox indirect jumps.
|
|
|
|
if (isIndirectJump(Inst)) {
|
2014-03-12 05:23:40 +08:00
|
|
|
if (PendingCall)
|
|
|
|
report_fatal_error("Dangerous instruction in branch delay slot!");
|
2014-02-28 18:00:38 +08:00
|
|
|
sandboxIndirectJump(Inst, STI);
|
2014-03-11 04:34:23 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sandbox loads, stores and SP changes.
|
2020-01-07 02:24:53 +08:00
|
|
|
unsigned AddrIdx = 0;
|
|
|
|
bool IsStore = false;
|
2014-03-11 04:34:23 +08:00
|
|
|
bool IsMemAccess = isBasePlusOffsetMemoryAccess(Inst.getOpcode(), &AddrIdx,
|
|
|
|
&IsStore);
|
|
|
|
bool IsSPFirstOperand = isStackPointerFirstOperand(Inst);
|
|
|
|
if (IsMemAccess || IsSPFirstOperand) {
|
|
|
|
bool MaskBefore = (IsMemAccess
|
|
|
|
&& baseRegNeedsLoadStoreMask(Inst.getOperand(AddrIdx)
|
|
|
|
.getReg()));
|
|
|
|
bool MaskAfter = IsSPFirstOperand && !IsStore;
|
2014-06-09 22:09:28 +08:00
|
|
|
if (MaskBefore || MaskAfter) {
|
|
|
|
if (PendingCall)
|
|
|
|
report_fatal_error("Dangerous instruction in branch delay slot!");
|
2014-03-11 04:34:23 +08:00
|
|
|
sandboxLoadStoreStackChange(Inst, AddrIdx, STI, MaskBefore, MaskAfter);
|
2014-06-09 22:09:28 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
// fallthrough
|
2014-03-11 04:34:23 +08:00
|
|
|
}
|
|
|
|
|
2014-03-12 05:23:40 +08:00
|
|
|
// Sandbox calls by aligning call and branch delay to the bundle end.
|
|
|
|
// For indirect calls, emit the mask before the call.
|
|
|
|
bool IsIndirectCall;
|
[mips][mips64r6] Use JALR for returns instead of JR (which is not available on MIPS32r6/MIPS64r6)
Summary:
RET, and RET_MM have been replaced by a pseudo named PseudoReturn.
In addition a version with a 64-bit GPR named PseudoReturn64 has been
added.
Instruction selection for a return matches RetRA, which is expanded post
register allocation to PseudoReturn/PseudoReturn64. During MipsAsmPrinter,
this PseudoReturn/PseudoReturn64 are emitted as:
- (JALR64 $zero, $rs) on MIPS64r6
- (JALR $zero, $rs) on MIPS32r6
- (JR_MM $rs) on microMIPS
- (JR $rs) otherwise
On MIPS32r6/MIPS64r6, 'jr $rs' is an alias for 'jalr $zero, $rs'. To aid
development and review (specifically, to ensure all cases of jr are
updated), these aliases are temporarily named 'r6.jr' instead of 'jr'.
A follow up patch will change them back to the correct mnemonic.
Added (JALR $zero, $rs) to MipsNaClELFStreamer's definition of an indirect
jump, and removed it from its definition of a call.
Note: I haven't accounted for MIPS64 in MipsNaClELFStreamer since it's
doesn't appear to account for any MIPS64-specifics.
The return instruction created as part of eh_return expansion is now expanded
using expandRetRA() so we use the right return instruction on MIPS32r6/MIPS64r6
('jalr $zero, $rs').
Also, fixed a misuse of isABI_N64() to detect 64-bit wide registers in
expandEhReturn().
Reviewers: jkolek, vmedic, mseaborn, zoran.jovanovic, dsanders
Reviewed By: dsanders
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D4268
llvm-svn: 212604
2014-07-09 18:16:07 +08:00
|
|
|
if (isCall(Inst, &IsIndirectCall)) {
|
2014-03-12 05:23:40 +08:00
|
|
|
if (PendingCall)
|
|
|
|
report_fatal_error("Dangerous instruction in branch delay slot!");
|
|
|
|
|
|
|
|
// Start the sandboxing sequence by emitting call.
|
2020-02-16 00:52:56 +08:00
|
|
|
emitBundleLock(true);
|
2014-03-12 05:23:40 +08:00
|
|
|
if (IsIndirectCall) {
|
|
|
|
unsigned TargetReg = Inst.getOperand(1).getReg();
|
|
|
|
emitMask(TargetReg, IndirectBranchMaskReg, STI);
|
|
|
|
}
|
2020-02-14 13:58:16 +08:00
|
|
|
MipsELFStreamer::emitInstruction(Inst, STI);
|
2014-03-12 05:23:40 +08:00
|
|
|
PendingCall = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (PendingCall) {
|
|
|
|
// Finish the sandboxing sequence by emitting branch delay.
|
2020-02-14 13:58:16 +08:00
|
|
|
MipsELFStreamer::emitInstruction(Inst, STI);
|
2020-02-16 00:52:56 +08:00
|
|
|
emitBundleUnlock();
|
2014-03-12 05:23:40 +08:00
|
|
|
PendingCall = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-03-11 04:34:23 +08:00
|
|
|
// None of the sandboxing applies, just emit the instruction.
|
2020-02-14 13:58:16 +08:00
|
|
|
MipsELFStreamer::emitInstruction(Inst, STI);
|
2014-02-28 18:00:38 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // end anonymous namespace
|
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
|
2014-03-11 04:34:23 +08:00
|
|
|
bool isBasePlusOffsetMemoryAccess(unsigned Opcode, unsigned *AddrIdx,
|
|
|
|
bool *IsStore) {
|
|
|
|
if (IsStore)
|
|
|
|
*IsStore = false;
|
|
|
|
|
|
|
|
switch (Opcode) {
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Load instructions with base address register in position 1.
|
|
|
|
case Mips::LB:
|
|
|
|
case Mips::LBu:
|
|
|
|
case Mips::LH:
|
|
|
|
case Mips::LHu:
|
|
|
|
case Mips::LW:
|
|
|
|
case Mips::LWC1:
|
|
|
|
case Mips::LDC1:
|
|
|
|
case Mips::LL:
|
2014-06-16 21:13:03 +08:00
|
|
|
case Mips::LL_R6:
|
2014-03-11 04:34:23 +08:00
|
|
|
case Mips::LWL:
|
|
|
|
case Mips::LWR:
|
|
|
|
*AddrIdx = 1;
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Store instructions with base address register in position 1.
|
|
|
|
case Mips::SB:
|
|
|
|
case Mips::SH:
|
|
|
|
case Mips::SW:
|
|
|
|
case Mips::SWC1:
|
|
|
|
case Mips::SDC1:
|
|
|
|
case Mips::SWL:
|
|
|
|
case Mips::SWR:
|
|
|
|
*AddrIdx = 1;
|
|
|
|
if (IsStore)
|
|
|
|
*IsStore = true;
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Store instructions with base address register in position 2.
|
|
|
|
case Mips::SC:
|
2014-06-16 21:13:03 +08:00
|
|
|
case Mips::SC_R6:
|
2014-03-11 04:34:23 +08:00
|
|
|
*AddrIdx = 2;
|
|
|
|
if (IsStore)
|
|
|
|
*IsStore = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool baseRegNeedsLoadStoreMask(unsigned Reg) {
|
|
|
|
// The contents of SP and thread pointer register do not require masking.
|
|
|
|
return Reg != Mips::SP && Reg != Mips::T8;
|
|
|
|
}
|
|
|
|
|
2017-10-11 09:57:21 +08:00
|
|
|
MCELFStreamer *createMipsNaClELFStreamer(MCContext &Context,
|
|
|
|
std::unique_ptr<MCAsmBackend> TAB,
|
2018-05-19 02:26:45 +08:00
|
|
|
std::unique_ptr<MCObjectWriter> OW,
|
2017-10-12 07:34:47 +08:00
|
|
|
std::unique_ptr<MCCodeEmitter> Emitter,
|
2014-10-16 00:12:52 +08:00
|
|
|
bool RelaxAll) {
|
2018-05-19 02:26:45 +08:00
|
|
|
MipsNaClELFStreamer *S = new MipsNaClELFStreamer(
|
|
|
|
Context, std::move(TAB), std::move(OW), std::move(Emitter));
|
2014-02-28 18:00:38 +08:00
|
|
|
if (RelaxAll)
|
|
|
|
S->getAssembler().setRelaxAll(true);
|
|
|
|
|
|
|
|
// Set bundle-alignment as required by the NaCl ABI for the target.
|
2020-02-16 00:52:56 +08:00
|
|
|
S->emitBundleAlignMode(Log2(MIPS_NACL_BUNDLE_ALIGN));
|
2014-02-28 18:00:38 +08:00
|
|
|
|
|
|
|
return S;
|
|
|
|
}
|
|
|
|
|
2017-02-01 09:22:51 +08:00
|
|
|
} // end namespace llvm
|