Skip to content

Commit 3e92293

Browse files
committed
[clang-repl] Lay the foundation of pretty printing for C.
1 parent 253c28f commit 3e92293

File tree

3 files changed

+101
-80
lines changed

3 files changed

+101
-80
lines changed

clang/lib/Interpreter/Interpreter.cpp

Lines changed: 92 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
#include "llvm/Support/ErrorHandling.h"
4343
#include "llvm/Support/raw_ostream.h"
4444
#include "llvm/TargetParser/Host.h"
45+
46+
#include <cstdarg>
47+
4548
using namespace clang;
4649

4750
// FIXME: Figure out how to unify with namespace init_convenience from
@@ -250,14 +253,9 @@ Interpreter::~Interpreter() {
250253
// can't find the precise resource directory in unittests so we have to hard
251254
// code them.
252255
const char *const Runtimes = R"(
256+
#define __CLANG_REPL__ 1
253257
#ifdef __cplusplus
254258
void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*);
255-
void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*);
256-
void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, void*);
257-
void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, float);
258-
void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, double);
259-
void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, long double);
260-
void __clang_Interpreter_SetValueNoAlloc(void*,void*,void*,unsigned long long);
261259
struct __clang_Interpreter_NewTag{} __ci_newtag;
262260
void* operator new(__SIZE_TYPE__, void* __p, __clang_Interpreter_NewTag) noexcept;
263261
template <class T, class = T (*)() /*disable for arrays*/>
@@ -269,7 +267,10 @@ const char *const Runtimes = R"(
269267
void __clang_Interpreter_SetValueCopyArr(const T (*Src)[N], void* Placement, unsigned long Size) {
270268
__clang_Interpreter_SetValueCopyArr(Src[0], Placement, Size);
271269
}
270+
extern "C"
272271
#endif // __cplusplus
272+
273+
void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, ...);
273274
)";
274275

275276
llvm::Expected<std::unique_ptr<Interpreter>>
@@ -564,15 +565,17 @@ std::unique_ptr<RuntimeInterfaceBuilder> Interpreter::FindRuntimeInterface() {
564565
if (!LookupInterface(ValuePrintingInfo[NoAlloc],
565566
MagicRuntimeInterface[NoAlloc]))
566567
return nullptr;
567-
if (!LookupInterface(ValuePrintingInfo[WithAlloc],
568-
MagicRuntimeInterface[WithAlloc]))
569-
return nullptr;
570-
if (!LookupInterface(ValuePrintingInfo[CopyArray],
571-
MagicRuntimeInterface[CopyArray]))
572-
return nullptr;
573-
if (!LookupInterface(ValuePrintingInfo[NewTag],
574-
MagicRuntimeInterface[NewTag]))
575-
return nullptr;
568+
if (Ctx.getLangOpts().CPlusPlus) {
569+
if (!LookupInterface(ValuePrintingInfo[WithAlloc],
570+
MagicRuntimeInterface[WithAlloc]))
571+
return nullptr;
572+
if (!LookupInterface(ValuePrintingInfo[CopyArray],
573+
MagicRuntimeInterface[CopyArray]))
574+
return nullptr;
575+
if (!LookupInterface(ValuePrintingInfo[NewTag],
576+
MagicRuntimeInterface[NewTag]))
577+
return nullptr;
578+
}
576579

577580
return createInProcessRuntimeInterfaceBuilder(*this, Ctx, S);
578581
}
@@ -831,69 +834,82 @@ __clang_Interpreter_SetValueWithAlloc(void *This, void *OutVal,
831834
return VRef.getPtr();
832835
}
833836

834-
// Pointers, lvalue struct that can take as a reference.
835-
REPL_EXTERNAL_VISIBILITY void
836-
__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
837-
void *Val) {
838-
Value &VRef = *(Value *)OutVal;
839-
VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
840-
VRef.setPtr(Val);
841-
}
842-
843-
REPL_EXTERNAL_VISIBILITY void
844-
__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal,
845-
void *OpaqueType) {
837+
REPL_EXTERNAL_VISIBILITY
838+
extern "C" void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal,
839+
void *OpaqueType, ...) {
846840
Value &VRef = *(Value *)OutVal;
847-
VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
848-
}
849-
850-
static void SetValueDataBasedOnQualType(Value &V, unsigned long long Data) {
851-
QualType QT = V.getType();
852-
if (const auto *ET = QT->getAs<EnumType>())
853-
QT = ET->getDecl()->getIntegerType();
854-
855-
switch (QT->castAs<BuiltinType>()->getKind()) {
856-
default:
857-
llvm_unreachable("unknown type kind!");
858-
#define X(type, name) \
859-
case BuiltinType::name: \
860-
V.set##name(Data); \
861-
break;
862-
REPL_BUILTIN_TYPES
863-
#undef X
841+
Interpreter *I = static_cast<Interpreter *>(This);
842+
VRef = Value(I, OpaqueType);
843+
if (VRef.isVoid())
844+
return;
845+
846+
va_list args;
847+
va_start(args, /*last named param*/ OpaqueType);
848+
849+
QualType QT = VRef.getType();
850+
if (VRef.getKind() == Value::K_PtrOrObj) {
851+
VRef.setPtr(va_arg(args, void *));
852+
} else {
853+
if (const auto *ET = QT->getAs<EnumType>())
854+
QT = ET->getDecl()->getIntegerType();
855+
switch (QT->castAs<BuiltinType>()->getKind()) {
856+
default:
857+
llvm_unreachable("unknown type kind!");
858+
break;
859+
// Types shorter than int are resolved as int, else va_arg has UB.
860+
case BuiltinType::Bool:
861+
VRef.setBool(va_arg(args, int));
862+
break;
863+
case BuiltinType::Char_S:
864+
VRef.setChar_S(va_arg(args, int));
865+
break;
866+
case BuiltinType::SChar:
867+
VRef.setSChar(va_arg(args, int));
868+
break;
869+
case BuiltinType::Char_U:
870+
VRef.setChar_U(va_arg(args, unsigned));
871+
break;
872+
case BuiltinType::UChar:
873+
VRef.setUChar(va_arg(args, unsigned));
874+
break;
875+
case BuiltinType::Short:
876+
VRef.setShort(va_arg(args, int));
877+
break;
878+
case BuiltinType::UShort:
879+
VRef.setUShort(va_arg(args, unsigned));
880+
break;
881+
case BuiltinType::Int:
882+
VRef.setInt(va_arg(args, int));
883+
break;
884+
case BuiltinType::UInt:
885+
VRef.setUInt(va_arg(args, unsigned));
886+
break;
887+
case BuiltinType::Long:
888+
VRef.setLong(va_arg(args, long));
889+
break;
890+
case BuiltinType::ULong:
891+
VRef.setULong(va_arg(args, unsigned long));
892+
break;
893+
case BuiltinType::LongLong:
894+
VRef.setLongLong(va_arg(args, long long));
895+
break;
896+
case BuiltinType::ULongLong:
897+
VRef.setULongLong(va_arg(args, unsigned long long));
898+
break;
899+
// Types shorter than double are resolved as double, else va_arg has UB.
900+
case BuiltinType::Float:
901+
VRef.setFloat(va_arg(args, double));
902+
break;
903+
case BuiltinType::Double:
904+
VRef.setDouble(va_arg(args, double));
905+
break;
906+
case BuiltinType::LongDouble:
907+
VRef.setLongDouble(va_arg(args, long double));
908+
break;
909+
// See REPL_BUILTIN_TYPES.
910+
}
864911
}
865-
}
866-
867-
REPL_EXTERNAL_VISIBILITY void
868-
__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
869-
unsigned long long Val) {
870-
Value &VRef = *(Value *)OutVal;
871-
VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
872-
SetValueDataBasedOnQualType(VRef, Val);
873-
}
874-
875-
REPL_EXTERNAL_VISIBILITY void
876-
__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
877-
float Val) {
878-
Value &VRef = *(Value *)OutVal;
879-
VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
880-
VRef.setFloat(Val);
881-
}
882-
883-
REPL_EXTERNAL_VISIBILITY void
884-
__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
885-
double Val) {
886-
Value &VRef = *(Value *)OutVal;
887-
VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
888-
VRef.setDouble(Val);
889-
}
890-
891-
REPL_EXTERNAL_VISIBILITY void
892-
__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
893-
long double Val) {
894-
Value &VRef = *(Value *)OutVal;
895-
VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
896-
VRef.setLongDouble(Val);
912+
va_end(args);
897913
}
898914

899915
// A trampoline to work around the fact that operator placement new cannot

clang/lib/Parse/ParseStmt.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -563,11 +563,8 @@ StmtResult Parser::ParseExprStatement(ParsedStmtContext StmtCtx) {
563563
}
564564

565565
Token *CurTok = nullptr;
566-
// If the semicolon is missing at the end of REPL input, consider if
567-
// we want to do value printing. Note this is only enabled in C++ mode
568-
// since part of the implementation requires C++ language features.
569566
// Note we shouldn't eat the token since the callback needs it.
570-
if (Tok.is(tok::annot_repl_input_end) && Actions.getLangOpts().CPlusPlus)
567+
if (Tok.is(tok::annot_repl_input_end))
571568
CurTok = &Tok;
572569
else
573570
// Otherwise, eat the semicolon.

clang/test/Interpreter/pretty-print.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// REQUIRES: host-supports-jit
2+
// UNSUPPORTED: system-aix
3+
// RUN: cat %s | clang-repl -Xcc -xc | FileCheck %s
4+
// RUN: cat %s | clang-repl -Xcc -std=c++11 | FileCheck %s
5+
6+
const char* c_str = "Hello, world!"; c_str
7+
8+
// CHECK: Not implement yet.

0 commit comments

Comments
 (0)