Commit 50a3331c by Karl Schimpf

Generate block labels in the ARM hybrid assembler.

Fixes an issue where branches don't compile in the hybrid integrated assembler because some jump instructions have not yet been integrated. It does this by adding an instruction label for each corresponding label generated by the standalone ARM assembler. Note that in order to fix this, I had to change the signature of virtual method Assembler::bindCfgNodeLabel to get the Cfg node (rather than the index value). This allows the ARM hybrid assembler to generate a label for each CfgNode (using the getAsmName() method). BUG= https://code.google.com/p/nativeclient/issues/detail?id=4334 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1407273006 .
parent 2fee2a2f
......@@ -276,9 +276,8 @@ public:
/// Get the label for a CfgNode.
virtual Label *getCfgNodeLabel(SizeT NodeNumber) = 0;
/// Mark the current text location as the start of a CFG node (represented by
/// NodeNumber).
virtual void bindCfgNodeLabel(SizeT NodeNumber) = 0;
/// Mark the current text location as the start of a CFG node.
virtual void bindCfgNodeLabel(const CfgNode *Node) = 0;
virtual bool fixupIsPCRel(FixupKind Kind) const = 0;
......
......@@ -21,6 +21,7 @@
//===----------------------------------------------------------------------===//
#include "IceAssemblerARM32.h"
#include "IceCfgNode.h"
#include "IceUtils.h"
namespace {
......@@ -204,6 +205,18 @@ DecodedResult decodeAddress(const Operand *Opnd, uint32_t &Value) {
namespace Ice {
void ARM32::AssemblerARM32::bindCfgNodeLabel(const CfgNode *Node) {
if (BuildDefs::dump() && !Ctx->getFlags().getDisableHybridAssembly()) {
// Generate label name so that branches can find it.
constexpr SizeT InstSize = 0;
emitTextInst(Node->getAsmName() + ":", InstSize);
}
SizeT NodeNumber = Node->getIndex();
assert(!getPreliminary());
Label *L = getOrCreateCfgNodeLabel(NodeNumber);
this->bind(L);
}
Label *ARM32::AssemblerARM32::getOrCreateLabel(SizeT Number,
LabelVector &Labels) {
Label *L = nullptr;
......@@ -236,12 +249,13 @@ void ARM32::AssemblerARM32::bind(Label *label) {
label->bindTo(bound);
}
void ARM32::AssemblerARM32::emitTextInst(const std::string &Text) {
static constexpr uint32_t Placeholder = 0;
void ARM32::AssemblerARM32::emitTextInst(const std::string &Text,
SizeT InstSize) {
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
AssemblerFixup *F = createTextFixup(Text, sizeof(Placeholder));
AssemblerFixup *F = createTextFixup(Text, InstSize);
emitFixup(F);
emitInst(Placeholder);
for (SizeT I = 0; I < InstSize; ++I)
Buffer.emit<char>(0);
}
void ARM32::AssemblerARM32::emitType01(CondARM32::Cond Cond, uint32_t Type,
......
......@@ -39,6 +39,7 @@ namespace Ice {
namespace ARM32 {
class AssemblerARM32 : public Assembler {
AssemblerARM32() = delete;
AssemblerARM32(const AssemblerARM32 &) = delete;
AssemblerARM32 &operator=(const AssemblerARM32 &) = delete;
......@@ -48,7 +49,16 @@ public:
// TODO(kschimpf): Add mode if needed when branches are handled.
(void)use_far_branches;
}
~AssemblerARM32() override = default;
~AssemblerARM32() override {
if (BuildDefs::asserts()) {
for (const Label *Label : CfgNodeLabels) {
Label->finalCheck();
}
for (const Label *Label : LocalLabels) {
Label->finalCheck();
}
}
}
void alignFunction() override {
const SizeT Align = 1 << getBundleAlignLog2Bytes();
......@@ -84,10 +94,12 @@ public:
return CfgNodeLabels[NodeNumber];
}
void bindCfgNodeLabel(SizeT NodeNumber) override {
assert(!getPreliminary());
Label *L = getOrCreateCfgNodeLabel(NodeNumber);
this->bind(L);
void bindCfgNodeLabel(const CfgNode *Node) override;
void bindLocalLabel(SizeT Number) {
Label *L = getOrCreateLocalLabel(Number);
if (!getPreliminary())
this->bind(L);
}
bool fixupIsPCRel(FixupKind Kind) const override {
......@@ -120,17 +132,22 @@ public:
return Asm->getKind() == Asm_ARM32;
}
void emitTextInst(const std::string &Text);
void emitTextInst(const std::string &Text, SizeT InstSize = sizeof(uint32_t));
private:
// A vector of pool-allocated x86 labels for CFG nodes.
using LabelVector = std::vector<Label *>;
LabelVector CfgNodeLabels;
// A vector of pool-allocated x86 labels for Local labels.
LabelVector LocalLabels;
Label *getOrCreateLabel(SizeT Number, LabelVector &Labels);
Label *getOrCreateCfgNodeLabel(SizeT NodeNumber) {
return getOrCreateLabel(NodeNumber, CfgNodeLabels);
}
Label *getOrCreateLocalLabel(SizeT Number) {
return getOrCreateLabel(Number, LocalLabels);
}
void emitInst(uint32_t Value) { Buffer.emit<uint32_t>(Value); }
......
......@@ -67,8 +67,7 @@ public:
llvm_unreachable("Not yet implemented.");
}
void bindCfgNodeLabel(SizeT NodeNumber) override {
(void)NodeNumber;
void bindCfgNodeLabel(const CfgNode *) override {
llvm::report_fatal_error("Not yet implemented.");
}
......
......@@ -152,7 +152,7 @@ public:
}
Ice::Label *getCfgNodeLabel(SizeT NodeNumber) override;
void bindCfgNodeLabel(SizeT NodeNumber) override;
void bindCfgNodeLabel(const CfgNode *Node) override;
Label *getOrCreateCfgNodeLabel(SizeT Number);
Label *getOrCreateLocalLabel(SizeT Number);
void bindLocalLabel(SizeT Number);
......
......@@ -22,6 +22,7 @@
#include "IceAssemblerX86Base.h"
#include "IceCfg.h"
#include "IceCfgNode.h"
#include "IceOperand.h"
namespace Ice {
......@@ -86,9 +87,9 @@ Label *AssemblerX86Base<Machine>::getOrCreateLocalLabel(SizeT Number) {
}
template <class Machine>
void AssemblerX86Base<Machine>::bindCfgNodeLabel(SizeT NodeNumber) {
void AssemblerX86Base<Machine>::bindCfgNodeLabel(const CfgNode *Node) {
assert(!getPreliminary());
Label *L = getOrCreateCfgNodeLabel(NodeNumber);
Label *L = getOrCreateCfgNodeLabel(Node->getIndex());
this->bind(L);
}
......
......@@ -1184,7 +1184,7 @@ void CfgNode::emitIAS(Cfg *Func) const {
// TODO(stichnot): When sandboxing, defer binding the node label until just
// before the first instruction is emitted, to reduce the chance that a
// padding nop is a branch target.
Asm->bindCfgNodeLabel(getIndex());
Asm->bindCfgNodeLabel(this);
for (const Inst &I : Phis) {
if (I.isDeleted())
continue;
......
......@@ -801,6 +801,13 @@ void InstARM32Label::emit(const Cfg *Func) const {
Str << getName(Func) << ":";
}
void InstARM32Label::emitIAS(const Cfg *Func) const {
ARM32::AssemblerARM32 *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
Asm->bindLocalLabel(Number);
if (Asm->needsTextFixup())
emitUsingTextFixup(Func);
}
void InstARM32Label::dump(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
......
......@@ -792,6 +792,7 @@ 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:
......
......@@ -26,15 +26,16 @@ define internal i32 @add1ToR0(i32 %p) {
}
; ASM-LABEL: add1ToR0:
; ASM: add r0, r0, #1
; ASM-NEXT: bx lr
; ASM-NEXT: .Ladd1ToR0$__0:
; ASM-NEXT: add r0, r0, #1
; ASM-NEXT: bx lr
; DIS-LABEL:00000000 <add1ToR0>:
; DIS-NEXT: 0: e2800001
; DIS-NEXT: 4: e12fff1e
; IASM-LABEL: add1ToR0:
; IASM-LABEL: .Ladd1ToR0$__0:
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x80
......@@ -51,15 +52,16 @@ define internal i32 @Add2Regs(i32 %p1, i32 %p2) {
}
; ASM-LABEL: Add2Regs:
; ASM: add r0, r0, r1
; ASM-NEXT: bx lr
; ASM-NEXT: .LAdd2Regs$__0:
; ASM-NEXT: add r0, r0, r1
; ASM-NEXT: bx lr
; DIS-LABEL:00000010 <Add2Regs>:
; DIS-NEXT: 10: e0800001
; DIS-NEXT: 14: e12fff1e
; IASM-LABEL: Add2Regs:
; IASM-NEXT: .LAdd2Regs$__0:
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x80
......
; Test branching instructions.
; TODO(kschimpf): Get this working.
; 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
; REQUIRES: allow_dump
define internal void @simple_uncond_branch() {
; DIS-LABEL: 00000000 <simple_uncond_branch>:
; ASM-LABEL: simple_uncond_branch:
; IASM-LABEL:simple_uncond_branch:
; ASM-NEXT: .Lsimple_uncond_branch$__0:
; IASM-NEXT: .Lsimple_uncond_branch$__0:
br label %l2
; ASM-NEXT: b .Lsimple_uncond_branch$l2
; IASM-NEXT: b .Lsimple_uncond_branch$l2
; DIS-NEXT: 0: ea000000
l1:
; ASM-NEXT: .Lsimple_uncond_branch$l1:
; IASM-NEXT: .Lsimple_uncond_branch$l1:
br label %l3
; ASM-NEXT: b .Lsimple_uncond_branch$l3
; IASM-NEXT: b .Lsimple_uncond_branch$l3
; DIS-NEXT: 4: ea000000
l2:
; ASM-NEXT: .Lsimple_uncond_branch$l2:
; IASM-NEXT: .Lsimple_uncond_branch$l2:
br label %l1
; ASM-NEXT: b .Lsimple_uncond_branch$l1
; IASM-NEXT: b .Lsimple_uncond_branch$l1
; DIS-NEXT: 8: eafffffd
l3:
; ASM-NEXT: .Lsimple_uncond_branch$l3:
; IASM-NEXT: .Lsimple_uncond_branch$l3:
ret void
; ASM-NEXT: bx lr
; IASM-NEXT: .byte 0x1e
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0x2f
; IASM-NEXT: .byte 0xe1
}
......@@ -52,6 +52,7 @@ define internal i32 @load() {
; DIS-NEXT: c: e12fff1e
; IASM-LABEL:load:
; IASM-NEXT: .Lload$__0:
; IASM-NEXT: movw r0, #:lower16:global1
; IASM-NEXT: movt r0, #:upper16:global1
; IASM-NEXT: ldr r0, [r0]
......@@ -80,6 +81,7 @@ define internal void @store(i32 %v) {
; DIS-NEXT: 1c: e12fff1e
; IASM-LABEL:store:
; IASM-NEXT: .Lstore$__0:
; IASM-NEXT: movw r1, #:lower16:global1
; IASM-NEXT: movt r1, #:upper16:global1
; IASM-NEXT: str r0, [r1]
......
......@@ -27,10 +27,9 @@ define internal void @f() {
; ASM-NEXT: .Lf$__0:
; ASM-NEXT: bx lr
; DIS-LABEL:00000000 <f>:
; IASM-LABEL:f:
; IASM-NEXT:.Lf$__0:
; DIS-NEXT: 0: e12fff1e
; IASM-NEXT: .byte 0x1e
......
......@@ -50,7 +50,7 @@ define internal i32 @Sub2Regs(i32 %p1, i32 %p2) {
; DIS-NEXT: 10: e0400001
; IASM-LABEL: Sub2Regs:
; IASM-NEXT: .byte 0x1
; IASM: .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