335 lines · plain
1%include <typemaps.i>2 3// FIXME: We need to port more typemaps from Python4 5//===----------------------------------------------------------------------===//6 7// In Lua 5.3 and beyond the VM supports integers, so we need to remap8// SWIG's internal handling of integers.9 10 11%define LLDB_NUMBER_TYPEMAP(TYPE)12 13// Primitive integer mapping14%typemap(in,checkfn="lua_isinteger") TYPE15%{ $1 = ($type)lua_tointeger(L, $input); %}16%typemap(in,checkfn="lua_isinteger") const TYPE&($basetype temp)17%{ temp=($basetype)lua_tointeger(L,$input); $1=&temp;%}18%typemap(out) TYPE19%{ lua_pushinteger(L, (lua_Integer) $1); SWIG_arg++;%}20%typemap(out) const TYPE&21%{ lua_pushinteger(L, (lua_Integer) $1); SWIG_arg++;%}22 23// Pointer and reference mapping24%typemap(in,checkfn="lua_isinteger") TYPE *INPUT($*ltype temp), TYPE &INPUT($*ltype temp)25%{ temp = ($*ltype)lua_tointeger(L,$input);26 $1 = &temp; %}27%typemap(in, numinputs=0) TYPE *OUTPUT ($*ltype temp)28%{ $1 = &temp; %}29%typemap(argout) TYPE *OUTPUT30%{ lua_pushinteger(L, (lua_Integer) *$1); SWIG_arg++;%}31%typemap(in) TYPE *INOUT = TYPE *INPUT;32%typemap(argout) TYPE *INOUT = TYPE *OUTPUT;33%typemap(in) TYPE &OUTPUT = TYPE *OUTPUT;34%typemap(argout) TYPE &OUTPUT = TYPE *OUTPUT;35%typemap(in) TYPE &INOUT = TYPE *INPUT;36%typemap(argout) TYPE &INOUT = TYPE *OUTPUT;37%typemap(in,checkfn="lua_isinteger") const TYPE *INPUT($*ltype temp)38%{ temp = ($*ltype)lua_tointeger(L,$input);39 $1 = &temp; %}40 41%enddef // LLDB_NUMBER_TYPEMAP42 43LLDB_NUMBER_TYPEMAP(unsigned char);44LLDB_NUMBER_TYPEMAP(signed char);45LLDB_NUMBER_TYPEMAP(short);46LLDB_NUMBER_TYPEMAP(unsigned short);47LLDB_NUMBER_TYPEMAP(signed short);48LLDB_NUMBER_TYPEMAP(int);49LLDB_NUMBER_TYPEMAP(unsigned int);50LLDB_NUMBER_TYPEMAP(signed int);51LLDB_NUMBER_TYPEMAP(long);52LLDB_NUMBER_TYPEMAP(unsigned long);53LLDB_NUMBER_TYPEMAP(signed long);54LLDB_NUMBER_TYPEMAP(long long);55LLDB_NUMBER_TYPEMAP(unsigned long long);56LLDB_NUMBER_TYPEMAP(signed long long);57LLDB_NUMBER_TYPEMAP(enum SWIGTYPE);58 59%apply unsigned long { size_t };60%apply const unsigned long & { const size_t & };61%apply long { ssize_t };62%apply const long & { const ssize_t & };63 64//===----------------------------------------------------------------------===//65 66// FIXME:67// Ideally all the typemaps should be revisited in a future SB API revision.68// Typemaps, usually, modifies the function signatures and might spawn69// different LLDB APIs across languages (C++, Python, Lua...).70// Historically, typemaps have been used to replace SWIG's deficiencies,71// but SWIG itself evolved and some API design choices are now redundant.72 73//===----------------------------------------------------------------------===//74 75// Typemap definitions to allow SWIG to properly handle char buffer.76 77// typemap for a char buffer78%typemap(in) (char *dst, size_t dst_len) {79 $2 = luaL_checkinteger(L, $input);80 if ($2 <= 0) {81 return luaL_error(L, "Positive integer expected");82 }83 $1 = (char *)malloc($2);84}85 86// SBProcess::ReadCStringFromMemory() uses a void*, but needs to be treated87// as char data instead of byte data.88%typemap(in) (void *char_buf, size_t size) = (char *dst, size_t dst_len);89 90// Also SBProcess::ReadMemory.91%typemap(in) (void *buf, size_t size) = (char *dst, size_t dst_len);92 93// Return the char buffer. Discarding any previous return result94%typemap(argout) (char *dst, size_t dst_len) {95 lua_pop(L, 1); // Blow away the previous result96 if ($result == 0) {97 lua_pushliteral(L, "");98 } else {99 lua_pushlstring(L, (const char *)$1, $result);100 }101 free($1);102 // SWIG_arg was already incremented103}104 105// SBProcess::ReadCStringFromMemory() uses a void*, but needs to be treated106// as char data instead of byte data.107%typemap(argout) (void *char_buf, size_t size) = (char *dst, size_t dst_len);108 109// Also SBProcess::ReadMemory.110%typemap(argout) (void *buf, size_t size) = (char *dst, size_t dst_len);111 112//===----------------------------------------------------------------------===//113 114// Typemap for handling a snprintf-like API like SBThread::GetStopDescription.115 116%typemap(in) (char *dst_or_null, size_t dst_len) {117 $2 = luaL_checkinteger(L, $input);118 if ($2 <= 0) {119 return luaL_error(L, "Positive integer expected");120 }121 $1 = (char *)malloc($2);122}123 124// Disable default type checking for this method to avoid SWIG dispatch issues.125//126// Problem: SBThread::GetStopDescription has two overloads:127// 1. GetStopDescription(char* dst_or_null, size_t dst_len)128// 2. GetStopDescription(lldb::SBStream& stream)129//130// SWIG generates a dispatch function to select the correct overload based on argument types.131// see https://www.swig.org/Doc4.0/SWIGDocumentation.html#Typemaps_overloading.132// However, this dispatcher doesn't consider typemaps that transform function signatures.133//134// In lua, our typemap converts GetStopDescription(char*, size_t) to GetStopDescription(int).135// The dispatcher still checks against the original (char*, size_t) signature instead of136// the transformed (int) signature, causing type matching to fail.137// This only affects SBThread::GetStopDescription since the type check also matches138// the argument name, which is unique to this function.139%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER) (char *dst_or_null, size_t dst_len) ""140 141%typemap(argout) (char *dst_or_null, size_t dst_len) {142 lua_pop(L, 1); // Blow away the previous result143 llvm::StringRef ref($1);144 lua_pushlstring(L, (const char *)$1, ref.size());145 free($1);146 // SWIG_arg was already incremented147}148 149//===----------------------------------------------------------------------===//150 151// Typemap for handling SBModule::GetVersion152 153%typemap(in) (uint32_t *versions, uint32_t num_versions) {154 $2 = 99;155 $1 = (uint32_t *)malloc(sizeof(uint32_t) * $2);156}157 158%typemap(argout) (uint32_t *versions, uint32_t num_versions) {159 uint32_t count = result;160 if (count >= $2)161 count = $2;162 lua_newtable(L);163 int i = 0;164 while (i++ < count) {165 lua_pushinteger(L, $1[i - 1]);166 lua_seti(L, -2, i);167 }168 SWIG_arg++;169 free($1);170}171 172//===----------------------------------------------------------------------===//173 174// Typemap for handling SBDebugger::SetLoggingCallback175 176%typemap(in) (lldb::LogOutputCallback log_callback, void *baton) {177 $1 = LLDBSwigLuaCallLuaLogOutputCallback;178 $2 = (void *)L;179 180 luaL_checktype(L, 2, LUA_TFUNCTION);181 lua_settop(L, 2);182 183 lua_pushlightuserdata(L, (void *)&LLDBSwigLuaCallLuaLogOutputCallback);184 lua_insert(L, 2);185 lua_settable(L, LUA_REGISTRYINDEX);186}187 188//===----------------------------------------------------------------------===//189 190// Typemap for handling SBEvent::SBEvent(uint32_t event, const char *cstr, uint32_t cstr_len)191 192%typemap(in) (const char *cstr, uint32_t cstr_len) {193 $1 = (char *)luaL_checklstring(L, $input, (size_t *)&$2);194}195 196// Typemap for handling SBProcess::PutSTDIN197 198%typemap(in) (const char *src, size_t src_len) {199 $1 = (char *)luaL_checklstring(L, $input, &$2);200}201 202// Typemap for handling SBProcess::WriteMemory, SBTarget::GetInstructions...203 204%typemap(in) (const void *buf, size_t size),205 (const void *data, size_t data_len) {206 $1 = (void *)luaL_checklstring(L, $input, &$2);207}208 209//===----------------------------------------------------------------------===//210 211// Typemap for handling char ** in SBTarget::LaunchSimple, SBTarget::Launch...212 213// It should accept a Lua table of strings, for stuff like "argv" and "envp".214 215%typemap(in) char ** {216 if (lua_istable(L, $input)) {217 size_t size = lua_rawlen(L, $input);218 $1 = (char **)malloc((size + 1) * sizeof(char *));219 int i = 0, j = 0;220 while (i++ < size) {221 lua_rawgeti(L, $input, i);222 if (!lua_isstring(L, -1)) {223 // if current element cannot be converted to string, raise an error224 lua_pop(L, 1);225 return luaL_error(L, "List should only contain strings");226 }227 $1[j++] = (char *)lua_tostring(L, -1);228 lua_pop(L, 1);229 }230 $1[j] = 0;231 } else if (lua_isnil(L, $input)) {232 // "nil" is also acceptable, equivalent as an empty table233 $1 = NULL;234 } else {235 return luaL_error(L, "A list of strings expected");236 }237}238 239%typemap(freearg) char ** {240 free((char *) $1);241}242 243%typecheck(SWIG_TYPECHECK_STRING_ARRAY) char ** {244 $1 = (lua_istable(L, $input) || lua_isnil(L, $input));245}246 247//===----------------------------------------------------------------------===//248 249// Typemap for file handles (e.g. used in SBDebugger::SetOutputFile)250 251%typemap(in) lldb::FileSP {252 luaL_Stream *p = (luaL_Stream *)luaL_checkudata(L, $input, LUA_FILEHANDLE);253 lldb::FileSP file_sp;254 file_sp = std::make_shared<lldb_private::NativeFile>(255 p->f, lldb_private::NativeFile::eOpenOptionWriteOnly, false);256 if (!file_sp->IsValid())257 return luaL_error(L, "Invalid file");258 $1 = file_sp;259}260 261%typecheck(SWIG_TYPECHECK_POINTER) lldb::FileSP {262 $1 = (lua_isuserdata(L, $input)) &&263 (luaL_testudata(L, $input, LUA_FILEHANDLE) != nullptr);264}265 266// Typemap for file handles (e.g. used in SBDebugger::GetOutputFileHandle)267 268%typemap(out) lldb::FileSP {269 lldb::FileSP sp = $1;270 if (sp && sp->IsValid()) {271 luaL_Stream *p = (luaL_Stream *)lua_newuserdata(L, sizeof(luaL_Stream));272 p->closef = &LLDBSwigLuaCloseFileHandle;273 p->f = sp->GetStream();274 luaL_setmetatable(L, LUA_FILEHANDLE);275 SWIG_arg++;276 }277}278 279//===----------------------------------------------------------------------===//280 281// Typemap for SBData::CreateDataFromUInt64Array, SBData::SetDataFromUInt64Array ...282 283%typemap(in) (uint64_t* array, size_t array_len),284 (uint32_t* array, size_t array_len),285 (int64_t* array, size_t array_len),286 (int32_t* array, size_t array_len),287 (double* array, size_t array_len) {288 if (lua_istable(L, $input)) {289 // It should accept a table of numbers.290 $2 = lua_rawlen(L, $input);291 $1 = ($1_ltype)malloc(($2) * sizeof($*1_type));292 int i = 0, j = 0;293 while (i++ < $2) {294 lua_rawgeti(L, $input, i);295 if (!lua_isnumber(L, -1)) {296 // if current element cannot be converted to number, raise an error297 lua_pop(L, 1);298 return luaL_error(L, "List should only contain numbers");299 }300 $1[j++] = ($*1_ltype) lua_tonumber(L, -1);301 lua_pop(L, 1);302 }303 } else if (lua_isnil(L, $input)) {304 // "nil" is also acceptable, equivalent as an empty table305 $1 = NULL;306 $2 = 0;307 } else {308 // else raise an error309 return luaL_error(L, "A list of numbers expected.");310 }311}312 313%typemap(freearg) (uint64_t* array, size_t array_len),314 (uint32_t* array, size_t array_len),315 (int64_t* array, size_t array_len),316 (int32_t* array, size_t array_len),317 (double* array, size_t array_len) {318 free($1);319}320 321//===----------------------------------------------------------------------===//322 323// Typemap for SBCommandReturnObject::PutCString324 325%typemap(in) (const char *string, int len) {326 if (lua_isnil(L, $input)) {327 $1 = NULL;328 $2 = 0;329 } else {330 $1 = (char *)luaL_checklstring(L, $input, (size_t *)&$2);331 }332}333 334//===----------------------------------------------------------------------===//335