Add `ENABLE_ASSERTIONS` build option

Add the new build option `ENABLE_ASSERTIONS` that controls whether or
not assert functions are compiled out. It defaults to 1 for debug builds
and to 0 for release builds.

Additionally, a following patch will be done to allow this build option
to hide auxiliary code used for the checks done in an `assert()`. This
code is is currently under the DEBUG build flag.

Assert messages are now only printed if LOG_LEVEL >= LOG_LEVEL_INFO,
which is the default for debug builds.

This patch also updates the User Guide.

Change-Id: I1401530b56bab25561bb0f274529f1d12c5263bc
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
diff --git a/Makefile b/Makefile
index 02aa50e..d03c2bf 100644
--- a/Makefile
+++ b/Makefile
@@ -52,8 +52,9 @@
 
 include ${MAKE_HELPERS_DIRECTORY}defaults.mk
 
-# ASM_ASSERTION enabled for DEBUG builds only
+# Assertions enabled for DEBUG builds by default
 ASM_ASSERTION			:= ${DEBUG}
+ENABLE_ASSERTIONS		:= ${DEBUG}
 ENABLE_PMF			:= ${ENABLE_RUNTIME_INSTRUMENTATION}
 PLAT				:= ${DEFAULT_PLAT}
 
@@ -446,6 +447,7 @@
 $(eval $(call assert_boolean,CTX_INCLUDE_FPREGS))
 $(eval $(call assert_boolean,DEBUG))
 $(eval $(call assert_boolean,DISABLE_PEDANTIC))
+$(eval $(call assert_boolean,ENABLE_ASSERTIONS))
 $(eval $(call assert_boolean,ENABLE_PLAT_COMPAT))
 $(eval $(call assert_boolean,ENABLE_PMF))
 $(eval $(call assert_boolean,ENABLE_PSCI_STAT))
@@ -482,6 +484,7 @@
 $(eval $(call add_define,COLD_BOOT_SINGLE_CPU))
 $(eval $(call add_define,CTX_INCLUDE_AARCH32_REGS))
 $(eval $(call add_define,CTX_INCLUDE_FPREGS))
+$(eval $(call add_define,ENABLE_ASSERTIONS))
 $(eval $(call add_define,ENABLE_PLAT_COMPAT))
 $(eval $(call add_define,ENABLE_PMF))
 $(eval $(call add_define,ENABLE_PSCI_STAT))
diff --git a/common/aarch32/debug.S b/common/aarch32/debug.S
index 77298a1..bafce7c 100644
--- a/common/aarch32/debug.S
+++ b/common/aarch32/debug.S
@@ -107,6 +107,11 @@
  * ---------------------------------------------------------------------------
  */
 func asm_assert
+#if LOG_LEVEL >= LOG_LEVEL_INFO
+	/*
+	 * Only print the output if LOG_LEVEL is higher or equal to
+	 * LOG_LEVEL_INFO, which is the default value for builds with DEBUG=1.
+	 */
 	/* Stash the parameters already in r0 and r1 */
 	mov	r5, r0
 	mov	r6, r1
@@ -147,6 +152,7 @@
 	bl	plat_crash_console_flush
 
 1:
+#endif /* LOG_LEVEL >= LOG_LEVEL_INFO */
 	no_ret	plat_panic_handler
 endfunc asm_assert
 #endif
diff --git a/common/aarch64/debug.S b/common/aarch64/debug.S
index fb6924e..3d8e0f4 100644
--- a/common/aarch64/debug.S
+++ b/common/aarch64/debug.S
@@ -78,6 +78,11 @@
  * ---------------------------------------------------------------------------
  */
 func asm_assert
+#if LOG_LEVEL >= LOG_LEVEL_INFO
+	/*
+	 * Only print the output if LOG_LEVEL is higher or equal to
+	 * LOG_LEVEL_INFO, which is the default value for builds with DEBUG=1.
+	 */
 	mov	x5, x0
 	mov	x6, x1
 	/* Ensure the console is initialized */
@@ -98,6 +103,7 @@
 	asm_print_line_dec
 	bl	plat_crash_console_flush
 _assert_loop:
+#endif /* LOG_LEVEL >= LOG_LEVEL_INFO */
 	no_ret	plat_panic_handler
 endfunc asm_assert
 #endif
diff --git a/docs/user-guide.md b/docs/user-guide.md
index a1df965..af08360 100644
--- a/docs/user-guide.md
+++ b/docs/user-guide.md
@@ -286,6 +286,14 @@
     payload. Please refer to the "Booting an EL3 payload" section for more
     details.
 
+*   `ENABLE_ASSERTIONS`: This option controls whether or not calls to `assert()`
+    are compiled out. For debug builds, this option defaults to 1, and calls to
+    `assert()` are left in place. For release builds, this option defaults to 0
+    and calls to `assert()` function are compiled out. This option can be set
+    independently of `DEBUG`. It can also be used to hide any auxiliary code
+    that is only required for the assertion and does not fit in the assertion
+    itself.
+
 *   `ENABLE_PMF`: Boolean option to enable support for optional Performance
      Measurement Framework(PMF). Default is 0.
 
diff --git a/include/lib/stdlib/assert.h b/include/lib/stdlib/assert.h
index 5621f8c..1bcd1ea 100644
--- a/include/lib/stdlib/assert.h
+++ b/include/lib/stdlib/assert.h
@@ -34,30 +34,27 @@
  *	@(#)assert.h	8.2 (Berkeley) 1/21/94
  * $FreeBSD$
  */
-
-#include <sys/cdefs.h>
-
 /*
- * Unlike other ANSI header files, <assert.h> may usefully be included
- * multiple times, with and without NDEBUG defined.
+ * Portions copyright (c) 2017, ARM Limited and Contributors.
+ * All rights reserved.
  */
 
-#undef assert
-#undef _assert
+#ifndef _ASSERT_H_
+#define _ASSERT_H_
 
-#ifdef NDEBUG
-#define	assert(e)	((void)0)
-#define	_assert(e)	((void)0)
-#else
-#define	_assert(e)	assert(e)
+#include <sys/cdefs.h>
 
+#if ENABLE_ASSERTIONS
+#define	_assert(e)	assert(e)
 #define	assert(e)	((e) ? (void)0 : __assert(__func__, __FILE__, \
 			    __LINE__, #e))
-#endif /* NDEBUG */
+#else
+#define	assert(e)	((void)0)
+#define	_assert(e)	((void)0)
+#endif /* ENABLE_ASSERTIONS */
 
-#ifndef _ASSERT_H_
-#define _ASSERT_H_
 __BEGIN_DECLS
 void __assert(const char *, const char *, int, const char *) __dead2;
 __END_DECLS
+
 #endif /* !_ASSERT_H_ */
diff --git a/lib/stdlib/assert.c b/lib/stdlib/assert.c
index 3486e50..3c0bd16 100644
--- a/lib/stdlib/assert.c
+++ b/lib/stdlib/assert.c
@@ -32,15 +32,18 @@
 #include <debug.h>
 #include <platform.h>
 
-/*
- * This is a basic implementation. This could be improved.
- */
-void __assert (const char *function, const char *file, unsigned int line,
+void __assert(const char *function, const char *file, unsigned int line,
 		const char *assertion)
 {
+#if LOG_LEVEL >= LOG_LEVEL_INFO
+	/*
+	 * Only print the output if LOG_LEVEL is higher or equal to
+	 * LOG_LEVEL_INFO, which is the default value for builds with DEBUG=1.
+	 */
 	tf_printf("ASSERT: %s <%d> : %s\n", function, line, assertion);
 
 	console_flush();
+#endif
 
 	plat_panic_handler();
 }