llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Anutosh Bhat (anutosh491)

<details>
<summary>Changes</summary>

Fixes https://github.com/llvm/llvm-project/issues/166120

I could think of two approaches here 

1) As per the comment 
https://github.com/llvm/llvm-project/issues/166120#issuecomment-3479552518 : 
Saying we could flush after each input line. 

Yes this would make sense and work too 

Here's an **unpolished diff** where 

1) Flush after every input is parsed (through an IsFlushed var that is toggled 
for each input)
2) Once the flush is performed, we don't care about storing it in the list of 
PTUs or tracking it so we hit undo.

```
diff --git a/clang/include/clang/Interpreter/Interpreter.h 
b/clang/include/clang/Interpreter/Interpreter.h
index 078d70b3b174..d07992a4ad02 100644
--- a/clang/include/clang/Interpreter/Interpreter.h
+++ b/clang/include/clang/Interpreter/Interpreter.h
@@ -234,6 +234,9 @@ private:
   // This function forces emission of the needed dtor.
   llvm::Expected&lt;llvm::orc::ExecutorAddr&gt;
   CompileDtorCall(CXXRecordDecl *CXXRD) const;
+
+  bool IsOutOfProcess = false;
+  bool IsFlushing = false;
 };
 } // namespace clang
 
diff --git a/clang/lib/Interpreter/Interpreter.cpp 
b/clang/lib/Interpreter/Interpreter.cpp
index a071d0312f76..9a178487dec7 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -347,6 +347,8 @@ const char *const Runtimes = R"(
       memcpy(Placement, Src, Size);
     }
 #endif // __cplusplus
+  #include &lt;iostream&gt;
+  #include &lt;cstdio&gt;
   EXTERN_C void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*);
   EXTERN_C void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, 
void *OpaqueType, ...);
 )";
@@ -648,6 +650,7 @@ llvm::Error Interpreter::CreateExecutor(JITConfig Config) {
   bool IsWindowsTarget = TargetTriple.isOSWindows();
 
   if (!IsWindowsTarget &amp;&amp; Config.IsOutOfProcess) {
+    IsOutOfProcess = true;
     if (!JITBuilder) {
       auto ResOrErr = outOfProcessJITBuilder(Config);
       if (!ResOrErr)
@@ -732,6 +735,25 @@ llvm::Error Interpreter::ParseAndExecute(llvm::StringRef 
Code, Value *V) {
     } else
       *V = std::move(LastValue);
   }
+
+  if (IsOutOfProcess &amp;&amp; !IsFlushing) {
+    IsFlushing = true; // prevent recursion
+
+    static const char FlushSnippet[] = R"(
+      std::cout.flush();
+      std::cerr.flush();
+      std::fflush(stdout);
+      std::fflush(stderr);
+    )";
+
+    if (auto FlushErr = ParseAndExecute(FlushSnippet))
+      consumeError(std::move(FlushErr));
+
+    if (auto E = Undo())
+      consumeError(std::move(E));
+    IsFlushing = false;
+  }
+
   return llvm::Error::success();
 }
 
```

Downsides of this approach is we end up parsing and executing the above block 
for each input and then undoing the execution too everytime. Which just looks 
heavy !





---
Full diff: https://github.com/llvm/llvm-project/pull/166368.diff


1 Files Affected:

- (modified) clang/lib/Interpreter/Interpreter.cpp (+14) 


``````````diff
diff --git a/clang/lib/Interpreter/Interpreter.cpp 
b/clang/lib/Interpreter/Interpreter.cpp
index cde354c9cd8d1..f3927fc341341 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -351,6 +351,15 @@ const char *const Runtimes = R"(
   EXTERN_C void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, 
void *OpaqueType, ...);
 )";
 
+const char *const OOPRuntimes = R"(
+  #include <stdio.h>
+  __attribute__((constructor))
+  static void __clang_repl_ioinit(void) {
+    setvbuf(stdout, NULL, _IONBF, 0);
+    setvbuf(stderr, NULL, _IONBF, 0);
+  }
+)";
+
 llvm::Expected<std::pair<std::unique_ptr<llvm::orc::LLJITBuilder>, uint32_t>>
 Interpreter::outOfProcessJITBuilder(JITConfig Config) {
   std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC;
@@ -463,6 +472,11 @@ Interpreter::create(std::unique_ptr<CompilerInstance> CI, 
JITConfig Config) {
   if (auto E = Interp->ParseAndExecute(Runtimes))
     return std::move(E);
 
+  if (Config.IsOutOfProcess) {
+    if (auto E = Interp->ParseAndExecute(OOPRuntimes))
+      return std::move(E);
+  }
+
   Interp->markUserCodeStart();
 
   return std::move(Interp);

``````````

</details>


https://github.com/llvm/llvm-project/pull/166368
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to