blob: 0b909b889bc7ea078883388869451f5176cd345a [file] [log] [blame] [edit]
/*
* Copyright 2016 WebAssembly Community Group participants
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WABT_COMMON_H_
#define WABT_COMMON_H_
#include <assert.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <type_traits>
#include <vector>
#include "config.h"
#define WABT_FATAL(...) fprintf(stderr, __VA_ARGS__), exit(1)
#define WABT_ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
#define WABT_ZERO_MEMORY(var) \
WABT_STATIC_ASSERT( \
std::is_pod<std::remove_reference<decltype(var)>::type>::value); \
memset(static_cast<void*>(&(var)), 0, sizeof(var))
#define WABT_USE(x) static_cast<void>(x)
#define WABT_UNKNOWN_OFFSET (static_cast<uint32_t>(~0))
#define WABT_PAGE_SIZE 0x10000 /* 64k */
#define WABT_MAX_PAGES 0x10000 /* # of pages that fit in 32-bit address space */
#define WABT_BYTES_TO_PAGES(x) ((x) >> 16)
#define WABT_ALIGN_UP_TO_PAGE(x) \
(((x) + WABT_PAGE_SIZE - 1) & ~(WABT_PAGE_SIZE - 1))
#define PRIstringslice "%.*s"
#define WABT_PRINTF_STRING_SLICE_ARG(x) static_cast<int>((x).length), (x).start
#define WABT_DEFAULT_SNPRINTF_ALLOCA_BUFSIZE 128
#define WABT_SNPRINTF_ALLOCA(buffer, len, format) \
va_list args; \
va_list args_copy; \
va_start(args, format); \
va_copy(args_copy, args); \
char fixed_buf[WABT_DEFAULT_SNPRINTF_ALLOCA_BUFSIZE]; \
char* buffer = fixed_buf; \
size_t len = wabt_vsnprintf(fixed_buf, sizeof(fixed_buf), format, args); \
va_end(args); \
if (len + 1 > sizeof(fixed_buf)) { \
buffer = static_cast<char*>(alloca(len + 1)); \
len = wabt_vsnprintf(buffer, len + 1, format, args_copy); \
} \
va_end(args_copy)
#define WABT_ENUM_COUNT(name) \
(static_cast<int>(name::Last) - static_cast<int>(name::First) + 1)
#define WABT_DISALLOW_COPY_AND_ASSIGN(type) \
type(const type&) = delete; \
type& operator=(const type&) = delete;
namespace wabt {
enum class Result {
Ok,
Error,
};
#define WABT_SUCCEEDED(x) ((x) == Result::Ok)
#define WABT_FAILED(x) ((x) == Result::Error)
inline std::string WABT_PRINTF_FORMAT(1, 2)
string_printf(const char* format, ...) {
va_list args;
va_list args_copy;
va_start(args, format);
va_copy(args_copy, args);
size_t len = wabt_vsnprintf(nullptr, 0, format, args) + 1; // For \0.
std::vector<char> buffer(len);
va_end(args);
wabt_vsnprintf(buffer.data(), len, format, args_copy);
va_end(args_copy);
return std::string(buffer.data(), len - 1);
}
enum class LabelType {
Func,
Block,
Loop,
If,
Else,
First = Func,
Last = Else,
};
static const int kLabelTypeCount = WABT_ENUM_COUNT(LabelType);
struct StringSlice {
const char* start;
size_t length;
};
struct Location {
const char* filename;
int line;
int first_column;
int last_column;
};
/* matches binary format, do not change */
enum class Type {
I32 = -0x01,
I64 = -0x02,
F32 = -0x03,
F64 = -0x04,
Anyfunc = -0x10,
Func = -0x20,
Void = -0x40,
___ = Void, /* convenient for the opcode table in opcode.h */
Any = 0, /* Not actually specified, but useful for type-checking */
};
typedef std::vector<Type> TypeVector;
enum class RelocType {
FuncIndexLEB = 0, /* e.g. immediate of call instruction */
TableIndexSLEB = 1, /* e.g. loading address of function */
TableIndexI32 = 2, /* e.g. function address in DATA */
MemoryAddressLEB = 3,
MemoryAddressSLEB = 4,
MemoryAddressI32 = 5,
TypeIndexLEB = 6, /* e.g immediate type in call_indirect */
GlobalIndexLEB = 7, /* e.g immediate of get_global inst */
First = FuncIndexLEB,
Last = GlobalIndexLEB,
};
static const int kRelocTypeCount = WABT_ENUM_COUNT(RelocType);
struct Reloc {
Reloc(RelocType, size_t offset, uint32_t index, int32_t addend = 0);
RelocType type;
size_t offset;
uint32_t index;
int32_t addend;
};
/* matches binary format, do not change */
enum class ExternalKind {
Func = 0,
Table = 1,
Memory = 2,
Global = 3,
First = Func,
Last = Global,
};
static const int kExternalKindCount = WABT_ENUM_COUNT(ExternalKind);
struct Limits {
uint64_t initial;
uint64_t max;
bool has_max;
};
enum { WABT_USE_NATURAL_ALIGNMENT = 0xFFFFFFFF };
enum class LiteralType {
Int,
Float,
Hexfloat,
Infinity,
Nan,
};
struct Literal {
LiteralType type;
StringSlice text;
};
enum class NameSectionSubsection {
Function = 1,
Local = 2,
};
static WABT_INLINE char* wabt_strndup(const char* s, size_t len) {
size_t real_len = 0;
const char* p = s;
while (real_len < len && *p) {
p++;
real_len++;
}
char* new_s = new char[real_len + 1];
memcpy(new_s, s, real_len);
new_s[real_len] = 0;
return new_s;
}
static WABT_INLINE StringSlice dup_string_slice(StringSlice str) {
StringSlice result;
result.start = wabt_strndup(str.start, str.length);
result.length = str.length;
return result;
}
StringSlice empty_string_slice(void);
bool string_slice_eq_cstr(const StringSlice* s1, const char* s2);
bool string_slice_startswith(const StringSlice* s1, const char* s2);
StringSlice string_slice_from_cstr(const char* string);
bool string_slice_is_empty(const StringSlice*);
bool string_slices_are_equal(const StringSlice*, const StringSlice*);
void destroy_string_slice(StringSlice*);
Result read_file(const char* filename, char** out_data, size_t* out_size);
inline std::string string_slice_to_string(const StringSlice& ss) {
return std::string(ss.start, ss.length);
}
inline StringSlice string_to_string_slice(const std::string& s) {
StringSlice ss;
ss.start = s.data();
ss.length = s.length();
return ss;
}
bool default_source_error_callback(const Location*,
const char* error,
const char* source_line,
size_t source_line_length,
size_t source_line_column_offset,
void* user_data);
bool default_binary_error_callback(uint32_t offset,
const char* error,
void* user_data);
void init_stdio();
/* external kind */
extern const char* g_kind_name[];
static WABT_INLINE const char* get_kind_name(ExternalKind kind) {
assert(static_cast<int>(kind) < kExternalKindCount);
return g_kind_name[static_cast<size_t>(kind)];
}
/* reloc */
extern const char* g_reloc_type_name[];
static WABT_INLINE const char* get_reloc_type_name(RelocType reloc) {
assert(static_cast<int>(reloc) < kRelocTypeCount);
return g_reloc_type_name[static_cast<size_t>(reloc)];
}
/* type */
static WABT_INLINE const char* get_type_name(Type type) {
switch (type) {
case Type::I32:
return "i32";
case Type::I64:
return "i64";
case Type::F32:
return "f32";
case Type::F64:
return "f64";
case Type::Anyfunc:
return "anyfunc";
case Type::Func:
return "func";
case Type::Void:
return "void";
case Type::Any:
return "any";
default:
return nullptr;
}
}
} // namespace
#endif /* WABT_COMMON_H_ */