| Index: lib/CodeGen/CGStmt.cpp
|
| diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
|
| index 5e2ebe0d9cd4656e9278c6a172513dc09ed0d77f..e9e1f014f1b55905004e0f4cd19c2d2c46d13b91 100644
|
| --- a/lib/CodeGen/CGStmt.cpp
|
| +++ b/lib/CodeGen/CGStmt.cpp
|
| @@ -1701,6 +1701,31 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
|
| Result->addAttribute(llvm::AttributeSet::FunctionIndex,
|
| llvm::Attribute::NoUnwind);
|
|
|
| + // @LOCALMOD-START
|
| + // For PNaCl, emit two compiler fences containing a sequentially
|
| + // consistent fence (just like __sync_synchronize). This should
|
| + // enforce ordering of more than just atomic memory accesses, though
|
| + // it won't guarantee that all accesses (e.g. those to non-escaping
|
| + // objects) will not be reordered.
|
| + bool isEmptyAsm = AsmString.empty();
|
| + // Different triples will encode "touch everything" differently, e.g.:
|
| + // - le32-unknown-nacl has "~{memory}".
|
| + // - x86 "~{memory},~{dirflag},~{fpsr},~{flags}".
|
| + // The following code therefore only searches for memory: this pass
|
| + // deals with portable assembly, touching anything else than memory in
|
| + // an empty assembly statement is meaningless.
|
| + bool touchesMemory = Constraints.find("~{memory}") != std::string::npos;
|
| +
|
| + if (getTarget().getTriple().getArch() == llvm::Triple::le32 &&
|
| + ResultType->isVoidTy() && HasSideEffect && isEmptyAsm && touchesMemory) {
|
| + Builder.CreateFence(llvm::SequentiallyConsistent);
|
| + Builder.CreateCall(
|
| + llvm::InlineAsm::get(FTy, AsmString, Constraints, HasSideEffect))->
|
| + addAttribute(llvm::AttributeSet::FunctionIndex,
|
| + llvm::Attribute::NoUnwind);
|
| + }
|
| + // @LOCALMOD-END
|
| +
|
| // Slap the source location of the inline asm into a !srcloc metadata on the
|
| // call. FIXME: Handle metadata for MS-style inline asms.
|
| if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S))
|
|
|