Commit 2fee2a2f by Karl Schimpf

Add hybrid assembler concept to ARM assembler.

Adds a notion of a hybrid assembler. That is, if the integrated assembler can lower an instruction to bytes, it does. Otherwise, it uses the standalone assembler to generate text as the placeholder for the instruction. This is done using a textual fixup in the assembly buffer. The advantage of the hybrid assembler is that one can incrementally implement the integrated assembler and still test the generated assembly. BUG= https://code.google.com/p/nativeclient/issues/detail?id=4334 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1418523002 .
parent ac8da5cf
......@@ -35,15 +35,28 @@ static uintptr_t NewContents(Assembler &Assemblr, intptr_t Capacity) {
return Result;
}
void AssemblerBuffer::installFixup(AssemblerFixup *F) {
F->set_position(0);
if (!Assemblr.getPreliminary())
Fixups.push_back(F);
}
AssemblerFixup *AssemblerBuffer::createFixup(FixupKind Kind,
const Constant *Value) {
AssemblerFixup *F =
new (Assemblr.allocate<AssemblerFixup>()) AssemblerFixup();
F->set_position(0);
F->set_kind(Kind);
F->set_value(Value);
if (!Assemblr.getPreliminary())
Fixups.push_back(F);
installFixup(F);
return F;
}
AssemblerTextFixup *AssemblerBuffer::createTextFixup(const std::string &Text,
size_t BytesUsed) {
AssemblerTextFixup *F = new (Assemblr.allocate<AssemblerTextFixup>())
AssemblerTextFixup(Text, BytesUsed);
installFixup(F);
TextFixupNeeded = false;
return F;
}
......@@ -72,12 +85,13 @@ AssemblerBuffer::EnsureCapacity::~EnsureCapacity() {
}
AssemblerBuffer::AssemblerBuffer(Assembler &Asm) : Assemblr(Asm) {
const intptr_t OneKB = 1024;
static const intptr_t kInitialBufferCapacity = 4 * OneKB;
constexpr intptr_t OneKB = 1024;
static constexpr intptr_t kInitialBufferCapacity = 4 * OneKB;
Contents = NewContents(Assemblr, kInitialBufferCapacity);
Cursor = Contents;
Limit = computeLimit(Contents, kInitialBufferCapacity);
HasEnsuredCapacity = false;
TextFixupNeeded = false;
// Verify internal state.
assert(capacity() == kInitialBufferCapacity);
......@@ -89,7 +103,7 @@ AssemblerBuffer::~AssemblerBuffer() = default;
void AssemblerBuffer::extendCapacity() {
intptr_t old_size = size();
intptr_t old_capacity = capacity();
const intptr_t OneMB = 1 << 20;
constexpr intptr_t OneMB = 1 << 20;
intptr_t new_capacity = std::min(old_capacity * 2, old_capacity + OneMB);
if (new_capacity < old_capacity) {
llvm::report_fatal_error(
......@@ -123,7 +137,6 @@ void Assembler::emitIASBytes() const {
Ostream &Str = Ctx->getStrEmit();
intptr_t EndPosition = Buffer.size();
intptr_t CurPosition = 0;
const intptr_t FixupSize = 4;
for (const AssemblerFixup *NextFixup : fixups()) {
intptr_t NextFixupLoc = NextFixup->position();
for (intptr_t i = CurPosition; i < NextFixupLoc; ++i) {
......@@ -131,16 +144,13 @@ void Assembler::emitIASBytes() const {
Str.write_hex(Buffer.load<uint8_t>(i));
Str << "\n";
}
Str << "\t.long ";
// For PCRel fixups, we write the pc-offset from a symbol into the Buffer
// (e.g., -4), but we don't represent that in the fixup's offset. Otherwise
// the fixup holds the true offset, and so does the Buffer. Just load the
// offset from the buffer.
NextFixup->emit(Ctx, Buffer.load<RelocOffsetT>(NextFixupLoc));
if (fixupIsPCRel(NextFixup->kind()))
Str << " - .";
Str << "\n";
CurPosition = NextFixupLoc + FixupSize;
CurPosition = NextFixupLoc +
NextFixup->emit(Ctx, Buffer.load<RelocOffsetT>(NextFixupLoc),
fixupIsPCRel(NextFixup->kind()));
assert(CurPosition <= EndPosition);
}
// Handle any bytes that are not prefixed by a fixup.
......
......@@ -174,6 +174,20 @@ public:
/// Create and track a fixup in the current function.
AssemblerFixup *createFixup(FixupKind Kind, const Constant *Value);
/// Create and track a textual fixup in the current function.
AssemblerTextFixup *createTextFixup(const std::string &Text,
size_t BytesUsed);
/// Mark that an attempt was made to emit, but failed. Hence, in order to
/// continue, one must emit a text fixup.
void setNeedsTextFixup() { TextFixupNeeded = true; }
/// Returns true if last emit failed and needs a text fixup.
bool needsTextFixup() const { return TextFixupNeeded; }
/// Installs a created fixup, after it has been allocated.
void installFixup(AssemblerFixup *F);
const FixupRefList &fixups() const { return Fixups; }
void setSize(intptr_t NewSize) {
......@@ -194,6 +208,9 @@ private:
Assembler &Assemblr;
/// List of pool-allocated fixups relative to the current function.
FixupRefList Fixups;
// True if a textual fixup is needed, because the assembler was unable to
// emit the last request.
bool TextFixupNeeded;
uintptr_t cursor() const { return Cursor; }
uintptr_t limit() const { return Limit; }
......@@ -268,12 +285,24 @@ public:
// Return a view of all the bytes of code for the current function.
llvm::StringRef getBufferView() const;
/// Emit a fixup at the current location.
void emitFixup(AssemblerFixup *Fixup) { Buffer.emitFixup(Fixup); }
const FixupRefList &fixups() const { return Buffer.fixups(); }
AssemblerFixup *createFixup(FixupKind Kind, const Constant *Value) {
return Buffer.createFixup(Kind, Value);
}
AssemblerTextFixup *createTextFixup(const std::string &Text,
size_t BytesUsed) {
return Buffer.createTextFixup(Text, BytesUsed);
}
void setNeedsTextFixup() { Buffer.setNeedsTextFixup(); }
bool needsTextFixup() const { return Buffer.needsTextFixup(); }
void emitIASBytes() const;
bool getInternal() const { return IsInternal; }
void setInternal(bool Internal) { IsInternal = Internal; }
......@@ -306,6 +335,9 @@ private:
/// fully committed (Preliminary=false).
bool Preliminary = false;
/// Installs a created fixup, after it has been allocated.
void installFixup(AssemblerFixup *F) { Buffer.installFixup(F); }
protected:
GlobalContext *Ctx;
// Buffer's constructor uses the Allocator, so it needs to appear after it.
......
......@@ -53,11 +53,12 @@ public:
void alignFunction() override {
const SizeT Align = 1 << getBundleAlignLog2Bytes();
SizeT BytesNeeded = Utils::OffsetToAlignment(Buffer.getPosition(), Align);
constexpr uint32_t UndefinedInst = 0xe7fedef0; // udf #60896
constexpr SizeT InstSize = sizeof(int32_t);
assert(BytesNeeded % InstSize == 0);
while (BytesNeeded > 0) {
// TODO(kschimpf) Should this be NOP or some other instruction?
bkpt(0);
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
emitInst(UndefinedInst);
BytesNeeded -= InstSize;
}
}
......@@ -91,7 +92,8 @@ public:
bool fixupIsPCRel(FixupKind Kind) const override {
(void)Kind;
llvm_unreachable("Not yet implemented.");
// TODO(kschimpf) Decide if we need this.
return false;
}
void bind(Label *label);
......@@ -118,6 +120,8 @@ public:
return Asm->getKind() == Asm_ARM32;
}
void emitTextInst(const std::string &Text);
private:
// A vector of pool-allocated x86 labels for CFG nodes.
using LabelVector = std::vector<Label *>;
......
......@@ -885,7 +885,6 @@ private:
inline void emitRegisterOperand(int rm, int reg);
template <typename RegType, typename RmType>
inline void emitXmmRegisterOperand(RegType reg, RmType rm);
inline void emitFixup(AssemblerFixup *fixup);
inline void emitOperandSizeOverride();
void emitOperand(int rm, const typename Traits::Operand &operand);
......@@ -1063,11 +1062,6 @@ inline void AssemblerX86Base<Machine>::emitXmmRegisterOperand(RegType reg,
}
template <class Machine>
inline void AssemblerX86Base<Machine>::emitFixup(AssemblerFixup *fixup) {
Buffer.emitFixup(fixup);
}
template <class Machine>
inline void AssemblerX86Base<Machine>::emitOperandSizeOverride() {
emitUint8(0x66);
}
......
......@@ -74,6 +74,11 @@ cl::opt<std::string>
cl::desc("Define default global prefix for naming "
"unnamed globals"),
cl::init("Global"));
cl::opt<bool> DisableHybridAssembly(
"no-hybrid-asm", cl::desc("Disable hybrid assembly when -filetype=iasm"),
cl::init(false));
cl::opt<bool> DisableInternal("externalize",
cl::desc("Externalize all symbols"));
// Note: Modifiable only if ALLOW_DISABLE_IR_GEN.
......@@ -380,6 +385,7 @@ void ClFlags::resetClFlags(ClFlags &OutFlags) {
OutFlags.AllowUninitializedGlobals = false;
OutFlags.DataSections = false;
OutFlags.DecorateAsm = false;
OutFlags.DisableHybridAssembly = false;
OutFlags.DisableInternal = false;
OutFlags.DisableIRGeneration = false;
OutFlags.DisableTranslation = false;
......@@ -445,6 +451,7 @@ void ClFlags::getParsedClFlags(ClFlags &OutFlags) {
OutFlags.setDecorateAsm(::DecorateAsm);
OutFlags.setDefaultFunctionPrefix(::DefaultFunctionPrefix);
OutFlags.setDefaultGlobalPrefix(::DefaultGlobalPrefix);
OutFlags.setDisableHybridAssembly(::DisableHybridAssembly);
OutFlags.setDisableInternal(::DisableInternal);
OutFlags.setDisableIRGeneration(::DisableIRGeneration);
OutFlags.setDisableTranslation(::DisableTranslation);
......
......@@ -62,6 +62,11 @@ public:
bool getDecorateAsm() const { return DecorateAsm; }
void setDecorateAsm(bool NewValue) { DecorateAsm = NewValue; }
bool getDisableHybridAssembly() const { return DisableHybridAssembly; }
void setDisableHybridAssembly(bool NewValue) {
DisableHybridAssembly = NewValue;
}
bool getDisableInternal() const { return DisableInternal; }
void setDisableInternal(bool NewValue) { DisableInternal = NewValue; }
......@@ -253,6 +258,7 @@ private:
bool AllowUninitializedGlobals;
bool DataSections;
bool DecorateAsm;
bool DisableHybridAssembly;
bool DisableInternal;
bool DisableIRGeneration;
bool DisableTranslation;
......
......@@ -48,11 +48,13 @@ IceString AssemblerFixup::symbol(const GlobalContext *Ctx) const {
return Str.str();
}
void AssemblerFixup::emit(GlobalContext *Ctx,
RelocOffsetT OverrideOffset) const {
size_t AssemblerFixup::emit(GlobalContext *Ctx, RelocOffsetT OverrideOffset,
bool IsPCRel) const {
static constexpr const size_t FixupSize = 4;
if (!BuildDefs::dump())
return;
return FixupSize;
Ostream &Str = Ctx->getStrEmit();
Str << "\t.long ";
if (isNullSymbol())
Str << "__Sz_AbsoluteZero";
else
......@@ -60,6 +62,22 @@ void AssemblerFixup::emit(GlobalContext *Ctx,
RelocOffsetT Offset = OverrideOffset;
if (Offset)
Str << " + " << Offset;
// For PCRel fixups, we write the pc-offset from a symbol into the Buffer
// (e.g., -4), but we don't represent that in the fixup's offset. Otherwise
// the fixup holds the true offset, and so does the Buffer. Just load the
// offset from the buffer.
if (IsPCRel)
Str << " - .";
Str << "\n";
return FixupSize;
}
size_t AssemblerTextFixup::emit(GlobalContext *Ctx, RelocOffsetT OverrideOffset,
bool IsPCRel) const {
(void)OverrideOffset;
(void)IsPCRel;
Ctx->getStrEmit() << Message << "\n";
return NumBytes;
}
} // end of namespace Ice
......@@ -45,7 +45,9 @@ public:
void set_value(const Constant *Value) { value_ = Value; }
void emit(GlobalContext *Ctx, RelocOffsetT OverrideOffset) const;
/// Emits fixup, then returns the number of bytes to skip.
virtual size_t emit(GlobalContext *Ctx, RelocOffsetT OverrideOffset,
bool IsPCRel) const;
private:
intptr_t position_ = 0;
......@@ -53,6 +55,26 @@ private:
const Constant *value_ = nullptr;
};
/// Extends a fixup to be textual. That is, it emits text instead of a sequence
/// of bytes. This class is used as a fallback for unimplemented emitIAS
/// methods, allowing them to generate compilable assembly code.
class AssemblerTextFixup : public AssemblerFixup {
AssemblerTextFixup() = delete;
AssemblerTextFixup(const AssemblerTextFixup &) = delete;
AssemblerTextFixup &operator=(const AssemblerTextFixup &) = delete;
public:
AssemblerTextFixup(const std::string &Message, size_t NumBytes)
: AssemblerFixup(), Message(Message), NumBytes(NumBytes) {}
~AssemblerTextFixup() = default;
virtual size_t emit(GlobalContext *Ctx, RelocOffsetT OverrideOffset,
bool isPcRel) const;
private:
const std::string Message;
const size_t NumBytes;
};
using FixupList = std::vector<AssemblerFixup>;
using FixupRefList = std::vector<AssemblerFixup *>;
......
......@@ -175,6 +175,7 @@ public:
Ostream &getStrDump() { return *StrDump; }
Ostream &getStrError() { return *StrError; }
Ostream &getStrEmit() { return *StrEmit; }
void setStrEmit(Ostream &NewStrEmit) { StrEmit = &NewStrEmit; }
LockedPtr<ErrorCode> getErrorStatus() {
return LockedPtr<ErrorCode>(&ErrorStatus, &ErrorStatusLock);
......
......@@ -344,6 +344,8 @@ public:
void dump(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
protected:
InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest)
: InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {}
......@@ -351,6 +353,10 @@ protected:
static bool isClassof(const Inst *Inst, InstKindARM32 MyKind) {
return Inst->getKind() == static_cast<InstKind>(MyKind);
}
// Generates text of assembly instruction using method emit(), and then adds
// to the assembly buffer as a Fixup.
void emitUsingTextFixup(const Cfg *Func) const;
};
/// A predicable ARM instruction.
......@@ -412,10 +418,6 @@ public:
return;
emitUnaryopGPR(Opcode, this, Func, NeedsWidthSuffix);
}
void emitIAS(const Cfg *Func) const override {
(void)Func;
llvm_unreachable("Not yet implemented");
}
void dump(const Cfg *Func) const override {
if (!BuildDefs::dump())
return;
......@@ -456,10 +458,6 @@ public:
return;
emitUnaryopFP(Opcode, this, Func);
}
void emitIAS(const Cfg *Func) const override {
(void)Func;
llvm::report_fatal_error("Not yet implemented");
}
void dump(const Cfg *Func) const override {
if (!BuildDefs::dump())
return;
......@@ -501,10 +499,7 @@ public:
return;
emitTwoAddr(Opcode, this, Func);
}
void emitIAS(const Cfg *Func) const override {
(void)Func;
llvm::report_fatal_error("Not yet implemented");
}
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override {
if (!BuildDefs::dump())
return;
......@@ -542,7 +537,6 @@ public:
InstARM32LoadBase(Func, Dest, Source, Predicate);
}
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override {
if (!BuildDefs::dump())
return;
......@@ -636,10 +630,6 @@ public:
return;
emitThreeAddrFP(Opcode, this, Func);
}
void emitIAS(const Cfg *Func) const override {
(void)Func;
llvm::report_fatal_error("Not yet implemented");
}
void dump(const Cfg *Func) const override {
if (!BuildDefs::dump())
return;
......@@ -682,10 +672,6 @@ public:
return;
emitFourAddr(Opcode, this, Func);
}
void emitIAS(const Cfg *Func) const override {
(void)Func;
llvm::report_fatal_error("Not yet implemented");
}
void dump(const Cfg *Func) const override {
if (!BuildDefs::dump())
return;
......@@ -729,10 +715,6 @@ public:
return;
emitCmpLike(Opcode, this, Func);
}
void emitIAS(const Cfg *Func) const override {
(void)Func;
llvm_unreachable("Not yet implemented");
}
void dump(const Cfg *Func) const override {
if (!BuildDefs::dump())
return;
......@@ -810,7 +792,6 @@ public:
IceString getName(const Cfg *Func) const;
SizeT getNumber() const { return Number; }
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
private:
......@@ -879,7 +860,6 @@ public:
}
bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Br); }
......@@ -910,7 +890,6 @@ public:
InstARM32AdjustStack(Func, SP, Amount, SrcAmount);
}
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Adjuststack); }
SizeT getAmount() const { return Amount; }
......@@ -936,7 +915,6 @@ public:
}
Operand *getCallTarget() const { return getSrc(0); }
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Call); }
......@@ -956,7 +934,6 @@ public:
return new (Func->allocate<InstARM32Pop>()) InstARM32Pop(Func, Dests);
}
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Pop); }
......@@ -978,7 +955,6 @@ public:
return new (Func->allocate<InstARM32Push>()) InstARM32Push(Func, Srcs);
}
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Push); }
......@@ -1029,7 +1005,6 @@ public:
InstARM32Str(Func, Value, Mem, Predicate);
}
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Str); }
......@@ -1055,7 +1030,6 @@ public:
InstARM32Strex(Func, Dest, Value, Mem, Predicate);
}
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Strex); }
......@@ -1074,7 +1048,6 @@ public:
return new (Func->allocate<InstARM32Trap>()) InstARM32Trap(Func);
}
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Trap); }
......@@ -1097,7 +1070,6 @@ public:
InstARM32Umull(Func, DestLo, DestHi, Src0, Src1, Predicate);
}
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Umull); }
......@@ -1122,7 +1094,6 @@ public:
InstARM32Vcvt(Func, Dest, Src, Variant, Predicate);
}
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Vcvt); }
......@@ -1189,7 +1160,6 @@ public:
InstARM32Vcmp(Func, Src0, Src1, Predicate);
}
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Vcmp); }
......@@ -1209,7 +1179,6 @@ public:
return new (Func->allocate<InstARM32Vmrs>()) InstARM32Vmrs(Func, Predicate);
}
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Vmrs); }
......@@ -1229,7 +1198,6 @@ public:
InstARM32Vabs(Func, Dest, Src, Predicate);
}
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Vabs); }
......@@ -1248,7 +1216,6 @@ public:
return new (Func->allocate<InstARM32Dmb>()) InstARM32Dmb(Func);
}
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Dmb); }
......
......@@ -48,7 +48,6 @@ const char *InstMIPS32::getWidthString(Type Ty) {
return "TBD";
}
template <> const char *InstMIPS32Addiu::Opcode = "addiu";
template <> const char *InstMIPS32Lui::Opcode = "lui";
template <> const char *InstMIPS32La::Opcode = "la";
......
......@@ -44,6 +44,7 @@ public:
if (BuildDefs::dump())
Str << "<OperandMIPS32>";
}
protected:
OperandMIPS32(OperandKindMIPS32 Kind, Type Ty)
: Operand(static_cast<OperandKind>(Kind), Ty) {}
......@@ -272,13 +273,12 @@ public:
private:
InstMIPS32Imm16(Cfg *Func, Variable *Dest, Operand *Source, uint32_t Imm)
: InstMIPS32(Func, K, 1, Dest), Imm(Imm){
: InstMIPS32(Func, K, 1, Dest), Imm(Imm) {
addSource(Source);
}
InstMIPS32Imm16(Cfg *Func, Variable *Dest, uint32_t Imm)
: InstMIPS32(Func, K, 0, Dest), Imm(Imm) {
}
: InstMIPS32(Func, K, 0, Dest), Imm(Imm) {}
static const char *Opcode;
......@@ -304,7 +304,7 @@ public:
return !isMultiDest() && !isMultiSource() &&
checkForRedundantAssign(getDest(), getSrc(0));
}
//bool isSimpleAssign() const override { return true; }
// bool isSimpleAssign() const override { return true; }
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
......
......@@ -4,11 +4,22 @@
; REQUIRES: allow_dump
; Compile using standalone assembler.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -O2 \
; RUN: | FileCheck %s --check-prefix=ASM
; Show bytes in assembled standalone code.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -O2 | FileCheck %s --check-prefix=DIS
; Compile using integrated assembler.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -O2 \
; RUN: | FileCheck %s --check-prefix=IASM
; Show bytes in assembled integrated code.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -O2 | FileCheck %s --check-prefix=DIS
define internal i32 @add1ToR0(i32 %p) {
%v = add i32 %p, 1
ret i32 %v
......@@ -18,11 +29,21 @@ define internal i32 @add1ToR0(i32 %p) {
; ASM: add r0, r0, #1
; ASM-NEXT: bx lr
; DIS-LABEL:00000000 <add1ToR0>:
; DIS-NEXT: 0: e2800001
; DIS-NEXT: 4: e12fff1e
; IASM-LABEL: add1ToR0:
; IASM: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x80
; IASM-NEXT: .byte 0xe2
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x80
; IASM-NEXT: .byte 0xe2
; IASM-NEXT: .byte 0x1e
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0x2f
; IASM-NEXT: .byte 0xe1
define internal i32 @Add2Regs(i32 %p1, i32 %p2) {
%v = add i32 %p1, %p2
......@@ -33,9 +54,18 @@ define internal i32 @Add2Regs(i32 %p1, i32 %p2) {
; ASM: add r0, r0, r1
; ASM-NEXT: bx lr
; DIS-LABEL:00000010 <Add2Regs>:
; DIS-NEXT: 10: e0800001
; DIS-NEXT: 14: e12fff1e
; IASM-LABEL: Add2Regs:
; IASM: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x80
; IASM-NEXT: .byte 0xe0
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x80
; IASM-NEXT: .byte 0xe0
; IASM-NEXT: .byte 0x1e
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0x2f
; IASM-NEXT: .byte 0xe1
; TODO(kschimpf): Show that we can handle global variable loads/stores.
; REQUIRES: allow_dump
; Compile using standalone assembler.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -O2 \
; RUN: | FileCheck %s --check-prefix=ASM
; Show bytes in assembled standalone code.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -O2 | FileCheck %s --check-prefix=DIS
; Compile using integrated assembler.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -O2 \
; RUN: | FileCheck %s --check-prefix=IASM
; Show bytes in assembled integrated code.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -O2 | FileCheck %s --check-prefix=DIS
@global1 = internal global [4 x i8] zeroinitializer, align 4
; ASM-LABEL: global1:
; ASM-NEXT: .zero 4
; ASM-NEXT: .size global1, 4
; ASM-NEXT: .text
; ASM-NEXT: .p2alignl 4,0xe7fedef0
; IASM-LABEL:global1:
; IASM-NEXT: .zero 4
; IASM-NEXT: .size global1, 4
; IASM-NEXT: .text
; IASM-NEXT: .p2alignl 4,0xe7fedef0
define internal i32 @load() {
%addr = bitcast [4 x i8]* @global1 to i32*
%v = load i32, i32* %addr, align 1
ret i32 %v
}
; ASM-LABEL: load:
; ASM-NEXT: .Lload$__0:
; ASM-NEXT: movw r0, #:lower16:global1
; ASM-NEXT: movt r0, #:upper16:global1
; ASM-NEXT: ldr r0, [r0]
; ASM-NEXT: bx lr
; DIS-LABEL:00000000 <load>:
; DIS-NEXT: 0: e3000000
; DIS-NEXT: 4: e3400000
; DIS-NEXT: 8: e5900000
; DIS-NEXT: c: e12fff1e
; IASM-LABEL:load:
; IASM-NEXT: movw r0, #:lower16:global1
; IASM-NEXT: movt r0, #:upper16:global1
; IASM-NEXT: ldr r0, [r0]
; IASM-NEXT: .byte 0x1e
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0x2f
; IASM-NEXT: .byte 0xe1
define internal void @store(i32 %v) {
%addr = bitcast [4 x i8]* @global1 to i32*
store i32 %v, i32* %addr, align 1
ret void
}
; ASM-LABEL:store:
; ASM-NEXT: .Lstore$__0:
; ASM-NEXT: movw r1, #:lower16:global1
; ASM-NEXT: movt r1, #:upper16:global1
; ASM-NEXT: str r0, [r1]
; ASM-NEXT: bx lr
; DIS-LABEL:00000010 <store>:
; DIS-NEXT: 10: e3001000
; DIS-NEXT: 14: e3401000
; DIS-NEXT: 18: e5810000
; DIS-NEXT: 1c: e12fff1e
; IASM-LABEL:store:
; IASM-NEXT: movw r1, #:lower16:global1
; IASM-NEXT: movt r1, #:upper16:global1
; IASM-NEXT: str r0, [r1]
; IASM-NEXT: .byte 0x1e
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0x2f
; IASM-NEXT: .byte 0xe1
......@@ -2,11 +2,22 @@
; REQUIRES: allow_dump
; Compile using standalone assembler.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -Om1 \
; RUN: | FileCheck %s --check-prefix=ASM
; Show bytes in assembled standalone code.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -Om1 | FileCheck %s --check-prefix=DIS
; Compile using integrated assembler.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -Om1 \
; RUN: | FileCheck %s --check-prefix=IASM
; Show bytes in assembled integrated code.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -Om1 | FileCheck %s --check-prefix=DIS
define internal i32 @add1ToR0(i32 %p) {
%v = add i32 %p, 1
ret i32 %v
......@@ -14,52 +25,61 @@ define internal i32 @add1ToR0(i32 %p) {
; ASM-LABEL: add1ToR0:
; IASM-LABEL: add1ToR0:
; DIS-LABEL:00000000 <add1ToR0>:
; ASM: sub sp, sp, #8
; DIS-NEXT: 0: e24dd008
; IASM: .byte 0x8
; IASM-NEXT: .byte 0xd0
; IASM-NEXT: .byte 0x4d
; IASM-NEXT: .byte 0xe2
; ASM-NEXT: str r0, [sp, #4]
; DIS-NEXT: 4: e58d0004
; IASM-NEXT: .byte 0x4
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: ldr r0, [sp, #4]
; DIS-NEXT: 8: e59d0004
; IASM-NEXT: .byte 0x4
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x9d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: add r0, r0, #1
; DIS-NEXT: c: e2800001
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x80
; IASM-NEXT: .byte 0xe2
; ASM-NEXT: str r0, [sp]
; DIS-NEXT: 10: e58d0000
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: ldr r0, [sp]
; DIS-NEXT: 14: e59d0000
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x9d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: add sp, sp, #8
; DIS-NEXT: 18: e28dd008
; IASM-NEXT: .byte 0x8
; IASM-NEXT: .byte 0xd0
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe2
; ASM-NEXT: bx lr
; IASM-NEXT: .byte 0x1e
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0x2f
; IASM-NEXT: .byte 0xe1
; DIS-NEXT: 1c: e12fff1e
; IASM-NEXT: .byte 0x1e
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0x2f
; IASM-NEXT: .byte 0xe1
......@@ -2,22 +2,37 @@
; REQUIRES: allow_dump
; RUN: %p2i --filetype=asm -i %s --target=arm32 \
; Compile using standalone assembler.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -O2 \
; RUN: | FileCheck %s --check-prefix=ASM
; RUN: %p2i --filetype=iasm -i %s --target=arm32 \
; Show bytes in assembled standalone code.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -O2 | FileCheck %s --check-prefix=DIS
; Compile using integrated assembler.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -O2 \
; RUN: | FileCheck %s --check-prefix=IASM
; Show bytes in assembled integrated code.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -O2 | FileCheck %s --check-prefix=DIS
define internal i32 @Imm1() {
ret i32 1
}
; ASM-LABEL: Imm1:
; ASM: mov r0, #1
; ASM: mov r0, #1
; DIS-LABEL:00000000 <Imm1>:
; DIS-NEXT: 0: e3a00001
; IASM-LABEL: Imm1:
; IASM: .byte 0x1
; IASM: .byte 0x0
; IASM: .byte 0xa0
; IASM: .byte 0xe3
; IASM: .byte 0x1
; IASM: .byte 0x0
; IASM: .byte 0xa0
; IASM: .byte 0xe3
define internal i32 @rotateFImmAA() {
......@@ -26,13 +41,16 @@ define internal i32 @rotateFImmAA() {
}
; ASM-LABEL: rotateFImmAA:
; ASM: mov r0, #680
; ASM: mov r0, #680
; DIS-LABEL:00000010 <rotateFImmAA>:
; DIS-NEXT: 10: e3a00faa
; IASM-LABEL: rotateFImmAA:
; IASM: .byte 0xaa
; IASM: .byte 0xf
; IASM: .byte 0xa0
; IASM: .byte 0xe3
; IASM: .byte 0xaa
; IASM: .byte 0xf
; IASM: .byte 0xa0
; IASM: .byte 0xe3
define internal i32 @rotateEImmAA() {
; immediate = 0x00000aa0 = b 0000 0000 0000 0000 0000 1010 1010 0000
......@@ -40,13 +58,16 @@ define internal i32 @rotateEImmAA() {
}
; ASM-LABEL: rotateEImmAA:
; ASM: mov r0, #2720
; ASM: mov r0, #2720
; DIS-LABEL:00000020 <rotateEImmAA>:
; DIS-NEXT: 20: e3a00eaa
; IASM-LABEL: rotateEImmAA:
; IASM: .byte 0xaa
; IASM: .byte 0xe
; IASM: .byte 0xa0
; IASM: .byte 0xe3
; IASM: .byte 0xaa
; IASM: .byte 0xe
; IASM: .byte 0xa0
; IASM: .byte 0xe3
define internal i32 @rotateDImmAA() {
; immediate = 0x00002a80 = b 0000 0000 0000 0000 0010 1010 1000 0000
......@@ -54,13 +75,16 @@ define internal i32 @rotateDImmAA() {
}
; ASM-LABEL: rotateDImmAA:
; ASM: mov r0, #10880
; ASM: mov r0, #10880
; DIS-LABEL:00000030 <rotateDImmAA>:
; DIS-NEXT: 30: e3a00daa
; IASM-LABEL: rotateDImmAA:
; IASM: .byte 0xaa
; IASM: .byte 0xd
; IASM: .byte 0xa0
; IASM: .byte 0xe3
; IASM: .byte 0xaa
; IASM: .byte 0xd
; IASM: .byte 0xa0
; IASM: .byte 0xe3
define internal i32 @rotateCImmAA() {
; immediate = 0x0000aa00 = b 0000 0000 0000 0000 1010 1010 0000 0000
......@@ -68,13 +92,16 @@ define internal i32 @rotateCImmAA() {
}
; ASM-LABEL: rotateCImmAA:
; ASM: mov r0, #43520
; ASM: mov r0, #43520
; DIS-LABEL:00000040 <rotateCImmAA>:
; DIS-NEXT: 40: e3a00caa
; IASM-LABEL: rotateCImmAA:
; IASM: .byte 0xaa
; IASM: .byte 0xc
; IASM: .byte 0xa0
; IASM: .byte 0xe3
; IASM: .byte 0xaa
; IASM: .byte 0xc
; IASM: .byte 0xa0
; IASM: .byte 0xe3
define internal i32 @rotateBImmAA() {
; immediate = 0x0002a800 = b 0000 0000 0000 0010 1010 1000 0000 0000
......@@ -82,13 +109,16 @@ define internal i32 @rotateBImmAA() {
}
; ASM-LABEL: rotateBImmAA:
; ASM: mov r0, #174080
; ASM: mov r0, #174080
; DIS-LABEL:00000050 <rotateBImmAA>:
; DIS-NEXT: 50: e3a00baa
; IASM-LABEL: rotateBImmAA:
; IASM: .byte 0xaa
; IASM: .byte 0xb
; IASM: .byte 0xa0
; IASM: .byte 0xe3
; IASM: .byte 0xaa
; IASM: .byte 0xb
; IASM: .byte 0xa0
; IASM: .byte 0xe3
define internal i32 @rotateAImmAA() {
; immediate = 0x000aa000 = b 0000 0000 0000 1010 1010 0000 0000 0000
......@@ -96,13 +126,16 @@ define internal i32 @rotateAImmAA() {
}
; ASM-LABEL: rotateAImmAA:
; ASM: mov r0, #696320
; ASM: mov r0, #696320
; DIS-LABEL:00000060 <rotateAImmAA>:
; DIS-NEXT: 60: e3a00aaa
; IASM-LABEL: rotateAImmAA:
; IASM: .byte 0xaa
; IASM: .byte 0xa
; IASM: .byte 0xa0
; IASM: .byte 0xe3
; IASM: .byte 0xaa
; IASM: .byte 0xa
; IASM: .byte 0xa0
; IASM: .byte 0xe3
define internal i32 @rotate9ImmAA() {
; immediate = 0x002a8000 = b 0000 0000 0010 1010 1000 0000 0000 0000
......@@ -110,13 +143,16 @@ define internal i32 @rotate9ImmAA() {
}
; ASM-LABEL: rotate9ImmAA:
; ASM: mov r0, #2785280
; ASM: mov r0, #2785280
; DIS-LABEL:00000070 <rotate9ImmAA>:
; DIS-NEXT: 70: e3a009aa
; IASM-LABEL: rotate9ImmAA:
; IASM: .byte 0xaa
; IASM: .byte 0x9
; IASM: .byte 0xa0
; IASM: .byte 0xe3
; IASM: .byte 0xaa
; IASM: .byte 0x9
; IASM: .byte 0xa0
; IASM: .byte 0xe3
define internal i32 @rotate8ImmAA() {
; immediate = 0x00aa0000 = b 0000 0000 1010 1010 0000 0000 0000 0000
......@@ -124,13 +160,16 @@ define internal i32 @rotate8ImmAA() {
}
; ASM-LABEL: rotate8ImmAA:
; ASM: mov r0, #11141120
; ASM: mov r0, #11141120
; DIS-LABEL:00000080 <rotate8ImmAA>:
; DIS-NEXT: 80: e3a008aa
; IASM-LABEL: rotate8ImmAA:
; IASM: .byte 0xaa
; IASM: .byte 0x8
; IASM: .byte 0xa0
; IASM: .byte 0xe3
; IASM: .byte 0xaa
; IASM: .byte 0x8
; IASM: .byte 0xa0
; IASM: .byte 0xe3
define internal i32 @rotate7ImmAA() {
; immediate = 0x02a80000 = b 0000 0010 1010 1000 0000 0000 0000 0000
......@@ -138,13 +177,16 @@ define internal i32 @rotate7ImmAA() {
}
; ASM-LABEL: rotate7ImmAA:
; ASM: mov r0, #44564480
; ASM: mov r0, #44564480
; DIS-LABEL:00000090 <rotate7ImmAA>:
; DIS-NEXT: 90: e3a007aa
; IASM-LABEL: rotate7ImmAA:
; IASM: .byte 0xaa
; IASM: .byte 0x7
; IASM: .byte 0xa0
; IASM: .byte 0xe3
; IASM: .byte 0xaa
; IASM: .byte 0x7
; IASM: .byte 0xa0
; IASM: .byte 0xe3
define internal i32 @rotate6ImmAA() {
; immediate = 0x0aa00000 = b 0000 1010 1010 0000 0000 0000 0000 0000
......@@ -152,13 +194,16 @@ define internal i32 @rotate6ImmAA() {
}
; ASM-LABEL: rotate6ImmAA:
; ASM: mov r0, #178257920
; ASM: mov r0, #178257920
; DIS-LABEL:000000a0 <rotate6ImmAA>:
; DIS-NEXT: a0: e3a006aa
; IASM-LABEL: rotate6ImmAA:
; IASM: .byte 0xaa
; IASM: .byte 0x6
; IASM: .byte 0xa0
; IASM: .byte 0xe3
; IASM: .byte 0xaa
; IASM: .byte 0x6
; IASM: .byte 0xa0
; IASM: .byte 0xe3
define internal i32 @rotate5ImmAA() {
; immediate = 0x2a800000 = b 0010 1010 1000 0000 0000 0000 0000 0000
......@@ -166,13 +211,16 @@ define internal i32 @rotate5ImmAA() {
}
; ASM-LABEL: rotate5ImmAA:
; ASM: mov r0, #713031680
; ASM: mov r0, #713031680
; DIS-LABEL:000000b0 <rotate5ImmAA>:
; DIS-NEXT: b0: e3a005aa
; IASM-LABEL: rotate5ImmAA:
; IASM: .byte 0xaa
; IASM: .byte 0x5
; IASM: .byte 0xa0
; IASM: .byte 0xe3
; IASM: .byte 0xaa
; IASM: .byte 0x5
; IASM: .byte 0xa0
; IASM: .byte 0xe3
define internal i32 @rotate4ImmAA() {
; immediate = 0xaa000000 = b 1010 1010 0000 0000 0000 0000 0000 0000
......@@ -180,13 +228,16 @@ define internal i32 @rotate4ImmAA() {
}
; ASM-LABEL: rotate4ImmAA:
; ASM: mov r0, #2852126720
; ASM: mov r0, #2852126720
; DIS-LABEL:000000c0 <rotate4ImmAA>:
; DIS-NEXT: c0: e3a004aa
; IASM-LABEL: rotate4ImmAA:
; IASM: .byte 0xaa
; IASM: .byte 0x4
; IASM: .byte 0xa0
; IASM: .byte 0xe3
; IASM: .byte 0xaa
; IASM: .byte 0x4
; IASM: .byte 0xa0
; IASM: .byte 0xe3
define internal i32 @rotate3ImmAA() {
; immediate = 0xa8000002 = b 1010 1000 0000 0000 0000 0000 0000 0010
......@@ -194,13 +245,16 @@ define internal i32 @rotate3ImmAA() {
}
; ASM-LABEL: rotate3ImmAA:
; ASM: mov r0, #2818572290
; ASM: mov r0, #2818572290
; DIS-LABEL:000000d0 <rotate3ImmAA>:
; DIS-NEXT: d0: e3a003aa
; IASM-LABEL: rotate3ImmAA:
; IASM: .byte 0xaa
; IASM: .byte 0x3
; IASM: .byte 0xa0
; IASM: .byte 0xe3
; IASM: .byte 0xaa
; IASM: .byte 0x3
; IASM: .byte 0xa0
; IASM: .byte 0xe3
define internal i32 @rotate2ImmAA() {
; immediate = 0xa000000a = b 1010 0000 0000 0000 0000 0000 0000 1010
......@@ -208,13 +262,16 @@ define internal i32 @rotate2ImmAA() {
}
; ASM-LABEL: rotate2ImmAA:
; ASM: mov r0, #2684354570
; ASM: mov r0, #2684354570
; DIS-LABEL:000000e0 <rotate2ImmAA>:
; DIS-NEXT: e0: e3a002aa
; IASM-LABEL: rotate2ImmAA:
; IASM: .byte 0xaa
; IASM: .byte 0x2
; IASM: .byte 0xa0
; IASM: .byte 0xe3
; IASM: .byte 0xaa
; IASM: .byte 0x2
; IASM: .byte 0xa0
; IASM: .byte 0xe3
define internal i32 @rotate1ImmAA() {
; immediate = 0x8000002a = b 1000 1000 0000 0000 0000 0000 0010 1010
......@@ -222,13 +279,16 @@ define internal i32 @rotate1ImmAA() {
}
; ASM-LABEL: rotate1ImmAA:
; ASM: mov r0, #2147483690
; ASM: mov r0, #2147483690
; DIS-LABEL:000000f0 <rotate1ImmAA>:
; DIS-NEXT: f0: e3a001aa
; IASM-LABEL: rotate1ImmAA:
; IASM: .byte 0xaa
; IASM: .byte 0x1
; IASM: .byte 0xa0
; IASM: .byte 0xe3
; IASM: .byte 0xaa
; IASM: .byte 0x1
; IASM: .byte 0xa0
; IASM: .byte 0xe3
define internal i32 @rotate0ImmAA() {
; immediate = 0x000000aa = b 0000 0000 0000 0000 0000 0000 1010 1010
......@@ -236,10 +296,13 @@ define internal i32 @rotate0ImmAA() {
}
; ASM-LABEL: rotate0ImmAA:
; ASM: mov r0, #170
; ASM: mov r0, #170
; DIS-LABEL:00000100 <rotate0ImmAA>:
; DIS-NEXT: 100: e3a000aa
; IASM-LABEL: rotate0ImmAA:
; IASM: .byte 0xaa
; IASM: .byte 0x0
; IASM: .byte 0xa0
; IASM: .byte 0xe3
; IASM: .byte 0xaa
; IASM: .byte 0x0
; IASM: .byte 0xa0
; IASM: .byte 0xe3
......@@ -3,36 +3,63 @@
; REQUIRES: allow_dump
; RUN: %p2i --filetype=asm -i %s --target=arm32 \
; Compile using standalone assembler.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -Om1 \
; RUN: | FileCheck %s --check-prefix=ASM
; RUN: %p2i --filetype=iasm -i %s --target=arm32 \
; Show bytes in assembled standalone code.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -Om1 | FileCheck %s --check-prefix=DIS
; Compile using integrated assembler.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -Om1 \
; RUN: | FileCheck %s --check-prefix=IASM
; Show bytes in assembled integrated code.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -Om1 | FileCheck %s --check-prefix=DIS
define internal void @f() {
ret void
}
; ASM-LABEL:f:
; ASM-NEXT: .Lf$__0:
; ASM-NEXT: bx lr
; ASM-NEXT: bx lr
; DIS-LABEL:00000000 <f>:
; IASM-LABEL:f:
; IASM-NEXT: .byte 0x1e
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0x2f
; IASM-NEXT: .byte 0xe1
; IASM-NEXT: .byte 0x70
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x20
; IASM-NEXT: .byte 0xe1
; IASM-NEXT: .byte 0x70
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x20
; IASM-NEXT: .byte 0xe1
; IASM-NEXT: .byte 0x70
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x20
; IASM-NEXT: .byte 0xe1
; DIS-NEXT: 0: e12fff1e
; IASM-NEXT: .byte 0x1e
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0x2f
; IASM-NEXT: .byte 0xe1
; DIS-NEXT: 4: e7fedef0
; IASM-NEXT: .byte 0xf0
; IASM-NEXT: .byte 0xde
; IASM-NEXT: .byte 0xfe
; IASM-NEXT: .byte 0xe7
; DIS-NEXT: 8: e7fedef0
; IASM-NEXT: .byte 0xf0
; IASM-NEXT: .byte 0xde
; IASM-NEXT: .byte 0xfe
; IASM-NEXT: .byte 0xe7
; DIS-NEXT: c: e7fedef0
; IASM-NEXT: .byte 0xf0
; IASM-NEXT: .byte 0xde
; IASM-NEXT: .byte 0xfe
; IASM-NEXT: .byte 0xe7
define internal void @ignore() {
ret void
}
; ASM-LABEL:ignore:
; DIS-LABEL:00000010 <ignore>:
; IASM-LABEL:ignore:
; Show that we know how to translate instruction sub.
; NOTE: We use -O2 to get rid of memory stores.
; REQUIRES: allow_dump
; Compile using standalone assembler.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -O2 \
; RUN: | FileCheck %s --check-prefix=ASM
; Show bytes in assembled standalone code.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -O2 | FileCheck %s --check-prefix=DIS
; Compile using integrated assembler.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -O2 \
; RUN: | FileCheck %s --check-prefix=IASM
; Show bytes in assembled integrated code.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -O2 | FileCheck %s --check-prefix=DIS
define internal i32 @sub1FromR0(i32 %p) {
%v = sub i32 %p, 1
ret i32 %v
......@@ -18,6 +27,9 @@ define internal i32 @sub1FromR0(i32 %p) {
; ASM: sub r0, r0, #1
; ASM: bx lr
; DIS-LABEL:00000000 <sub1FromR0>:
; DIS-NEXT: 0: e2400001
; IASM-LABEL: sub1FromR0:
; IASM: .byte 0x1
; IASM-NEXT: .byte 0x0
......@@ -34,9 +46,11 @@ define internal i32 @Sub2Regs(i32 %p1, i32 %p2) {
; ASM: sub r0, r0, r1
; ASM-NEXT: bx lr
; IASM-LABEL: Sub2Regs:
; DIS-LABEL:00000010 <Sub2Regs>:
; DIS-NEXT: 10: e0400001
; IASM: .byte 0x1
; IASM-LABEL: Sub2Regs:
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x40
; IASM-NEXT: .byte 0xe0
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment