Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ class Sema final {

OpenCLOptions OpenCLFeatures;
FPOptions CurFPFeatures;
LangOptions::CheerpDefaultEnvMode CurCheerpEnv;
LangAS CurCheerpFallbackAS;

const LangOptions &LangOpts;
Preprocessor &PP;
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/CGDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1443,7 +1443,8 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
QualType Ty = D.getType();
assert(
Ty.getAddressSpace() == LangAS::Default ||
(Ty.getAddressSpace() == LangAS::opencl_private && getLangOpts().OpenCL));
(Ty.getAddressSpace() == LangAS::opencl_private && getLangOpts().OpenCL) ||
(Qualifiers::isCheerpAddressSpace(Ty.getAddressSpace()) && getLangOpts().Cheerp));

AutoVarEmission emission(D);

Expand Down
8 changes: 7 additions & 1 deletion clang/lib/Sema/SemaAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1163,7 +1163,13 @@ void Sema::ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc) {
}

void Sema::ActOnPragmaCheerpEnv(LangOptions::CheerpDefaultEnvMode Mode, SourceLocation PragmaLoc) {
CurCheerpEnv = Mode;
if (Mode == LangOptions::CheerpDefaultEnvMode::GenericJS) {
CurCheerpFallbackAS = LangAS::cheerp_genericjs;
} else if (Mode == LangOptions::CheerpDefaultEnvMode::Wasm) {
CurCheerpFallbackAS = LangAS::cheerp_wasm;
} else {
CurCheerpFallbackAS = LangAS::Default;
}
}

void Sema::ActOnPragmaMSOptimize(SourceLocation Loc, bool IsOn) {
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Sema/SemaCheerp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -804,9 +804,9 @@ cheerp::CheerpAttributeToAdd cheerp::getCheerpAttributeToAdd(clang::Sema& S, con
}

// Or set default attr based on default
if (S.CurCheerpEnv == clang::LangOptions::Wasm)
if (S.CurCheerpFallbackAS == clang::LangAS::cheerp_wasm)
return CheerpAttributeToAdd::AsmJSLike;
else if (S.CurCheerpEnv == clang::LangOptions::GenericJS)
else if (S.CurCheerpFallbackAS == clang::LangAS::cheerp_genericjs)
return CheerpAttributeToAdd::GenericJS;
else
return CheerpAttributeToAdd::None;
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4135,7 +4135,10 @@ Sema::IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType) {
= ToPtrType->getPointeeType()->getAs<BuiltinType>()) {
// This conversion is considered only when there is an
// explicit appropriate pointer target type (C++ 4.2p2).
if (!ToPtrType->getPointeeType().hasQualifiers()) {
if (!ToPtrType->getPointeeType().hasQualifiers() ||
// CHEERP: Also allow this conversion when the target type has
// non-cvr qualifiers, such as address spaces.
(getLangOpts().Cheerp && !ToPtrType->getPointeeType().getCVRQualifiers())) {
switch (StrLit->getKind()) {
case StringLiteral::UTF8:
case StringLiteral::UTF16:
Expand Down
33 changes: 31 additions & 2 deletions clang/lib/Sema/SemaInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4935,13 +4935,42 @@ static void TryReferenceInitializationCore(Sema &S,
const Type *T1Ptr = T1.getTypePtr();
const Type *T2Ptr = T2.getTypePtr();

// CHEERP: Skip the address space check. This makes it so we can implicitly
// construct objects in one address space, by calling a constructor that
// takes an argument in an incompatible address space.
//
// For example:
//
// namespace client [[cheerp::genericjs]] {
// class [[cheerp::client_layout]] String {
// public:
// String();
// String(const char *str) : String() {}
// };
// }
//
// [[cheerp::genericjs]]
// void foo(const client::String &str);
//
// [[cheerp::genericjs]]
// int main() {
// // NOTE: "hello" is wasm_as when compiling with
// // "-target cheerp-wasm", even though main is a js function.
// foo("hello");
// }
//
// Skipping the check entirely may allow some invalid code, but we ignore
// this for now.
bool canInitializeAddressSpace = S.getLangOpts().Cheerp ||
T1Quals.isAddressSpaceSupersetOf(T2Quals, T1Ptr, T2Ptr);

// - Otherwise, the reference shall be an lvalue reference to a
// non-volatile const type (i.e., cv1 shall be const), or the reference
// shall be an rvalue reference.
// For address spaces, we interpret this to mean that an addr space
// of a reference "cv1 T1" is a superset of addr space of "cv2 T2".
if (isLValueRef && !(T1Quals.hasConst() && !T1Quals.hasVolatile() &&
T1Quals.isAddressSpaceSupersetOf(T2Quals, T1Ptr, T2Ptr))) {
canInitializeAddressSpace)) {
if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy)
Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
else if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
Expand All @@ -4950,7 +4979,7 @@ static void TryReferenceInitializationCore(Sema &S,
ConvOvlResult);
else if (!InitCategory.isLValue())
Sequence.SetFailed(
T1Quals.isAddressSpaceSupersetOf(T2Quals, T1Ptr, T2Ptr)
canInitializeAddressSpace
? InitializationSequence::
FK_NonConstLValueReferenceBindingToTemporary
: InitializationSequence::FK_ReferenceInitDropsQualifiers);
Expand Down
8 changes: 8 additions & 0 deletions libcxx/include/locale
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,10 @@ template <class charT> class messages_byname;
#include <streambuf>
#include <version>

#ifdef __CHEERP__
#define free reinterpret_cast<void(*)(void*)>(free)
#endif

#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
// Most unix variants have catopen. These are the specific ones that don't.
# if !defined(__BIONIC__) && !defined(_NEWLIB_VERSION) && !defined(__EMSCRIPTEN__)
Expand Down Expand Up @@ -4375,4 +4379,8 @@ _LIBCPP_POP_MACROS
# include <typeinfo>
#endif

#ifdef __CHEERP__
#undef free
#endif

#endif // _LIBCPP_LOCALE
6 changes: 5 additions & 1 deletion libcxx/include/stdexcept
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,11 @@ public:
_LIBCPP_BEGIN_NAMESPACE_STD

typedef int count_t;
struct [[cheerp::bytelayout]] _Rep_base {
struct
#if defined(__CHEERP__) && !defined(__ASMJS__)
[[cheerp::bytelayout]]
#endif
_Rep_base {
std::size_t len;
std::size_t cap;
count_t count;
Expand Down
13 changes: 9 additions & 4 deletions libcxx/src/ios.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,15 +279,20 @@ ios_base::init(void* sb)
::new(&__loc_) locale;
}

#ifdef __CHEERP__
#define indirectfree reinterpret_cast<void(*)(void*)>(free)
#else
#define indirectfree free
#endif
void
ios_base::copyfmt(const ios_base& rhs)
{
// If we can't acquire the needed resources, throw bad_alloc (can't set badbit)
// Don't alter *this until all needed resources are acquired
unique_ptr<event_callback, void (*)(void*)> new_callbacks(0, free);
unique_ptr<int, void (*)(void*)> new_ints(0, free);
unique_ptr<long, void (*)(void*)> new_longs(0, free);
unique_ptr<void*, void (*)(void*)> new_pointers(0, free);
unique_ptr<event_callback, void (*)(void*)> new_callbacks(0, indirectfree);
unique_ptr<int, void (*)(void*)> new_ints(0, indirectfree);
unique_ptr<long, void (*)(void*)> new_longs(0, indirectfree);
unique_ptr<void*, void (*)(void*)> new_pointers(0, indirectfree);
if (__event_cap_ < rhs.__event_size_)
{
size_t newesize = sizeof(event_callback) * rhs.__event_size_;
Expand Down
Loading