The Ethereum ABI defines how arguments are encoded and passed when a method is called. But how are the arguments to the constructor encoded in the contract creation transaction which creates the smart contract?
According to the Ethereum Yellow Paper (section 4.2), the contract creation transaction does not have a data byte array where the arguments to method calls are placed. The contract creation only has the init byte array so the arguments to the constructor must go in there.
The init byte array is also where the byte code of the smart contract logic is placed.
The way that the Solidity compiler expects the constructor arguments to be passed is by appending the arguments to the byte code produced by the Solidity compiler. The arguments are formatted as defined in the Ethereum ABI. The arguments are then copied from the init byte array to the EVM memory through the
CODECOPY opcode with appropriate values on the stack. This is done when the byte code in the init byte array is actually run on the network.