dawn: Make ASSERT() breakpoint on all supported platforms.

This moves the implementation of DAWN_BREAKPOINT() in the only file
that uses it and completes it for all supported architectures. If in
the future breakpoints are needed in other places, it would be possible
to expose the function in a header.

Add DAWN_PLATFORM_IS macros for all supported architectures so they can
be used for implementing Breakpoint() and add support for RISCV.

Bug: dawn:1506
Change-Id: Ib1b92c2d0c119cfc1b348fe905029fe366f5ad04
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/98121
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Loko Kung <lokokung@google.com>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn/common/Assert.cpp b/src/dawn/common/Assert.cpp
index 2599e12..ecc92df 100644
--- a/src/dawn/common/Assert.cpp
+++ b/src/dawn/common/Assert.cpp
@@ -17,6 +17,38 @@
 #include <cstdlib>
 
 #include "dawn/common/Log.h"
+#include "dawn/common/Platform.h"
+
+#if DAWN_COMPILER_IS(CLANG) || DAWN_COMPILER_IS(GCC)
+void BreakPoint() {
+#if DAWN_PLATFORM_IS(X86)
+    __asm__ __volatile__("int $3\n\t");
+#elif DAWN_PLATFORM_IS(ARM32)
+    __asm__ __volatile__("bkpt 0");
+#elif DAWN_PLATFORM_IS(ARM64)
+    __asm__ __volatile__("brk 0");
+#elif DAWN_PLATFORM_IS(RISCV)
+    __asm__ __volatile__("ebreak");
+#elif DAWN_PLATFORM_IS(MIPS)
+    __asm__ __volatile__("break");
+#elif DAWN_PLATFORM_IS(S390) || DAWN_PLATFORM_IS_(S390X)
+    __asm__ __volatile__(".word 0x0001");
+#elif DAWN_PLATFORM_IS(PPC) || DAWN_PLATFORM_IS_(PPC64)
+    __asm__ __volatile__("twge 2,2");
+#else
+#error "Unsupported platform"
+#endif
+}
+
+#elif DAWN_COMPILER_IS(MSVC)
+extern void __cdecl __debugbreak(void);
+void BreakPoint() {
+    __debugbreak();
+}
+
+#else
+#error "Unsupported compiler"
+#endif
 
 void HandleAssertionFailure(const char* file,
                             const char* function,
@@ -27,6 +59,6 @@
 #if defined(DAWN_ABORT_ON_ASSERT)
     abort();
 #else
-    DAWN_BREAKPOINT();
+    BreakPoint();
 #endif
 }
diff --git a/src/dawn/common/Compiler.h b/src/dawn/common/Compiler.h
index eb7e623..e55f969 100644
--- a/src/dawn/common/Compiler.h
+++ b/src/dawn/common/Compiler.h
@@ -17,7 +17,6 @@
 
 // Defines macros for compiler-specific functionality
 //  - DAWN_COMPILER_IS(CLANG|GCC|MSVC): Compiler detection
-//  - DAWN_BREAKPOINT(): Raises an exception and breaks in the debugger
 //  - DAWN_BUILTIN_UNREACHABLE(): Hints the compiler that a code path is unreachable
 //  - DAWN_(UN)?LIKELY(EXPR): Where available, hints the compiler that the expression will be true
 //      (resp. false) to help it generate code that leads to better branch prediction.
@@ -35,13 +34,6 @@
 #define DAWN_COMPILER_IS_GCC 1
 #endif
 
-#if defined(__i386__) || defined(__x86_64__)
-#define DAWN_BREAKPOINT() __asm__ __volatile__("int $3\n\t")
-#else
-// TODO(cwallez@chromium.org): Implement breakpoint on all supported architectures
-#define DAWN_BREAKPOINT()
-#endif
-
 #define DAWN_BUILTIN_UNREACHABLE() __builtin_unreachable()
 #define DAWN_LIKELY(x) __builtin_expect(!!(x), 1)
 #define DAWN_UNLIKELY(x) __builtin_expect(!!(x), 0)
@@ -60,9 +52,6 @@
 #elif defined(_MSC_VER)
 #define DAWN_COMPILER_IS_MSVC 1
 
-extern void __cdecl __debugbreak(void);
-#define DAWN_BREAKPOINT() __debugbreak()
-
 #define DAWN_BUILTIN_UNREACHABLE() __assume(false)
 
 #define DAWN_DECLARE_UNUSED
diff --git a/src/dawn/common/Platform.h b/src/dawn/common/Platform.h
index 2a86434..39d5eb4 100644
--- a/src/dawn/common/Platform.h
+++ b/src/dawn/common/Platform.h
@@ -15,6 +15,25 @@
 #ifndef SRC_DAWN_COMMON_PLATFORM_H_
 #define SRC_DAWN_COMMON_PLATFORM_H_
 
+// Use #if DAWN_PLATFORM_IS(X) for platform specific code.
+// Do not use #ifdef or the naked macro DAWN_PLATFORM_IS_X.
+// This can help avoid common mistakes like not including "Platform.h" and falling into unwanted
+// code block as usage of undefined macro "function" will be blocked by the compiler.
+#define DAWN_PLATFORM_IS(X) (1 == DAWN_PLATFORM_IS_##X)
+
+// Define platform macros for OSes:
+//
+//  - WINDOWS
+//    - WIN32
+//    - WINUWP
+//  - POSIX
+//    - LINUX
+//      - ANDROID
+//    - APPLE
+//      - IOS
+//      - MACOS
+//    - FUCHSIA
+//    - EMSCRIPTEN
 #if defined(_WIN32) || defined(_WIN64)
 #include <winapifamily.h>
 #define DAWN_PLATFORM_IS_WINDOWS 1
@@ -57,22 +76,81 @@
 #error "Unsupported platform."
 #endif
 
-// Distinguish mips32.
-#if defined(__mips__) && (_MIPS_SIM == _ABIO32) && !defined(__mips32__)
-#define __mips32__
+// Define platform macros for CPU architectures:
+//
+//  - X86
+//    - I386
+//    - X86_64
+//  - ARM
+//    - ARM32
+//    - ARM64
+//  - RISCV
+//    - RISCV32
+//    - RISCV64
+//  - MIPS
+//    - MIPS32
+//    - MIPS64
+//  - S390
+//  - S390X
+//  - PPC
+//  - PPC64
+#if defined(__i386__) || defined(_M_IX86)
+#define DAWN_PLATFORM_IS_X86 1
+#define DAWN_PLATFORM_IS_I386 1
+#elif defined(__x86_64__) || defined(_M_X64)
+#define DAWN_PLATFORM_IS_X86 1
+#define DAWN_PLATFORM_IS_X86_64 1
+
+#elif defined(__arm__) || defined(_M_ARM)
+#define DAWN_PLATFORM_IS_ARM 1
+#define DAWN_PLATFORM_IS_ARM32 1
+#elif defined(__aarch64__) || defined(_M_ARM64)
+#define DAWN_PLATFORM_IS_ARM 1
+#define DAWN_PLATFORM_IS_ARM64 1
+
+#elif defined(__riscv)
+#define DAWN_PLATFORM_IS_RISCV 1
+#if __riscv_xlen == 32
+#define DAWN_PLATFORM_IS_RISCV32 1
+#else
+#define DAWN_PLATFORM_IS_RISCV64 1
 #endif
 
-// Distinguish mips64.
-#if defined(__mips__) && (_MIPS_SIM == _ABI64) && !defined(__mips64__)
-#define __mips64__
+#elif defined(__mips__)
+#define DAWN_PLATFORM_IS_MIPS 1
+#if _MIPS_SIM == _ABIO32
+#define DAWN_PLATFORM_IS_MIPS32 1
+#else
+#define DAWN_PLATFORM_IS_MIPS64 1
 #endif
 
-#if defined(_WIN64) || defined(__aarch64__) || defined(__x86_64__) || defined(__mips64__) || \
-    defined(__s390x__) || defined(__PPC64__)
+#elif defiend(__s390__)
+#define DAWN_PLATFORM_IS_S390 1
+#elif defiend(__s390x__)
+#define DAWN_PLATFORM_IS_S390X 1
+
+#elif defined(__PPC__)
+#define DAWN_PLATFORM_IS_PPC 1
+#elif defined(__PPC64__)
+#define DAWN_PLATFORM_IS_PPC64 1
+
+#else
+#error "Unsupported platform."
+#endif
+
+// Define platform macros for pointer width:
+//
+//  - 64_BIT
+//  - 32_BIT
+#if defined(DAWN_PLATFORM_IS_X86_64) || defined(DAWN_PLATFORM_IS_ARM64) ||   \
+    defined(DAWN_PLATFORM_IS_RISCV64) || defined(DAWN_PLATFORM_IS_MIPS64) || \
+    defined(DAWN_PLATFORM_IS_S390X) || defined(DAWN_PLATFORM_IS_PPC64)
 #define DAWN_PLATFORM_IS_64_BIT 1
 static_assert(sizeof(sizeof(char)) == 8, "Expect sizeof(size_t) == 8");
-#elif defined(_WIN32) || defined(__arm__) || defined(__i386__) || defined(__mips32__) || \
-    defined(__s390__) || defined(__EMSCRIPTEN__)
+#elif defined(DAWN_PLATFORM_IS_I386) || defined(DAWN_PLATFORM_IS_ARM32) ||   \
+    defined(DAWN_PLATFORM_IS_RISCV32) || defined(DAWN_PLATFORM_IS_MIPS32) || \
+    defined(DAWN_PLATFORM_IS_S390) || defined(DAWN_PLATFORM_IS_PPC32) ||     \
+    defined(DAWN_PLATFORM_IS_EMSCRIPTEN)
 #define DAWN_PLATFORM_IS_32_BIT 1
 static_assert(sizeof(sizeof(char)) == 4, "Expect sizeof(size_t) == 4");
 #else
@@ -118,6 +196,60 @@
 #define DAWN_PLATFORM_IS_EMSCRIPTEN 0
 #endif
 
+#if !defined(DAWN_PLATFORM_IS_X86)
+#define DAWN_PLATFORM_IS_X86 0
+#endif
+#if !defined(DAWN_PLATFORM_IS_I386)
+#define DAWN_PLATFORM_IS_I386 0
+#endif
+#if !defined(DAWN_PLATFORM_IS_X86_64)
+#define DAWN_PLATFORM_IS_X86_64 0
+#endif
+
+#if !defined(DAWN_PLATFORM_IS_ARM)
+#define DAWN_PLATFORM_IS_ARM 0
+#endif
+#if !defined(DAWN_PLATFORM_IS_ARM32)
+#define DAWN_PLATFORM_IS_ARM32 0
+#endif
+#if !defined(DAWN_PLATFORM_IS_ARM64)
+#define DAWN_PLATFORM_IS_ARM64 0
+#endif
+
+#if !defined(DAWN_PLATFORM_IS_RISCV)
+#define DAWN_PLATFORM_IS_RISCV 0
+#endif
+#if !defined(DAWN_PLATFORM_IS_RISCV32)
+#define DAWN_PLATFORM_IS_RISCV32 0
+#endif
+#if !defined(DAWN_PLATFORM_IS_RISCV64)
+#define DAWN_PLATFORM_IS_RISCV64 0
+#endif
+
+#if !defined(DAWN_PLATFORM_IS_MIPS)
+#define DAWN_PLATFORM_IS_MIPS 0
+#endif
+#if !defined(DAWN_PLATFORM_IS_MIPS32)
+#define DAWN_PLATFORM_IS_MIPS32 0
+#endif
+#if !defined(DAWN_PLATFORM_IS_MIPS64)
+#define DAWN_PLATFORM_IS_MIPS64 0
+#endif
+
+#if !defined(DAWN_PLATFORM_IS_S390)
+#define DAWN_PLATFORM_IS_S390 0
+#endif
+#if !defined(DAWN_PLATFORM_IS_S390X)
+#define DAWN_PLATFORM_IS_S390X 0
+#endif
+
+#if !defined(DAWN_PLATFORM_IS_PPC)
+#define DAWN_PLATFORM_IS_PPC 0
+#endif
+#if !defined(DAWN_PLATFORM_IS_PPC64)
+#define DAWN_PLATFORM_IS_PPC64 0
+#endif
+
 #if !defined(DAWN_PLATFORM_IS_64_BIT)
 #define DAWN_PLATFORM_IS_64_BIT 0
 #endif
@@ -125,10 +257,4 @@
 #define DAWN_PLATFORM_IS_32_BIT 0
 #endif
 
-// Use #if DAWN_PLATFORM_IS(XXX) for platform specific code.
-// Do not use #ifdef or the naked macro DAWN_PLATFORM_IS_XXX.
-// This can help avoid common mistakes like not including "Platform.h" and falling into unwanted
-// code block as usage of undefined macro "function" will be blocked by the compiler.
-#define DAWN_PLATFORM_IS(X) (1 == DAWN_PLATFORM_IS_##X)
-
 #endif  // SRC_DAWN_COMMON_PLATFORM_H_