def wrap_function(ctype, orig_ctype, func): # only care about non-variadic functions if they return wrappable types. # otherwise, we always care about manually wrapping variadic functions # and functions that don't return. if not ctype.is_variadic \ and not has_extension_attribute(orig_ctype, "noreturn"): #if not will_wrap_function(ctype.ret_type, []): return # don't wrap deprecated functions; the compiler will complain about them. if has_extension_attribute(orig_ctype, "deprecated"): return if not must_wrap([ctype.ret_type] + ctype.param_types): return # internal function #elif func.startswith("__"): # return O = OUT internal_ret_type = ctype.ret_type.base_type() suffix, is_void = "", False if isinstance(internal_ret_type, CTypeBuiltIn) \ and "void" == internal_ret_type.name: suffix, is_void = "_VOID", True variadic = "" if ctype.is_variadic: if ctype.param_types: variadic = ", " variadic += "..." arg_list = [] num_params = [0] def next_param(p): if p: return p else: num_params[0] += 1 return "_arg%d" % num_params[0] param_names = map(next_param, ctype.param_names) last_arg_name = "" for (arg_ctype, arg_name) in zip(ctype.param_types, param_names): if not arg_name: arg_name = "" last_arg_name = arg_name arg_list.append( pretty_print_type(arg_ctype, arg_name, lang="C++").strip(" ")) args = ", ".join(arg_list) # get an output string for the return type. ret_type = "" if not is_void: ret_type = pretty_print_type(ctype.ret_type, "", lang="C++").strip(" ") ret_type = " (%s), " % ret_type addr_check = "" if func.startswith("__"): addr_check = " && defined(DETACH_ADDR_%s)" % func # TODO: re-enable auto-wrapping of variadic functions? if ctype.is_variadic: return O("#if defined(CAN_WRAP_", func, ") && CAN_WRAP_", func, addr_check) O("#ifndef APP_WRAPPER_FOR_", func) O("#define APP_WRAPPER_FOR_", func) O("FUNCTION_WRAPPER", suffix, "(APP, ", func, ",", ret_type, "(", args, variadic, "), {") if ctype.is_variadic: O(" va_list args__;") O(" va_start(args__, %s);" % last_arg_name) # assignment of return value; unattributed_type is used in place of base type # so that we don't end up with anonymous structs/unions/enums. a, r_v = "", "" if not is_void: r_v = "ret" a = pretty_print_type(ctype.ret_type.unattributed_type(), r_v, "C++") + " = " for (arg_ctype, arg_name) in zip(ctype.param_types, param_names): pre_wrap_var(arg_ctype, arg_name, O, indent=" ") global VA_LIST_FUNCS va_func = "v%s" % func special = False if ctype.is_variadic and va_func in VA_LIST_FUNCS: O(" IF_KERNEL( auto ", va_func, "((decltype(::", va_func, ") *) DETACH_ADDR_", va_func, "); ) ") O(" ", a, va_func, "(", ", ".join(param_names + ["args__"]), ");") else: if ctype.is_variadic: special = True O(" // TODO: variadic arguments") O(" D( granary_fault(); )") O(" ", a, func, "(", ", ".join(param_names), ");") if ctype.is_variadic: O(" va_end(args__);") #O(" D( granary::printf(\"FUNCTION_WRAPPER(APP, %s) %s\\n\"); )" % (func, special and "*" or "")) if not is_void and not isinstance(ctype.ret_type.base_type(), CTypeBuiltIn): O(" RETURN_IN_WRAP(", r_v, ");") if not is_void: O(" return ", r_v, ";") O("})") O("#endif") O("#endif") O() O()
def wrap_function(ctype, orig_ctype, func): # only care about non-variadic functions if they return wrappable types. # otherwise, we always care about manually wrapping variadic functions # and functions that don't return. if not ctype.is_variadic \ and not has_extension_attribute(orig_ctype, "noreturn"): #if not will_wrap_function(ctype.ret_type, []): return # don't wrap deprecated functions; the compiler will complain about them. if has_extension_attribute(orig_ctype, "deprecated"): return if not must_wrap([ctype.ret_type] + ctype.param_types): return # internal function #elif func.startswith("__"): # return O = OUT internal_ret_type = ctype.ret_type.base_type() suffix, is_void = "", False if isinstance(internal_ret_type, CTypeBuiltIn) \ and "void" == internal_ret_type.name: suffix, is_void = "_VOID", True variadic = "" if ctype.is_variadic: if ctype.param_types: variadic = ", " variadic += "..." arg_list = [] num_params = [0] def next_param(p): if p: return p else: num_params[0] += 1 return "_arg%d" % num_params[0] param_names = map(next_param, ctype.param_names) last_arg_name = "" for (arg_ctype, arg_name) in zip(ctype.param_types, param_names): if not arg_name: arg_name = "" last_arg_name = arg_name arg_list.append(pretty_print_type(arg_ctype, arg_name, lang="C++").strip(" ")) args = ", ".join(arg_list) # get an output string for the return type. ret_type = "" if not is_void: ret_type = pretty_print_type(ctype.ret_type, "", lang="C++").strip(" ") ret_type = " (%s), " % ret_type addr_check = "" if func.startswith("__"): addr_check = " && defined(DETACH_ADDR_%s)" % func O("#if defined(CAN_WRAP_", func, ") && CAN_WRAP_", func, addr_check) O("#ifndef APP_WRAPPER_FOR_", func) O("#define APP_WRAPPER_FOR_", func) O("FUNCTION_WRAPPER", suffix, "(APP, ", func, ",", ret_type,"(", args, variadic, "), {") if ctype.is_variadic: O(" va_list args__;") O(" va_start(args__, %s);" % last_arg_name) # assignment of return value; unattributed_type is used in place of base type # so that we don't end up with anonymous structs/unions/enums. a, r_v = "", "" if not is_void: r_v = "ret" a = pretty_print_type(ctype.ret_type.unattributed_type(), r_v, "C++") + " = " for (arg_ctype, arg_name) in zip(ctype.param_types, param_names): pre_wrap_var(arg_ctype, arg_name, O, indent=" ") global VA_LIST_FUNCS va_func = "v%s" % func special = False if ctype.is_variadic and va_func in VA_LIST_FUNCS: O(" IF_KERNEL( auto ", va_func, "((decltype(::", va_func, ") *) DETACH_ADDR_", va_func,"); ) ") O(" ", a, va_func, "(", ", ".join(param_names + ["args__"]), ");") else: if ctype.is_variadic: special = True O(" // TODO: variadic arguments") O(" D( granary_fault(); )") O(" ", a, func, "(", ", ".join(param_names), ");") if ctype.is_variadic: O(" va_end(args__);") #O(" D( granary::printf(\"FUNCTION_WRAPPER(APP, %s) %s\\n\"); )" % (func, special and "*" or "")) if not is_void and not isinstance(ctype.ret_type.base_type(), CTypeBuiltIn): O(" RETURN_IN_WRAP(", r_v, ");") if not is_void: O(" return ", r_v, ";") O("})") O("#endif") O("#endif") O() O()
def wrap_function(ctype, orig_ctype, func): # only care about non-variadic functions if they return wrappable types. # otherwise, we always care about manually wrapping variadic functions # and functions that don't return. if not ctype.is_variadic \ and not has_extension_attribute(orig_ctype, "noreturn"): #if not will_wrap_function(ctype.ret_type, []): return # don't wrap deprecated functions; the compiler will complain about them. if has_extension_attribute(orig_ctype, "deprecated"): return if not must_wrap([ctype.ret_type] + ctype.param_types): return # internal function #elif func.startswith("__"): # return O = OUT internal_ret_type = ctype.ret_type.base_type() suffix, is_void = "", False if isinstance(internal_ret_type, CTypeBuiltIn) \ and "void" == internal_ret_type.name: suffix, is_void = "_VOID", True variadic = "" if ctype.is_variadic: if ctype.param_types: variadic = ", " variadic += "..." arg_list = [] num_params = [0] def next_param(p): if p: return p else: num_params[0] += 1 return "_arg%d" % num_params[0] param_names = map(next_param, ctype.param_names) last_arg_name = "" for (arg_ctype, arg_name) in zip(ctype.param_types, param_names): if not arg_name: arg_name = "" last_arg_name = arg_name arg_list.append(pretty_print_type(arg_ctype, arg_name, lang="C++").strip(" ")) args = ", ".join(arg_list) # get an output string for the return type. ret_type = "" if not is_void: ret_type = pretty_print_type(ctype.ret_type, "", lang="C++").strip(" ") ret_type = " (%s), " % ret_type addr_check = "" if func.startswith("__"): addr_check = " && defined(DETACH_ADDR_%s)" % func O("FUNCTION_WRAPPER", suffix, "(", func, ",", ret_type ,"(", args, variadic, "), {") # assignment of return value; unattributed_type is used in place of base type # so that we don't end up with anonymous structs/unions/enums. O("})") O("#endif") O("#endif") O() O()