public void apply() throws DuplicateNameException, InvalidInputException {

		List<Integer> spillVars = new ArrayList<>();

		// for each parameter in the function's param list, calculate custom storage for it
		List<Parameter> newParams = new ArrayList<>();
		for (ParameterDefinition param : newSignature.getArguments()) {
			DataType dt = param.getDataType();
			ParameterImpl newParam = null;
			boolean isClosure =
				isClosureContext(param) && storageAllocator.getClosureContextRegister() != null;

			List<Register> regStorage = isClosure
					? List.of(storageAllocator.getClosureContextRegister())
					: storageAllocator.getRegistersFor(dt);
			if (regStorage != null && !regStorage.isEmpty()) {
				newParam =
					createParamWithCustomStorage(param.getName(), param.getDataType(), regStorage);
				if (!isClosure) {
					spillVars.add(param.getOrdinal());
				}
				if (dt instanceof Structure &&
					newParam.getVariableStorage().size() != dt.getLength()) {
					MarkupSession.logWarningAt(program, func.getEntryPoint(),
						"Known storage allocation problem: param %s register allocation for structs missing inter-field padding."
								.formatted(newParam.toString()));
				}
			}
			else {
				newParam = createParamWithStackStorage(param.getName(), param.getDataType());
			}
			newParams.add(newParam);
		}

		// prepare for calculating return result custom storage
		storageAllocator.alignStack();
		storageAllocator.resetRegAllocation();

		DataType returnDT = newSignature.getReturnType();
		List<LocalVariable> returnResultAliasVars = new ArrayList<>();
		ReturnParameterImpl returnParam = returnDT != null
				? updateReturn(returnResultAliasVars)
				: null;

		storageAllocator.alignStack();

		// Check if the func's current params / storage is same
		if (!isEquivStorage(newParams, returnParam)) {
			// modify the function's signature to match the new info.
			// First try just changing the callingconv.  If that doesn't produce the correct
			// storage, then resort to forcing the storage
			func.updateFunction(newCallingConv, returnParam, newParams,
				FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS, true, SourceType.IMPORTED);
			if (!isEquivStorage(newParams, returnParam)) {
				func.updateFunction(newCallingConv, returnParam, newParams,
					FunctionUpdateType.CUSTOM_STORAGE, true, SourceType.IMPORTED);
			}
		}

		// Remove any old local vars that are in the callers stack instead of in the local stack area
		for (Variable localVar : func.getLocalVariables()) {
			if (localVar.isStackVariable() && !isInLocalVarStorageArea(localVar.getStackOffset())) {
				func.removeVariable(localVar);
			}
		}

		// For any parameters that were passed as registers, the golang caller pre-allocates
		// space on the stack for the parameter value to be used when the register is overwritten.
		// Ghidra decompilation results are improved if those storage locations are covered
		// by variables that we create artificially.
		for (int paramOrdinal : spillVars) {
			Parameter param = func.getParameter(paramOrdinal);
			DataType paramDT = param.getFormalDataType();
			long stackOffset = storageAllocator.getStackAllocation(paramDT);
			Varnode stackVarnode =
				new Varnode(program.getAddressFactory().getStackSpace().getAddress(stackOffset),
					paramDT.getLength());
			VariableStorage varStorage = new VariableStorage(program, List.of(stackVarnode));
			String paramName = param.getName();
			if (paramName == null) {
				paramName = SymbolUtilities.getDefaultParamName(paramOrdinal);
			}
			LocalVariableImpl localVar =
				new LocalVariableImpl(paramName + "_spill", 0, paramDT, varStorage, program);

			// TODO: needs more thought
			func.addLocalVariable(localVar, SourceType.IMPORTED);
		}

		for (LocalVariable returnResultAliasVar : returnResultAliasVars) {
			func.addLocalVariable(returnResultAliasVar, SourceType.IMPORTED);
		}

		if (newSignature.hasNoReturn()) {
			func.setNoReturn(true);
		}
	}
Utility class that fixes golang function parameter storage using each function's current
parameter list (formal info only) as starting information.

TODO: verify GoFuncData.argsize property against what we calculate here
Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/GoFunctionFixup.java