Commit f644a4b3 by Jan Voung

Assemble calls to constant addresses.

Finally address this TODO in the assembler. This will help translate non-IRT using programs (no ABI stability). The default scons testing mode is non-IRT, so this helps with that. I haven't actually tested this against scons yet, but I'm filling in the tests based on how LLVM translates the same bitcode. The filetype=asm is adjusted to omit the "*" and the "$". The filetype=obj is adjusted to check for fixups with NullSymbols, and also fill the assembler buffer at the instruction's immediate field w/ the right constant. The filetype=iasm is still TODO (hits an new assert in the Fixup's emit() function). Reverts 7ad1bed9: "Allow stubbing of called constant addresses using command line argument." since this is now handled (except for iasm). BUG= https://code.google.com/p/nativeclient/issues/detail?id=4080 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1017373002
parent 1c335ef4
...@@ -30,8 +30,8 @@ public: ...@@ -30,8 +30,8 @@ public:
DecorateAsm(false), DisableInternal(false), DisableIRGeneration(false), DecorateAsm(false), DisableInternal(false), DisableIRGeneration(false),
DisableTranslation(false), DumpStats(false), FunctionSections(false), DisableTranslation(false), DumpStats(false), FunctionSections(false),
GenerateUnitTestMessages(false), PhiEdgeSplit(false), GenerateUnitTestMessages(false), PhiEdgeSplit(false),
StubConstantCalls(false), SubzeroTimingEnabled(false), SubzeroTimingEnabled(false), TimeEachFunction(false),
TimeEachFunction(false), UseSandboxing(false), UseSandboxing(false),
// FileType field // FileType field
OutFileType(FT_Iasm), OutFileType(FT_Iasm),
// IceString fields. // IceString fields.
...@@ -87,11 +87,6 @@ public: ...@@ -87,11 +87,6 @@ public:
bool getPhiEdgeSplit() const { return PhiEdgeSplit; } bool getPhiEdgeSplit() const { return PhiEdgeSplit; }
void setPhiEdgeSplit(bool NewValue) { PhiEdgeSplit = NewValue; } void setPhiEdgeSplit(bool NewValue) { PhiEdgeSplit = NewValue; }
bool getStubConstantCalls() const {
return !ALLOW_MINIMAL_BUILD && StubConstantCalls;
}
void setStubConstantCalls(bool NewValue) { StubConstantCalls = NewValue; }
bool getSubzeroTimingEnabled() const { return SubzeroTimingEnabled; } bool getSubzeroTimingEnabled() const { return SubzeroTimingEnabled; }
void setSubzeroTimingEnabled(bool NewValue) { void setSubzeroTimingEnabled(bool NewValue) {
SubzeroTimingEnabled = NewValue; SubzeroTimingEnabled = NewValue;
...@@ -154,7 +149,6 @@ private: ...@@ -154,7 +149,6 @@ private:
bool FunctionSections; bool FunctionSections;
bool GenerateUnitTestMessages; bool GenerateUnitTestMessages;
bool PhiEdgeSplit; bool PhiEdgeSplit;
bool StubConstantCalls;
bool SubzeroTimingEnabled; bool SubzeroTimingEnabled;
bool TimeEachFunction; bool TimeEachFunction;
bool UseSandboxing; bool UseSandboxing;
......
...@@ -84,10 +84,7 @@ ELFObjectWriter::ELFObjectWriter(GlobalContext &Ctx, ELFStreamer &Out) ...@@ -84,10 +84,7 @@ ELFObjectWriter::ELFObjectWriter(GlobalContext &Ctx, ELFStreamer &Out)
"Elf_Sym sizes cannot be derived from sizeof"); "Elf_Sym sizes cannot be derived from sizeof");
SymTab = createSection<ELFSymbolTableSection>(SymTabName, SHT_SYMTAB, 0, SymTab = createSection<ELFSymbolTableSection>(SymTabName, SHT_SYMTAB, 0,
SymTabAlign, SymTabEntSize); SymTabAlign, SymTabEntSize);
// The first entry in the symbol table should be a NULL entry. SymTab->createNullSymbol(NullSection);
const IceString NullSymName("");
SymTab->createDefinedSym(NullSymName, STT_NOTYPE, STB_LOCAL, NullSection, 0,
0);
const IceString StrTabName(".strtab"); const IceString StrTabName(".strtab");
StrTab = StrTab =
......
...@@ -80,6 +80,15 @@ size_t ELFRelocationSection::getSectionDataSize() const { ...@@ -80,6 +80,15 @@ size_t ELFRelocationSection::getSectionDataSize() const {
// Symbol tables. // Symbol tables.
void ELFSymbolTableSection::createNullSymbol(ELFSection *NullSection) {
// The first entry in the symbol table should be a NULL entry,
// so make sure the map is still empty.
assert(LocalSymbols.empty());
const IceString NullSymName("");
createDefinedSym(NullSymName, STT_NOTYPE, STB_LOCAL, NullSection, 0, 0);
NullSymbol = findSymbol(NullSymName);
}
void ELFSymbolTableSection::createDefinedSym(const IceString &Name, void ELFSymbolTableSection::createDefinedSym(const IceString &Name,
uint8_t Type, uint8_t Binding, uint8_t Type, uint8_t Binding,
ELFSection *Section, ELFSection *Section,
...@@ -105,7 +114,9 @@ void ELFSymbolTableSection::noteUndefinedSym(const IceString &Name, ...@@ -105,7 +114,9 @@ void ELFSymbolTableSection::noteUndefinedSym(const IceString &Name,
NewSymbol.Sym.setBindingAndType(STB_GLOBAL, STT_NOTYPE); NewSymbol.Sym.setBindingAndType(STB_GLOBAL, STT_NOTYPE);
NewSymbol.Section = NullSection; NewSymbol.Section = NullSection;
NewSymbol.Number = ELFSym::UnknownNumber; NewSymbol.Number = ELFSym::UnknownNumber;
GlobalSymbols.insert(std::make_pair(Name, NewSymbol)); bool Unique = GlobalSymbols.insert(std::make_pair(Name, NewSymbol)).second;
assert(Unique);
(void)Unique;
} }
const ELFSym *ELFSymbolTableSection::findSymbol(const IceString &Name) const { const ELFSym *ELFSymbolTableSection::findSymbol(const IceString &Name) const {
......
...@@ -163,7 +163,11 @@ class ELFSymbolTableSection : public ELFSection { ...@@ -163,7 +163,11 @@ class ELFSymbolTableSection : public ELFSection {
ELFSymbolTableSection &operator=(const ELFSymbolTableSection &) = delete; ELFSymbolTableSection &operator=(const ELFSymbolTableSection &) = delete;
public: public:
using ELFSection::ELFSection; ELFSymbolTableSection(const IceString &Name, Elf64_Word ShType,
Elf64_Xword ShFlags, Elf64_Xword ShAddralign,
Elf64_Xword ShEntsize)
: ELFSection(Name, ShType, ShFlags, ShAddralign, ShEntsize),
NullSymbol(nullptr) {}
// Create initial entry for a symbol when it is defined. // Create initial entry for a symbol when it is defined.
// Each entry should only be defined once. // Each entry should only be defined once.
...@@ -179,6 +183,9 @@ public: ...@@ -179,6 +183,9 @@ public:
const ELFSym *findSymbol(const IceString &Name) const; const ELFSym *findSymbol(const IceString &Name) const;
void createNullSymbol(ELFSection *NullSection);
const ELFSym *getNullSymbol() const { return NullSymbol; }
size_t getSectionDataSize() const { size_t getSectionDataSize() const {
return (LocalSymbols.size() + GlobalSymbols.size()) * Header.sh_entsize; return (LocalSymbols.size() + GlobalSymbols.size()) * Header.sh_entsize;
} }
...@@ -198,6 +205,7 @@ private: ...@@ -198,6 +205,7 @@ private:
template <bool IsELF64> template <bool IsELF64>
void writeSymbolMap(ELFStreamer &Str, const SymMap &Map); void writeSymbolMap(ELFStreamer &Str, const SymMap &Map);
const ELFSym *NullSymbol;
// Keep Local and Global symbols separate, since the sh_info needs to // Keep Local and Global symbols separate, since the sh_info needs to
// know the index of the last LOCAL. // know the index of the last LOCAL.
SymMap LocalSymbols; SymMap LocalSymbols;
...@@ -211,7 +219,11 @@ class ELFRelocationSection : public ELFSection { ...@@ -211,7 +219,11 @@ class ELFRelocationSection : public ELFSection {
ELFRelocationSection &operator=(const ELFRelocationSection &) = delete; ELFRelocationSection &operator=(const ELFRelocationSection &) = delete;
public: public:
using ELFSection::ELFSection; ELFRelocationSection(const IceString &Name, Elf64_Word ShType,
Elf64_Xword ShFlags, Elf64_Xword ShAddralign,
Elf64_Xword ShEntsize)
: ELFSection(Name, ShType, ShFlags, ShAddralign, ShEntsize),
RelatedSection(nullptr) {}
const ELFSection *getRelatedSection() const { return RelatedSection; } const ELFSection *getRelatedSection() const { return RelatedSection; }
void setRelatedSection(const ELFSection *Section) { void setRelatedSection(const ELFSection *Section) {
...@@ -340,7 +352,11 @@ template <bool IsELF64> ...@@ -340,7 +352,11 @@ template <bool IsELF64>
void ELFRelocationSection::writeData(const GlobalContext &Ctx, ELFStreamer &Str, void ELFRelocationSection::writeData(const GlobalContext &Ctx, ELFStreamer &Str,
const ELFSymbolTableSection *SymTab) { const ELFSymbolTableSection *SymTab) {
for (const AssemblerFixup &Fixup : Fixups) { for (const AssemblerFixup &Fixup : Fixups) {
const ELFSym *Symbol = SymTab->findSymbol(Fixup.symbol(&Ctx)); const ELFSym *Symbol;
if (Fixup.isNullSymbol())
Symbol = SymTab->getNullSymbol();
else
Symbol = SymTab->findSymbol(Fixup.symbol(&Ctx));
if (!Symbol) if (!Symbol)
llvm::report_fatal_error("Missing symbol mentioned in reloc"); llvm::report_fatal_error("Missing symbol mentioned in reloc");
......
...@@ -17,7 +17,11 @@ ...@@ -17,7 +17,11 @@
namespace Ice { namespace Ice {
const Constant *AssemblerFixup::NullSymbol = nullptr;
RelocOffsetT AssemblerFixup::offset() const { RelocOffsetT AssemblerFixup::offset() const {
if (isNullSymbol())
return 0;
if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(value_)) if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(value_))
return CR->getOffset(); return CR->getOffset();
return 0; return 0;
...@@ -27,6 +31,7 @@ IceString AssemblerFixup::symbol(const GlobalContext *Ctx) const { ...@@ -27,6 +31,7 @@ IceString AssemblerFixup::symbol(const GlobalContext *Ctx) const {
std::string Buffer; std::string Buffer;
llvm::raw_string_ostream Str(Buffer); llvm::raw_string_ostream Str(Buffer);
const Constant *C = value_; const Constant *C = value_;
assert(!isNullSymbol());
if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(C)) { if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(C)) {
if (CR->getSuppressMangling()) if (CR->getSuppressMangling())
Str << CR->getName(); Str << CR->getName();
...@@ -43,6 +48,9 @@ IceString AssemblerFixup::symbol(const GlobalContext *Ctx) const { ...@@ -43,6 +48,9 @@ IceString AssemblerFixup::symbol(const GlobalContext *Ctx) const {
void AssemblerFixup::emit(GlobalContext *Ctx) const { void AssemblerFixup::emit(GlobalContext *Ctx) const {
Ostream &Str = Ctx->getStrEmit(); Ostream &Str = Ctx->getStrEmit();
// TODO(jvoung): Not yet clear how to emit a relocation against
// the null symbol.
assert(!isNullSymbol());
Str << symbol(Ctx); Str << symbol(Ctx);
RelocOffsetT Offset = offset(); RelocOffsetT Offset = offset();
if (Offset) if (Offset)
......
...@@ -38,6 +38,10 @@ public: ...@@ -38,6 +38,10 @@ public:
RelocOffsetT offset() const; RelocOffsetT offset() const;
IceString symbol(const GlobalContext *Ctx) const; IceString symbol(const GlobalContext *Ctx) const;
static const Constant *NullSymbol;
bool isNullSymbol() const { return value_ == NullSymbol; }
void set_value(const Constant *Value) { value_ = Value; } void set_value(const Constant *Value) { value_ = Value; }
void emit(GlobalContext *Ctx) const; void emit(GlobalContext *Ctx) const;
......
...@@ -489,11 +489,10 @@ void InstX8632Jmp::emitIAS(const Cfg *Func) const { ...@@ -489,11 +489,10 @@ void InstX8632Jmp::emitIAS(const Cfg *Func) const {
} else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) { } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) {
// NaCl trampoline calls refer to an address within the sandbox directly. // NaCl trampoline calls refer to an address within the sandbox directly.
// This is usually only needed for non-IRT builds and otherwise not // This is usually only needed for non-IRT builds and otherwise not
// very portable or stable. For this, we would use the 0xE8 opcode // very portable or stable. Usually this is only done for "calls"
// (relative version of call) and there should be a PC32 reloc too. // and not jumps.
// The PC32 reloc will have symbol index 0, and the absolute address // TODO(jvoung): Support this when there is a lowering that
// would be encoded as an offset relative to the next instruction. // actually triggers this case.
// TODO(jvoung): Do we need to support this?
(void)Imm; (void)Imm;
llvm::report_fatal_error("Unexpected jmp to absolute address"); llvm::report_fatal_error("Unexpected jmp to absolute address");
} else { } else {
...@@ -515,10 +514,7 @@ void InstX8632Call::emit(const Cfg *Func) const { ...@@ -515,10 +514,7 @@ void InstX8632Call::emit(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrEmit(); Ostream &Str = Func->getContext()->getStrEmit();
assert(getSrcSize() == 1); assert(getSrcSize() == 1);
Str << "\tcall\t"; Str << "\tcall\t";
if (const auto CallTarget = if (const auto CallTarget = llvm::dyn_cast<Constant>(getCallTarget())) {
llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) {
// TODO(stichnot): All constant targets should suppress the '$',
// not just relocatables.
CallTarget->emitWithoutDollar(Func->getContext()); CallTarget->emitWithoutDollar(Func->getContext());
} else { } else {
Str << "*"; Str << "*";
...@@ -544,15 +540,7 @@ void InstX8632Call::emitIAS(const Cfg *Func) const { ...@@ -544,15 +540,7 @@ void InstX8632Call::emitIAS(const Cfg *Func) const {
assert(CR->getOffset() == 0 && "We only support calling a function"); assert(CR->getOffset() == 0 && "We only support calling a function");
Asm->call(CR); Asm->call(CR);
} else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) { } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) {
// NaCl trampoline calls refer to an address within the sandbox directly. Asm->call(x86::Immediate(Imm->getValue()));
// This is usually only needed for non-IRT builds and otherwise not
// very portable or stable. For this, we would use the 0xE8 opcode
// (relative version of call) and there should be a PC32 reloc too.
// The PC32 reloc will have symbol index 0, and the absolute address
// would be encoded as an offset relative to the next instruction.
// TODO(jvoung): Do we need to support this?
(void)Imm;
llvm_unreachable("Unexpected call to absolute address");
} else { } else {
llvm_unreachable("Unexpected operand type"); llvm_unreachable("Unexpected operand type");
} }
......
...@@ -108,6 +108,7 @@ public: ...@@ -108,6 +108,7 @@ public:
} }
void emit(const Cfg *Func) const override { emit(Func->getContext()); } void emit(const Cfg *Func) const override { emit(Func->getContext()); }
virtual void emit(GlobalContext *Ctx) const = 0; virtual void emit(GlobalContext *Ctx) const = 0;
virtual void emitWithoutDollar(GlobalContext *Ctx) const = 0;
static bool classof(const Operand *Operand) { static bool classof(const Operand *Operand) {
OperandKind Kind = Operand->getKind(); OperandKind Kind = Operand->getKind();
...@@ -149,6 +150,7 @@ public: ...@@ -149,6 +150,7 @@ public:
// The target needs to implement this for each ConstantPrimitive // The target needs to implement this for each ConstantPrimitive
// specialization. // specialization.
void emit(GlobalContext *Ctx) const override; void emit(GlobalContext *Ctx) const override;
void emitWithoutDollar(GlobalContext *Ctx) const override;
using Constant::dump; using Constant::dump;
void dump(const Cfg *, Ostream &Str) const override { void dump(const Cfg *, Ostream &Str) const override {
if (ALLOW_DUMP) if (ALLOW_DUMP)
...@@ -234,7 +236,7 @@ public: ...@@ -234,7 +236,7 @@ public:
using Constant::emit; using Constant::emit;
using Constant::dump; using Constant::dump;
void emit(GlobalContext *Ctx) const override; void emit(GlobalContext *Ctx) const override;
void emitWithoutDollar(GlobalContext *Ctx) const; void emitWithoutDollar(GlobalContext *Ctx) const override;
void dump(const Cfg *Func, Ostream &Str) const override; void dump(const Cfg *Func, Ostream &Str) const override;
static bool classof(const Operand *Operand) { static bool classof(const Operand *Operand) {
...@@ -273,6 +275,7 @@ public: ...@@ -273,6 +275,7 @@ public:
using Constant::dump; using Constant::dump;
// The target needs to implement this. // The target needs to implement this.
void emit(GlobalContext *Ctx) const override; void emit(GlobalContext *Ctx) const override;
void emitWithoutDollar(GlobalContext *Ctx) const override;
void dump(const Cfg *, Ostream &Str) const override { void dump(const Cfg *, Ostream &Str) const override {
if (ALLOW_DUMP) if (ALLOW_DUMP)
Str << "undef"; Str << "undef";
......
...@@ -4599,17 +4599,34 @@ void TargetX8632::makeRandomRegisterPermutation( ...@@ -4599,17 +4599,34 @@ void TargetX8632::makeRandomRegisterPermutation(
} }
} }
template <>
void ConstantInteger32::emitWithoutDollar(GlobalContext *Ctx) const {
if (!ALLOW_DUMP)
return;
Ostream &Str = Ctx->getStrEmit();
Str << (int32_t)getValue();
}
template <> void ConstantInteger32::emit(GlobalContext *Ctx) const { template <> void ConstantInteger32::emit(GlobalContext *Ctx) const {
if (!ALLOW_DUMP) if (!ALLOW_DUMP)
return; return;
Ostream &Str = Ctx->getStrEmit(); Ostream &Str = Ctx->getStrEmit();
Str << "$" << (int32_t)getValue(); Str << "$";
emitWithoutDollar(Ctx);
}
template <> void ConstantInteger64::emitWithoutDollar(GlobalContext *) const {
llvm_unreachable("Not expecting to emitWithoutDollar 64-bit integers");
} }
template <> void ConstantInteger64::emit(GlobalContext *) const { template <> void ConstantInteger64::emit(GlobalContext *) const {
llvm_unreachable("Not expecting to emit 64-bit integers"); llvm_unreachable("Not expecting to emit 64-bit integers");
} }
template <> void ConstantFloat::emitWithoutDollar(GlobalContext *) const {
llvm_unreachable("Not expecting to emitWithoutDollar floats");
}
template <> void ConstantFloat::emit(GlobalContext *Ctx) const { template <> void ConstantFloat::emit(GlobalContext *Ctx) const {
if (!ALLOW_DUMP) if (!ALLOW_DUMP)
return; return;
...@@ -4617,6 +4634,10 @@ template <> void ConstantFloat::emit(GlobalContext *Ctx) const { ...@@ -4617,6 +4634,10 @@ template <> void ConstantFloat::emit(GlobalContext *Ctx) const {
emitPoolLabel(Str); emitPoolLabel(Str);
} }
template <> void ConstantDouble::emitWithoutDollar(GlobalContext *) const {
llvm_unreachable("Not expecting to emitWithoutDollar doubles");
}
template <> void ConstantDouble::emit(GlobalContext *Ctx) const { template <> void ConstantDouble::emit(GlobalContext *Ctx) const {
if (!ALLOW_DUMP) if (!ALLOW_DUMP)
return; return;
...@@ -4624,6 +4645,10 @@ template <> void ConstantDouble::emit(GlobalContext *Ctx) const { ...@@ -4624,6 +4645,10 @@ template <> void ConstantDouble::emit(GlobalContext *Ctx) const {
emitPoolLabel(Str); emitPoolLabel(Str);
} }
void ConstantUndef::emitWithoutDollar(GlobalContext *) const {
llvm_unreachable("Not expecting to emitWithoutDollar undef");
}
void ConstantUndef::emit(GlobalContext *) const { void ConstantUndef::emit(GlobalContext *) const {
llvm_unreachable("undef value encountered by emitter."); llvm_unreachable("undef value encountered by emitter.");
} }
......
...@@ -167,7 +167,7 @@ public: ...@@ -167,7 +167,7 @@ public:
: NaClBitcodeParser(Cursor), Translator(Translator), : NaClBitcodeParser(Cursor), Translator(Translator),
ErrorStatus(ErrorStatus), NumErrors(0), NextDefiningFunctionID(0), ErrorStatus(ErrorStatus), NumErrors(0), NextDefiningFunctionID(0),
VariableDeclarations(new Ice::VariableDeclarationList()), VariableDeclarations(new Ice::VariableDeclarationList()),
BlockParser(nullptr), StubbedConstCallValue(nullptr) {} BlockParser(nullptr) {}
~TopLevelParser() override {} ~TopLevelParser() override {}
...@@ -276,24 +276,6 @@ public: ...@@ -276,24 +276,6 @@ public:
createValueIDsForGlobalVars(); createValueIDsForGlobalVars();
} }
/// Returns a defined function reference to be used in place of
/// called constant addresses. Returns the corresponding operand
/// to replace the calling address with. Reports an error if
/// a stub could not be found, returning the CallValue.
Ice::Operand *getStubbedConstCallValue(Ice::Operand *CallValue) {
if (StubbedConstCallValue)
return StubbedConstCallValue;
for (unsigned i = 0; i < getNumFunctionIDs(); ++i) {
Ice::FunctionDeclaration *Func = getFunctionByID(i);
if (!Func->isProto()) {
StubbedConstCallValue = getGlobalConstantByID(i);
return StubbedConstCallValue;
}
}
Error("Unable to find function definition to stub constant calls with");
return CallValue;
}
/// Returns the number of function declarations in the bitcode file. /// Returns the number of function declarations in the bitcode file.
unsigned getNumFunctionIDs() const { return FunctionDeclarationList.size(); } unsigned getNumFunctionIDs() const { return FunctionDeclarationList.size(); }
...@@ -383,8 +365,6 @@ private: ...@@ -383,8 +365,6 @@ private:
// The block parser currently being applied. Used for error // The block parser currently being applied. Used for error
// reporting. // reporting.
BlockParserBaseClass *BlockParser; BlockParserBaseClass *BlockParser;
// Value to use to stub constant calls.
Ice::Operand *StubbedConstCallValue;
bool ParseBlock(unsigned BlockID) override; bool ParseBlock(unsigned BlockID) override;
...@@ -510,8 +490,8 @@ bool TopLevelParser::ErrorAt(naclbitc::ErrorLevel Level, uint64_t Bit, ...@@ -510,8 +490,8 @@ bool TopLevelParser::ErrorAt(naclbitc::ErrorLevel Level, uint64_t Bit,
raw_ostream &OldErrStream = setErrStream(Context->getStrDump()); raw_ostream &OldErrStream = setErrStream(Context->getStrDump());
NaClBitcodeParser::ErrorAt(Level, Bit, Message); NaClBitcodeParser::ErrorAt(Level, Bit, Message);
setErrStream(OldErrStream); setErrStream(OldErrStream);
if (Level >= naclbitc::Error if (Level >= naclbitc::Error &&
&& !Translator.getFlags().getAllowErrorRecovery()) !Translator.getFlags().getAllowErrorRecovery())
Fatal(); Fatal();
return true; return true;
} }
...@@ -677,8 +657,8 @@ bool TopLevelParser::BlockError(const std::string &Message) { ...@@ -677,8 +657,8 @@ bool TopLevelParser::BlockError(const std::string &Message) {
} }
// Generates an error Message with the bit address prefixed to it. // Generates an error Message with the bit address prefixed to it.
bool BlockParserBaseClass::ErrorAt( bool BlockParserBaseClass::ErrorAt(naclbitc::ErrorLevel Level, uint64_t Bit,
naclbitc::ErrorLevel Level, uint64_t Bit, const std::string &Message) { const std::string &Message) {
std::string Buffer; std::string Buffer;
raw_string_ostream StrBuf(Buffer); raw_string_ostream StrBuf(Buffer);
// Note: If dump routines have been turned off, the error messages // Note: If dump routines have been turned off, the error messages
...@@ -2507,10 +2487,6 @@ void FunctionParser::ProcessRecord() { ...@@ -2507,10 +2487,6 @@ void FunctionParser::ProcessRecord() {
return; return;
} }
} else { } else {
if (getFlags().getStubConstantCalls() &&
llvm::isa<Ice::ConstantInteger32>(Callee)) {
Callee = Context->getStubbedConstCallValue(Callee);
}
ReturnType = Context->getSimpleTypeByID(Values[2]); ReturnType = Context->getSimpleTypeByID(Values[2]);
} }
......
...@@ -112,6 +112,17 @@ void AssemblerX86::call(const ConstantRelocatable *label) { ...@@ -112,6 +112,17 @@ void AssemblerX86::call(const ConstantRelocatable *label) {
(void)call_start; (void)call_start;
} }
void AssemblerX86::call(const Immediate &abs_address) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
intptr_t call_start = buffer_.GetPosition();
EmitUint8(0xE8);
EmitFixup(
this->createFixup(llvm::ELF::R_386_PC32, AssemblerFixup::NullSymbol));
EmitInt32(abs_address.value() - 4);
assert((buffer_.GetPosition() - call_start) == kCallExternalLabelSize);
(void)call_start;
}
void AssemblerX86::pushl(GPRRegister reg) { void AssemblerX86::pushl(GPRRegister reg) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_); AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0x50 + reg); EmitUint8(0x50 + reg);
......
...@@ -475,6 +475,7 @@ public: ...@@ -475,6 +475,7 @@ public:
void call(GPRRegister reg); void call(GPRRegister reg);
void call(const Address &address); void call(const Address &address);
void call(const ConstantRelocatable *label); void call(const ConstantRelocatable *label);
void call(const Immediate &abs_address);
static const intptr_t kCallExternalLabelSize = 5; static const intptr_t kCallExternalLabelSize = 5;
......
...@@ -176,12 +176,6 @@ static cl::opt<bool> AllowErrorRecovery( ...@@ -176,12 +176,6 @@ static cl::opt<bool> AllowErrorRecovery(
cl::desc("Allow error recovery when reading PNaCl bitcode."), cl::desc("Allow error recovery when reading PNaCl bitcode."),
cl::init(false)); cl::init(false));
// TODO(kschimpf) Remove once the emitter handles these cases.
static cl::opt<bool>
StubConstantCalls("stub-const-calls",
cl::desc("Stub indirect calls to constants."),
cl::init(false));
static cl::opt<bool> LLVMVerboseErrors( static cl::opt<bool> LLVMVerboseErrors(
"verbose-llvm-parse-errors", "verbose-llvm-parse-errors",
cl::desc("Print out more descriptive PNaCl bitcode parse errors when " cl::desc("Print out more descriptive PNaCl bitcode parse errors when "
...@@ -311,7 +305,6 @@ int main(int argc, char **argv) { ...@@ -311,7 +305,6 @@ int main(int argc, char **argv) {
Flags.setFunctionSections(FunctionSections); Flags.setFunctionSections(FunctionSections);
Flags.setNumTranslationThreads(NumThreads); Flags.setNumTranslationThreads(NumThreads);
Flags.setPhiEdgeSplit(EnablePhiEdgeSplit); Flags.setPhiEdgeSplit(EnablePhiEdgeSplit);
Flags.setStubConstantCalls(StubConstantCalls);
Flags.setSubzeroTimingEnabled(SubzeroTimingEnabled); Flags.setSubzeroTimingEnabled(SubzeroTimingEnabled);
Flags.setTimeEachFunction(TimeEachFunction); Flags.setTimeEachFunction(TimeEachFunction);
Flags.setTimingFocusOn(TimingFocusOn); Flags.setTimingFocusOn(TimingFocusOn);
......
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
; RUN: %p2i --filetype=obj --disassemble -i %s --args -O2 \ ; RUN: %p2i --filetype=obj --disassemble -i %s --args -O2 \
; RUN: | FileCheck %s ; RUN: | FileCheck %s
; RUN: %if --need=allow_dump --command %p2i --filetype=asm --assemble \
; RUN: --disassemble -i %s --args -O2 \
; RUN: | %if --need=allow_dump --command FileCheck %s
; RUN: %p2i --filetype=obj --disassemble -i %s --args -Om1 \ ; RUN: %p2i --filetype=obj --disassemble -i %s --args -Om1 \
; RUN: | FileCheck --check-prefix=OPTM1 %s ; RUN: | FileCheck --check-prefix=OPTM1 %s
...@@ -62,14 +65,23 @@ entry: ...@@ -62,14 +65,23 @@ entry:
; OPTM1: call [[TARGET]] ; OPTM1: call [[TARGET]]
; Calling an absolute address is used for non-IRT PNaCl pexes to directly ; Calling an absolute address is used for non-IRT PNaCl pexes to directly
; access syscall trampolines. Do we need to support this? ; access syscall trampolines. This is not really an indirect call, but
; define internal void @CallIndirectConst() { ; there is a cast from int to pointer first.
; entry: define internal void @CallConst() {
; %__1 = inttoptr i32 66496 to void ()* entry:
; call void %__1() %__1 = inttoptr i32 66496 to void ()*
; call void %__1() call void %__1()
; call void %__1() call void %__1()
; call void %__1() call void %__1()
; call void %__1() ret void
; ret void }
; }
; CHECK-LABEL: CallConst
; CHECK: e8 bc 03 01 00 call {{[0-9a-f]+}} {{.*}} R_386_PC32 *ABS*
; CHECK: e8 bc 03 01 00 call {{[0-9a-f]+}} {{.*}} R_386_PC32 *ABS*
; CHECK: e8 bc 03 01 00 call {{[0-9a-f]+}} {{.*}} R_386_PC32 *ABS*
;
; OPTM1-LABEL: CallConst
; OPTM1: e8 bc 03 01 00 call {{[0-9a-f]+}} {{.*}} R_386_PC32 *ABS*
; OPTM1: e8 bc 03 01 00 call {{[0-9a-f]+}} {{.*}} R_386_PC32 *ABS*
; OPTM1: e8 bc 03 01 00 call {{[0-9a-f]+}} {{.*}} R_386_PC32 *ABS*
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